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

Dear monks,

I'm an entry level Perl user and wish to get some help from you.

I have a small program called "Scheduling.pl" as shown below. When I run the program, I receive an error messgae "Use of uninitialized value in print at Scheduling.pl line 22, <STDIN> line 9."

Does anyone know if this is bug in the program or it is caused by the compiler? By the way, I use ActivePerl 5.6.1.

use warnings; use strict; my @horiz = <STDIN>; chomp(@horiz); my @dates = split '\|', shift @horiz; splice @dates, 0, 3; for my $line (@horiz) { my @flds = split '\|', $line; shift @flds; my $PID = shift @flds; my $SID = shift @flds; my @dates_copy = @dates; for my $date (@dates_copy) { print "$PID|$SID|",shift(@flds),"|$date\n"; } } # for $line
below are some sample data.
|||12/31/2007|1/1/2008|1/2/2008|1/3/2008|1/4/2008|1/5/2008| |3104|1|New Years|Holiday|Clinic||| |3104|2|New Years|Holiday|Clinic||| |3104|3|New Years|Holiday|Clinic||| |3104|4|New Years|Holiday|AofC Clin||| |3109|1|New Years|Holiday|Clinic||| |3109|2|New Years|Holiday|Clinic||| |3109|3|New Years|Holiday|Clinic||| |3109|4|New Years|Holiday|AofC Clin|||||
Out put
3104|1|New Years|12/31/2007 3104|1|Holiday|1/1/2008 3104|1|Clinic|1/2/2008 3104|1||1/3/2008 3104|1||1/4/2008 3104|1||1/5/2008 3104|2|New Years|12/31/2007 3104|2|Holiday|1/1/2008 3104|2|Clinic|1/2/2008 3104|2||1/3/2008 3104|2||1/4/2008 3104|2||1/5/2008 3104|3|New Years|12/31/2007 3104|3|Holiday|1/1/2008 3104|3|Clinic|1/2/2008 3104|3||1/3/2008 3104|3||1/4/2008 3104|3||1/5/2008 3104|4|New Years|12/31/2007 3104|4|Holiday|1/1/2008 3104|4|AofC Clin|1/2/2008 3104|4||1/3/2008 3104|4||1/4/2008 3104|4||1/5/2008 3109|1|New Years|12/31/2007 3109|1|Holiday|1/1/2008 3109|1|Clinic|1/2/2008 3109|1||1/3/2008 3109|1||1/4/2008 3109|1||1/5/2008 3109|2|New Years|12/31/2007 3109|2|Holiday|1/1/2008 3109|2|Clinic|1/2/2008 3109|2||1/3/2008 3109|2||1/4/2008 3109|2||1/5/2008 3109|3|New Years|12/31/2007 3109|3|Holiday|1/1/2008 3109|3|Clinic|1/2/2008 3109|3||1/3/2008 3109|3||1/4/2008 3109|3||1/5/2008 3109|4|New Years|12/31/2007 3109|4|Holiday|1/1/2008 3109|4|AofC Clin|1/2/2008 3109|4||1/3/2008 3109|4||1/4/2008 3109|4||1/5/2008
Your help would be greatly appreciated.

Replies are listed 'Best First'.
Re: Error: Uninicialized Value
by jdporter (Paladin) on Apr 29, 2008 at 16:51 UTC

    Look at what my @flds = split '\|', $line; is doing with the lines whose last two fields are empty, e.g. |3104|1|New Years|Holiday|Clinic|||
    Unfortunately, it does not return zero-length strings for trailing empty fields, as it ought to (and, I thought, used to).
    Instead, it doesn't return them at all; @flds is shorter by two.
    So you get undef when you try to access the fields at those indices.

    A word spoken in Mind will reach its own level, in the objective world, by its own weight

      If you don't want trailing empty values stripped, then use split '\|', $line, -1; as documented at split.

      - tye        

