Beefy Boxes and Bandwidth Generously Provided by pair Networks
Come for the quick hacks, stay for the epiphanies.
 
PerlMonks  

Uninitialized value in substr command

by lmtaylor (Novice)
on Aug 20, 2014 at 21:09 UTC ( [id://1098163]=perlquestion: print w/replies, xml ) Need Help??

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

Hello. I'm trying to take a very large array and re-format it. The initial array looks something like this:

>123

ABD

CEF

GHI

>456

JKL

MNO

>789

That's obviously simplified, but that's the idea. I want to join the elements between the two lines that begin with '>' and then get rid of the lines that begin with the '>', so my final array looks something like this:

ABDCEFGHI

JKLMNO

Here is the code I've written to do it. My problem is, every time I run it, I get a million errors that all say "Use of uninitialized value in substr at line 19." But I can't figure out what value it's talking about.

#!/usr/bin/perl -w my @contigfile = (">37","ABC","DEF","GHI","JKL","MNO","PQR","STU","VWX +","YZ",">38"); my $element1 = 0; my $element2 = 0; # print @contigfile; # print substr($contigfile[$element1],0,1); # print $contigfile[$element1]; while ($contigfile[$element1]){ if (substr($contigfile[$element1], 0, 1) eq '>'){ do { ++$element2; } until (substr($contigfile[$element2], 0, 1) eq '>'); $new = join('',@contigfile[($element1 + 1)..($element2 - 1)]); splice @contigfile, $element1, $element2, "$new"; ++$element1; $element2 = $element1; } } print @contigfile; exit;

I wrote this code to test my method before implementing it in my real program, which will take the array in from an input file. Only I can't figure out what this error is talking about. The commented out print commands work just fine. Does anyone see something that I'm missing?

Thank you so much for your help!

- Lisa

Replies are listed 'Best First'.
Re: Uninitialized value in substr command
by hippo (Bishop) on Aug 20, 2014 at 21:28 UTC

    $element2 at least is running away and therefore you are trying to read beyond the end of @contigfile in your substr call. Hence the warning message.

    If you must do it using this algorithm (and TIMTOWTDI but it wouldn't have been my choice) it would be wise to test that both $element1 and $element2 are not outside the bounds of the array. I'd also suggest you use strict.

      Thank you for your help! What does TIMTOWTDI mean?
        TIMTOWTDI is one of the Perl mottoes: "there is more than one way to do it."
Re: Uninitialized value in substr command
by Laurent_R (Canon) on Aug 20, 2014 at 21:27 UTC
    Well, if the array already exists, maybe try this (untested):
    my $string = ""; my @new_array; for my $item (@contigfile) { if ( $item =~ /^>\d) { push @new_array, $string unless $string eq ""; $string = ""; } else { $string .= $item; } } push @new_array, $string; # takes care of the last element
    If you have a file, you should probably avoid using a temporary array (at least if you file is big), but rather do essentially the same thing directly in a while loop reading the file:
    my $string = ""; while (my $line = <$input_fh>) { chomp $line; if ( $line =~ /^>\d) { push @new_array, $string unless $string eq "";; $string = ""; } else { $string .= $line; } } push @new_array, $string; # take care of the last element
    Update: fixed the typo indicated by Lotus1 (in the post just below) in the regex (I had inadvertently forgotten the '>'). Thanks to Lotus1.

      Laurent_R: I tested your code and got it working after fixing a typo in your regex.

          if ( $item =~ /^>\d/ ) {
      Thanks! I had to look up a few bits of your code to see what they meant, but now that I have I see that's a smart way to do it.
Re: Uninitialized value in substr command
by Anonymous Monk on Aug 20, 2014 at 21:53 UTC
    Here is the code I've written to do it. My problem is, every time I run it, I get a million errors that all say "Use of uninitialized value in substr at line 19." But I can't figure out what value it's talking about.
    Why, it's obvious.
    do { ++$element2; } until (substr($contigfile[$element2], 0, 1) eq '>');

    If $configfile[$element2] yields undef, the loop will never stop. Because substr( undef, 0,  1 ) eq '>' is never true.

    perl -we 'do { print "hello\n" } until substr( undef, 0, 1 ) eq ">"' hello Use of uninitialized value in substr at -e line 1. hello Use of uninitialized value in substr at -e line 1. hello Use of uninitialized value in substr at -e line 1. hello Use of uninitialized value in substr at -e line 1. hello ...
Re: Uninitialized value in substr command
by Anonymous Monk on Aug 20, 2014 at 23:04 UTC
    "Use of uninitialized value in substr at line 19." But I can't figure out what value it's talking about.

    Try adding use diagnostics; at the top of your program, you'll get a slightly longer explanation of errors and warnings. In this case the "uninitialized" warning means that one of the variables used had a value of undef, which happens e.g. when the variable has never been assigned anything, when you try to access array elements that you don't exist, or when the variable has been explicitly assigned undef at some point (see Declarations and undef). Also, another tool from the Basic debugging checklist is Data::Dumper, which makes it much easier to see your data structures (including undef). In this case you could have written print Dumper(\@contigfile,$element1,$element2); to see the current values of those variables.

Re: Uninitialized value in substr command
by choroba (Cardinal) on Aug 21, 2014 at 07:48 UTC
    In your script, the >456 header is missing before the second sequence. Here's how I would solve your task without BioPerl:
    #!/usr/bin/perl use warnings; use strict; my @contigfile = qw( >37 ABC DEF GHI >456 JKL MNO PQR STU VWX YZ >38 ) +; my @result; for my $i (0 .. $#contigfile) { my $current = $contigfile[$i]; push @result, q() and next if 0 == index $current, '>'; $result[-1] .= $current; } print "$_\n" for @result;
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others goofing around in the Monastery: (3)
As of 2024-04-26 04:05 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found