Newbie questions, migrating from c++

G

gg500

Thanks, that seems is the correct way. However I get those warnings
which I have mentioned and I have to add the weird condition not to
receive warning:

/^(\s+)/;
$i=defined ($1) ? length($1) : 0;

If I write:

/^(\s+)/;
$i=length($1);

I get "Use of uninitialized value in length..."
 
M

Matt Garrish

Just to correct myself, my space counting code does not work. But I
tried this and it did work:
$i=1;while (/^ {$i}/) {++$i;}--$i;
But this didn't work:
$i=0;while (/^ {$i+1}/) {++$i;}
which needless to say I do not understand.

Both are ugly, in my opinion, since you keep trying the regex until it
fails:

s/^(\s+)/print length($1)/e;

Also, your second code snippet doesn't work because you can't perform
addition within a matching regex like that (only interpolation, so your code
becomes /^ {1 + 0}/, for example, and never matches).

Matt
 
P

Paul Lalli

Thanks, that seems is the correct way. However I get those warnings
which I have mentioned and I have to add the weird condition not to
receive warning:

/^(\s+)/;
$i=defined ($1) ? length($1) : 0;

If I write:

/^(\s+)/;
$i=length($1);

I get "Use of uninitialized value in length..."

That's because you snipped a very important part of the code:

if(/^(\s+)/) {
print length($1),"\n";
}

You should never ever use $1, $2, etc without ensuring that the pattern
match succeeded. A better way to write this might be:

$len = (/^(\s+)/ ? length($1) : 0);
print "$len space characters start the string\n";

Paul Lalli
 
J

Joe Smith

If I write "split /\./, $ENV(REMOTE_ADDR)" I get warning about using
undefined variable, so without knowing how exactly I should proceed I
have written abundant amount of lines like "defined $ENV{REMOTE_ADDR}

You need to use the correct punctuation.
$ENV is not the same a %ENV.
$ENV(function_arguments) is not the same as $ENV{hash_key}.
It must have taken me 10 hours to try to get information how to refer
single byte (char) in "string/array"

You'll find this spelled out in any decent book on Perl.

Typically perl programs process strings using regular expressions
instead of one character at a time.
migrating from c++

Use the command
perldoc perltrap
and read the section "C programmers should take note of ...".

-Joe
 
S

Sherm Pendley

Thanks, that seems is the correct way. However I get those warnings
which I have mentioned and I have to add the weird condition not to
receive warning:

/^(\s+)/;
$i=defined ($1) ? length($1) : 0;

$1 is only valid if the preceding match succeeded. If you want to avoid
the defined(), you could write it like this:

my $i = (/^(\s+)/) ? length($1) : 0;

You could also avoid the call to length(). Just use the offset within
the string at the end of the match, which is in @+:

my $i = (/^\s+/) ? $+[0] : 0;

sherm--
 
M

Matt Garrish

Thanks, that seems is the correct way. However I get those warnings
which I have mentioned and I have to add the weird condition not to
receive warning:

/^(\s+)/;
$i=defined ($1) ? length($1) : 0;

If I write:

/^(\s+)/;
$i=length($1);

I get "Use of uninitialized value in length..."

They're called warnings because that's all they are. If the string has no
spaces at the beginning of it, nothing is assigned to $1 and so you get a
warning that you're calling the length function on an undefined value. If it
really bothers you, turn off the warnings for that part of your code. Most
people would do something like the following if it really matters if $1 gets
assigned to:

my ($cnt) = ($string =~ /^(\s+)/);

if ($cnt) { ... }

That way you don't execute code you don't want executed.

Matt
 
G

gg500

Paul said:
You should never ever use $1, $2, etc without ensuring that the pattern
match succeeded. A better way to write this might be:

Ok, thanks. I understand now. I must study what other similar cases of
warnings this explains (probably most of them).
 
J

Joe Smith

Just to correct myself, my space counting code does not work. But I
tried this and it did work:
$i=1;while (/^ {$i}/) {++$i;}--$i;
But this didn't work:
$i=0;while (/^ {$i+1}/) {++$i;}
which needless to say I do not understand.

That's not an appropriate use of {} in a regular expression.
Use parentheses inside the regex to pick up a desired substring:

$i = /(^ *)/ ? length $1 : 0;

-Joe
 
G

Gunnar Hjalmarsson

Sherm said:
In your example, you tried to read the environment variable
REMOTE_ADDR. That implies that you're writing a CGI script and you
want the remote host address. In that case, the normal way to get it
is to call the remote_host() method in CGI.pm.

remote_host() is not equivalent to $ENV{REMOTE_ADDR}, so that method is
reasonably not "normal" if you are after the REMOTE_ADDR env. variable.