Re: Error: Uninicialized Value
by shmem (Chancellor) on Apr 29, 2008 at 17:08 UTC

    Look at your output.

    3104|1|New Years|12/31/2007 3104|1|Holiday|1/1/2008 3104|1|Clinic|1/2/2008 3104|1||1/3/2008 ^^---- the uninitialized value is here

    You do

    print "$PID|$SID|",shift(@flds),"|$date\n";

    but sometimes the value shifted off @flds is undef. Quick fix:

    print "$PID|$SID|",(@flds ? shift(@flds) : ''),"|$date\n";

    But if those output lines containing an empty 3rd field are unwanted anyways, say

    print "$PID|$SID|",shift(@flds),"|$date\n" if $flds[0];

    Why are you

    my @dates_copy = @dates;

    copying @dates each pass through the loop? Just iterate over @dates.

    --shmem

    _($_=" "x(1<<5)."?\n".q·/)Oo.  G°\        /
                                  /\_¯/(q    /
    ----------------------------  \__(m.====·.(_("always off the crowd"))."·
    ");sub _{s./.($e="'Itrs `mnsgdq Gdbj O`qkdq")=~y/"-y/#-z/;$e.e && print}
Re: Error: Uninicialized Value
by toolic (Bishop) on Apr 29, 2008 at 16:56 UTC
    If you also add use diagnostics; to your code, you would get more verbose help:
    Use of uninitialized value in print at xxx line yyy, <STDIN> line 2 (# +1) (W uninitialized) An undefined value was used as if it were alread +y defined. It was interpreted as a "" or a 0, but maybe it was a mi +stake. To suppress this warning assign a defined value to your variables. To help you figure out what was undefined, perl tells you what ope +ration you used the undefined value in. Note, however, that perl optimiz +es your program and the operation displayed in the warning may not necessa +rily appear literally in your program. For example, "that $foo" is usually optimized into "that " . $foo, and the warning will refer +to the concatenation (.) operator, even though there is no . in your program.

    The problem occurs on the following line:

    print "$PID|$SID|",shift(@flds),"|$date\n";

    To debug this, I changed this line to:

    print shift(@flds),"\n";

    and I still get the warnings messages. This leads me to believe that you are trying to shift an element from an empty array.

Re: Error: Uninicialized Value
by apl (Monsignor) on Apr 29, 2008 at 17:13 UTC
    @dates contains (for example): 12/31/2007 1/1/2008 1/2/2008 1/3/2008 1/4/2008 1/5/2008

    @flds contains: 'New Years' Holiday Clinic

    In other words, you've six dates and three fields. You're trying to print one field with each date, and there aren't enough fields to go around. So you get three undefs, one each for the final three shifts.

Re: Error: Uninicialized Value
by jwkrahn (Abbot) on Apr 29, 2008 at 17:38 UTC

    Try it like this:

    use warnings; use strict; chomp( my @horiz = <STDIN> ); my @dates = grep length, split /\|/, shift @horiz; for my $line ( @horiz ) { my ( undef, $PID, $SID, @flds ) = split /\|/, $line, -1; for my $date ( @dates ) { print "$PID|$SID|", shift( @flds ), "|$date\n"; } }
Re: Error: Uninicialized Value
by dwm042 (Priest) on Apr 29, 2008 at 17:37 UTC
    jw2523, if you look at your data, your first line creates 6 dates that are stored in @dates. Later, you create a @flds array and generally you only put 3 nonempty entries into that array. The split leaves a few uninitialized variables in the array that lead to your errors. The following small change to your program will eliminate your error and give you cleaner output:

    replace for my $date (@dates_copy) { print "$PID|$SID|",shift(@flds),"|$date\n"; } with for my $date (@dates_copy) { my $field = shift(@flds); $field = '' unless ( $field ); print "$PID|$SID|",$field,"|$date\n"; }
Re: Error: Uninicialized Value
by jw2523 (Initiate) on Apr 29, 2008 at 17:59 UTC
    Thank you all. I really appreciate all of your kind help!