Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl-Sensitive Sunglasses
 
PerlMonks  

Eliminating substr warnings

by ezekiel (Pilgrim)
on Aug 13, 2004 at 00:41 UTC ( [id://382515]=perlquestion: print w/replies, xml ) Need Help??

ezekiel has asked for the wisdom of the Perl Monks concerning the following question:

I have a piece of code that gathers a set of substrings of fixed length from a longer string, thus:

my $i = 0; my $size = 10; while (my $substring = substr($string, $i, $size)) { push (@substrings, $substring); $i += $size }

This works fine, except that if the size of the segment does not evenly divide the size of the string, getting the last segment results in a warning message: "substr outside of string"

While this doesn't hurt anything, it offends my sense of order to see warnings like this where everything is working correctly :-) I could rewrite the code to use a for loop after working out the number of substrings based on the length of the string and the size of the substring, but I find this rather awkward and inelegant

Any suggestions for an elegant solution to this problem that avoids the error messages?

Replies are listed 'Best First'.
Re: Eliminating substr warnings
by Zaxo (Archbishop) on Aug 13, 2004 at 00:53 UTC

    You know that your usage is ok, so there's no objection to just turning off the warning. I'll show a trick for eliminating some temporary variables, too.

    my @substrings; { my $size = 10; no warnings 'substr'; push @substrings, substr($string, 0, $size, '') while $string; }
    If you want nondestructive treatment of $string, you can make a copy inside the curlies and work on that.

    Update: Here's yet another way to do it in 5.8+,

    my @substrings = do { local $/ = \10; open my $fh, '<', \$string; <$fh> };

    After Compline,
    Zaxo

        Perl stuffs parens around the whole thing (with /g), according to perlop:
        my @substrings = $string =~ /.{1,10}/gs;
        Two bytes saved. 189 bytes of bandwidth used.
Re: Eliminating substr warnings
by Aristotle (Chancellor) on Aug 13, 2004 at 03:00 UTC
    @substr = unpack "A$size" x ( 1 + length( $str ) / $size ), $str;

    Or maybe

    @substr = unpack "A$size" x POSIX::ceil( length( $str ) / $size ), $st +r;

    Makeshifts last the longest.

      I find this particularly useful:
      print join ",", unpack("(A3)*", "foobarbazi"), "\n"; __END__ foo,bar,baz,i
      It doesn't work in 5.6.1, but does in 5.8.

      thor

      Feel the white light, the light within
      Be your own disciple, fan the sparks of will
      With all of us waiting, your kingdom will come

Re: Eliminating substr warnings
by saberworks (Curate) on Aug 13, 2004 at 01:02 UTC
    Here's my take (which doesn't require turning off warnings):
    use strict; use warnings; my $i = 0; my $size = 10; my $string = 'some long string'; my @substrings; my $len = length($string); while($i <= $len) { push(@substrings, substr($string, $i, $size)); $i += $size; } $" = "\n"; print "@substrings\n";
    UPDATE: copied the "remove temp vars" from above posts.
      Density to time conversion:

      If you are as slow as I am, you may be wondering why this works and the original produced a warning.

      It's becuase the original produced the warning _after_ the last non-empty string was extracted. No warning is produced when the offset is equal to the string length, hence no warning when the length is a multiple of $size

      This is a good place for map:
      use warnings; use strict; my $str = 'abcdefghijklmnopqrstuvwxyz'; my $size = 10; my @subs = map substr($str, $_*$size, $size), 0..(length($str)-1)/$siz +e; print join("\n", @subs), "\n";

      Caution: Contents may have been coded under pressure.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://382515]
Approved by saberworks
Front-paged by broquaint
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others about the Monastery: (7)
As of 2024-03-28 21:43 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found