Besides, if it had been a method that only returned an environment
variable, personally I would have found it difficult to see the point
with it.
 
K

Kåre Olai Lindbach

Thanks, that seems is the correct way. However I get those warnings
which I have mentioned and I have to add the weird condition not to
receive warning:

/^(\s+)/;
$i=defined ($1) ? length($1) : 0;

If I write:

/^(\s+)/;
$i=length($1);

I get "Use of uninitialized value in length..."

That's why I put the regex-match in an if-statement, if it doesn't
match, 'number of whitespaces first' are considered zero, or whatever
you are trying to achieve.
I would not trust $n values unless matched in the regex. If you later
loop through several lines you want to count for starting spaces, you
will get last line's value if current line has no starting spaces,
unless you deliberately set a counter to 0, or use an if-statement.

If things aren't working correctly with 'use warnings;' and 'use
strict;', it is because something is programmed wrong...

Your way is one way to make a printable output when $1 is not set
(un-initialized).

Another way:

# Untested!

use strict;
use warnings;

my $string = ' string with whitespaces first';

my $start_space_counter = 0;
if($string =~ /^(\s+)/) {
$start_space_counter = length($1);
}

print "Number of whitespaces first: $start_space_counter\n";

Yet Another way:

# Untested!

use strict;
use warnings;

my $string = ' string with whitespaces first';

if($string =~ /^(\s+)/) {
print 'Number of whitespaces first:', length($1), "\n";
}
else
{
print "No whitespaces first\n";
}


It is up to you to decide what to achieve!
 
A

Arndt Jonasson

Paul Lalli said:
That's because you snipped a very important part of the code:

if(/^(\s+)/) {
print length($1),"\n";
}

You should never ever use $1, $2, etc without ensuring that the
pattern match succeeded. A better way to write this might be:

$len = (/^(\s+)/ ? length($1) : 0);
print "$len space characters start the string\n";

For some reason I don't get the mentioned warnings in my perl 5.005;
maybe more modern perls do. I do get a warning if I try to print $1.

But why not do

/^(\s*)/;
$i=length($1);

in this case? The match is guaranteed to succeed (isn't it?), and the
number 0 is not treated as a special case.
 
A

Arndt Jonasson

If I write "split /\./, $ENV(REMOTE_ADDR)" I get warning about using
undefined variable, so without knowing how exactly I should proceed I
have written abundant amount of lines like "defined $ENV{REMOTE_ADDR} ?
$ENV{REMOTE_ADDR} : """. Obviously I do not understand the
fundamentals, so could you please explain what I do wrong since I get
myself into this situation?

If your aim is to avoid repeating code, you can use an auxiliary variable:

$e = $ENV{REMOTE_ADDR};
$e = "" unless defined $e;

Or you can write a subroutine to obtain a value, defaulting if needed
(not tested):

sub getvar {
my ($name, $default) = @_;
defined $ENV{$name} ? $ENV{$name} : $default;
}

.... = getvar("REMOTE_ADDR", "");

Others have suggested using packages from CPAN. Studying the
source code for them may give you insights on how to write similar
code yourself.
 
M

Michael Carman

If you honestly didn't recognize his reply as arrogant then I suggest
you take another look.

If that post really offended you I suggest you leave this group and
don't return until you've grown a thicker skin. Honestly, I do.
Otherwise this will just degenerate into yet another "why is everybody
in this newsgroup so !%@*#$ rude?" threads that benefit no one.

Many (most) of the postings here are very direct, even blunt. It's a
matter of efficiency (this is a high-volume newsgroup) not rudeness or
arrogance. If you can't accept that, this will seem like a very hostile
place. If you can, it's wonderfully helpful and instructive.

-mjc
 
A

Arndt Jonasson

Michael Carman said:
If that post really offended you I suggest you leave this group and
don't return until you've grown a thicker skin. Honestly, I do.
Otherwise this will just degenerate into yet another "why is everybody
in this newsgroup so !%@*#$ rude?" threads that benefit no one.

I think the way to grow a thicker skin, if that's what one wants to
do, is to participate in the skin-beating process, not to
retreat. That means using this group for what it's meant for, of
course: discussing Perl, and not so much discussing whether the
questions posed are a model of clarity. (Sorry for doing $#thread++.)
 
M

Matt Garrish

Dave Weaver said:
Yuk! That seems quite convoluted, and also needlessly destroys your
source string:

I read too much into his post, it seems. I was under the impression that he
wanted to remove and count the whitespace. And granted, in looking back that
is one ugly regex. Must have been having one big brain fart when I wrote
that... : )

Matt
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,164
Messages
2,570,898
Members
47,439
Latest member
shasuze

Latest Threads

Top