snape has asked for the wisdom of the Perl Monks concerning the following question:
hi,
I am new to perl programming and have a doubt on checking the length and chomp of the scalar variable. My code is as follows :-
#!/usr/bin/perl -w
use strict;
use warnings;
print "Enter the string =";
my $str = <STDIN>;
print "Enter the size =";
my $n = <STDIN>;
print "The Length of the string = ",length($str);
if ($n <= length($str)){
my $x = pretty_print($str,$n);
print "\nThe substring is = ",$x;
}
else{
print"\nThe length of the string is shorter than the size ";
}
sub pretty_print{
my ($dna,$len) = @_;
my $substring = substr($dna,0,$len);
return $substring;
}
When I am trying to run it. For ex:
Enter the string =snape
Enter the size =4
The Length of the string = 6
The substring is = snap
I am not sure why I am getting my length as 6 and not 5. I have tried with various examples but I am getting the length as one more than the actual length.
Also, when I am trying chomp the $str after the 7th line, I am getting the length as 1.
Can you please let me know the reasons regarding it ?
Thanks.
Re: Length and Chomp ??
by Tanktalus (Canon) on Aug 18, 2009 at 20:46 UTC
|
The code my $str = <STDIN>; graps "snape\n" - it includes the newline. That's the extra character. It's often helpful to print out your string, but do so in a way that shows hidden whitespace. I usually do it like this: print "str = [$str]\n"; - this puts brackets around it so that I can see if there are spaces or newlines at the end.
If I add chomp after the input for $str, I'm not getting any problem - I think you might be calling it as $str = chomp $str which is wrong. Just call chomp $str; like this:
#!/usr/bin/perl -w
use strict;
use warnings;
print "Enter the string =";
my $str = <STDIN>;
chomp $str; #### here is the call to chomp
print "Enter the size =";
my $n = <STDIN>;
print "The Length of the string = ",length($str);
if ($n <= length($str)){
my $x = pretty_print($str,$n);
print "\nThe substring is = ",$x;
}
else{
print"\nThe length of the string is shorter than the size ";
}
sub pretty_print{
my ($dna,$len) = @_;
my $substring = substr($dna,0,$len);
return $substring;
}
So close :-) | [reply] [d/l] [select] |
|
thanks everyone for the replies..
| [reply] |
Re: Length and Chomp ??
by kennethk (Abbot) on Aug 18, 2009 at 20:49 UTC
|
The length issue you encountering comes about because the string you input is terminated with the newline character (\n), hence its length is 5 visible characters plus the newline. If you print $str, you will see the cursor advance a line. You should be able to fix it by inserting the following line after line 7:
chomp $str;
However, it seems like you already knew that, so I can only assume you are using chomp wrong. Since you say that your string ends up with a length of 1, I'd wager your code is
$str = chomp $str; #Wrong!
chomp magically acts upon the arguments and does not require you to reassign. | [reply] [d/l] [select] |
Re: Length and Chomp ??
by lostjimmy (Chaplain) on Aug 18, 2009 at 20:51 UTC
|
The reason you get 6 instead of 5 is because the value of $str is "snape\n". That newline is the sixth character.
I imagine that what you were doing with chomp was something like $str = chomp $str. This is incorrect. chomp will return the number of newlines removed from the end of the string, so you actually end up assigning "1" to $str, which indeed does have a length of 1.
| [reply] [d/l] [select] |
Re: Length and Chomp ??
by biohisham (Priest) on Aug 18, 2009 at 21:01 UTC
|
the length function returns the length (in bytes), your code is fine but you haven't chomped the new-line character (\n) which is embedded into the string the moment you press the return key.
The Return key press would be treated as part of the input and you have to trim it using chomp before going further.
chomp after the 7th line worked just fine for me!!!
use strict;
use warnings;
print "Enter the string =";
my $str = <STDIN>;
chomp $str;
print "Enter the size =";
my $n = <STDIN>;
chomp $n;
Excellence is an Endeavor of Persistence.
Chance Favors a Prepared Mind.
| [reply] [d/l] |
|
the length function returns the length (in bytes)
No, it does not. It returns the number of characters found in the argument (or $_ when called without an argument). See length.
Note that length counts every character, including control characters like CR, LF, and TAB, and not just printable characters.
Alexander
--
Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so". ;-)
| [reply] [d/l] |
|
| [reply] [d/l] |
|
Re: Length and Chomp ??
by vitoco (Hermit) on Aug 18, 2009 at 21:48 UTC
|
I am not sure why I am getting my length as 6 and not 5.
Sometimes, usually on DOS/Windows boxes, the "newline" from input has length of 2 bytes: CR (carriage return or "\r") and LF (line feed or "\n"). chomp eats both at the same time.
| [reply] [d/l] [select] |
|
| [reply] |
|
>ver
Microsoft Windows XP [Version 5.1.2600]
>perl -le"print length $/"
1
>perl -le"$,=' '; print map { uc unpack 'H*', $_ } $/=~/./sg"
0A
The reason this isn't a problem is that the PerlIO layer :crlf is used by default in Windows, and that layer converts CRLF to LF on read and LF to CRLF on write.
>>foo echo foo
>debug foo
-rcx
CX 0005
:
-d100 l5
0B0B:0100 66 6F 6F 0D 0A foo..
-q
>perl -le"print length <>" foo
4
>perl -le"$,=' '; print map { uc unpack 'H*', $_ } <>=~/./sg" foo
66 6F 6F 0A
Builds of Perl without PerlIO (i.e. before 5.8) use the underlying C library, and it does the same thing.
| [reply] [d/l] [select] |
Re: Length and Chomp ??
by Marshall (Canon) on Aug 19, 2009 at 07:57 UTC
|
Some wise Monks have shown what length($x) does.
I will show how to use this in a command line application.
First, what starts it and ends it goes right at the front!
We prompt for some input (the string) and give a graceful way to
stop (like Q, q, quit QUIT).
After that part, we re-prompt without error message if input line is blank.
Then we clean up the input line as users often put spaces around things.
This part along the way cleans up all this "\n" stuff.
Now we enter the 2nd level prompt for the "size".
Same sort of things happen... but we detect and report and re-prompt
if something isn't quite right.
I could have written the unless() as an if(). That is a matter of choice
and style. However, I do think that the way that I indent these clauses
is very good (my opinion). I believe that the "lining up" and spacing of
this makes a difference. You can do it this way with either "unless" or "if".
Then we come to the "print". That print won't fail mainly because we
know that $size is "good".
This code is pretty typical of UI code...lots of code that finally gets
around to a few statements that actually "do something".
Oh, I think it is worthy of notice that there aren't any tricky <CR><LF> vs just <LF> things
in the code below.
#!/usr/bin/perl -w
use strict;
while ( (print "Enter the string(or Quit): "),
(my $line = <STDIN>) !~ /^\s*q(uit)?\s*$/i
)
{
next if ($line =~ m/^\s*$/); #re-prompt if blank line
$line =~ s/^\s*//; #delete leading spaces
$line =~ s/\s$//; #delete trailing spaces
print "Enter the Sub-string size: ";
my $size = (<STDIN>);
unless( ($size =~ m/^\s*\d\s*$/) #only single digit
&& (length($line) >= $size) #only valid context
)
{
print "Invalid size, must be a single positive digit\n";
print " and less than or equal to: ",length($line),"\n";
next;
}
print "output: ",substr($line,0,$size),"\n";
}
__END__
Example Output:
C:\TEMP>perlcommand.pl
Enter the string(or Quit): asdf
Enter the Sub-string size: 8
Invalid size, must be a single positive digit
and less than or equal to: 4
Enter the string(or Quit): asdf
Enter the Sub-string size: -23
Invalid size, must be a single positive digit
and less than or equal to: 4
Enter the string(or Quit): asdf
Enter the Sub-string size: 2
output: as
Enter the string(or Quit): assf
Enter the Sub-string size: 4
output: assf
Enter the string(or Quit): q
| [reply] [d/l] |
Re: Length and Chomp ??
by sanku (Beadle) on Aug 21, 2009 at 12:55 UTC
|
hi,
In perl normally <STDIN> will have a single white space at the end of the input value to remove it we can use the chomp() function. So, if you include chomp() function in your code then it will show the correct length. | [reply] |
|
|