use of uninitialized value (beginner)

M

Marek Stepanek

Hello all,



I have some numbers to calculate (DATA). Each line represent a new day,
which are calculated with the subroutine "add_one_day"

But I can't get rid of the warnings, which I don't understand:

Use of uninitialized value in concatenation (.) or string at
../excel_autorech_test.pl line 35, <DATA> line 20.

Could somebody be so kind, and look through this script?


Thank you and best greetings from Munich


marek


#! /usr/bin/perl -w

use strict;

use Date::Calc qw:)all);


my $start_day = "01";
my $start_month = "06";
my $year = "2006";
my $day = $start_day;
my $month = $start_month;
my ($date, $wochentag);

my @lines;

while (<DATA>)
{
s/,/./g;
push @lines, $_ if (/^[\d,.\t\s]+$/ || /^$/);


}

foreach my $line (@lines)
{
if ($line =~ /^$/)
{
add_one_day($year, $month, $day);
print "$wochentag, $date: hurray, there is an empty line, but one
day more!\n";
}
elsif ($line=~ /[\d.\t]+/)
{
add_one_day($year, $month, $day);
print "$wochentag, $date: hurray, there is some stuff to
calculate!\n\t$line\n";
}
}

sub add_one_day
{

my $day_plus = 1;
my ($year2, $month2, $day2) = Add_Delta_Days($year, $month, $day,
$day_plus);
my $dow = Day_of_Week($year2,$month2,$day2);
Language(Decode_Language("Deutsch"));
my $lang = Language_to_Text(Language());
my $wochentag = Day_of_Week_Abbreviation($dow);
$month2 = sprintf("%02d", $month2);
$day2 = sprintf("%02d", $day2);
$date = "$day2.$month2.$year2";
($day, $month, $year) = ($day2, $month2, $year2);
# print "here for test reasons: $wochentag, $date, $year, $month,
$day\n\n";
return ($wochentag, $date, $year, $month, $day);

}

__DATA__

27192,1 10882,6 591 16 6138,5
27476,3 10990,7 596 16 6298,8
27737,9 11146,8 301 16 6523,1
27775,2 11158,5 604 16 6553,4


28179,1 11362,1 611 16 6863,3
28489,7 11524,2 619 16 7116,7
28752,1 11683,2 624 16 7849,6
29191,3 11882,2 618 16 7622,8
29290,8 11961,2 633 16 7746,7

29549,4 12109,9 638 16 7964,0
29778,4 12180,8 640 16 8063,2
30172,2 12364,1 644 16 8321,0
30282,0 12416,7 647 16 8401,1
30483,5 12506,1 652 16 8541,2
30769,3 12668,7 660 16 8788,6
30992,9 12725,4 662 16 8873,2
 
U

usenet

Marek said:
Use of uninitialized value in concatenation (.) or string at
./excel_autorech_test.pl line 35, <DATA> line 20.

Well, that means, um, that you are using an uninitalized value (ie, a
null variable) in a string. Just like it says.

The variable in question is $wochentag, which is declared but is not
populated within the scope of your line 35 (a different variable which
happens to have the same name is declared and populated in the
subroutine add_one_day, but this variable is lexically localized to
that subroutine and does not exist outside of that subroutine).

You need to clarify your thinking about that subroutine. You call it
like this:
add_one_day($year, $month, $day);

which passes those values to the subroutine as a special array named
@_, but you never look at those passed values. Instead, you declare
lexically local variables with those same names (which will be
undefined). You return from it like this:
return ($wochentag, $date, $year, $month, $day);

which returns five scalars as an array (not as five named scalars).
But the call to the subroutine does not attempt to capture the returned
values of this list.

I think your main problem is confusion on how lexical scoping works in
Perl (and how variables are passed to and from a subroutine).

Your program might work if you change your initial declarations from
"my" to "our" and drop the "my"s elsewhere in the program. But that's
an awful kludge.
 
D

Dr.Ruud

Marek Stepanek schreef:


This is not about the uninitialized value.
[\d,.\t\s]+

1. you just removed all ","
2. "\t" is in "\s"

So [\d.\s]+ would do the same.
So after a chomp, [\d.\t]+ would do.

if ($line =~ /^$/)
{ ... }
elsif ($line=~ /[\d.\t]+/)

Because you push only checked lines, the test in the elsif isn't needed.
A good habit is to always end with an else{}, like
else { die 'Should never reach this.' }.

If you need to make the checks on numbers stronger, Regexp::Common is
your friend.
http://search.cpan.org/search?module=Regexp::Common
 
M

Marek Stepanek


Thank you also to David! With your remarks it is working. I put indeed one
"my" declaration too much in front of the $wochentag, so this variable were
private ...

I will have a look to the module you suggested Regexp::Common ... No I idea
what it will do, but I am always keen to learn my Perl.

My script is now like follows, if you have suggestions on style, or say
better basics, - I am unfortunately not yet there, what you call "style" -
please go ahead :)

One remark for David as comment in the script ...

marek



#! /usr/bin/perl

use warnings;
use strict;

use Date::Calc qw:)all);


my $start_day = "01";
my $start_month = "06";
my $year = "2006";
my $day = $start_day;
my $month = $start_month;
my ($date, $wochentag);

my @lines;

while (<DATA>)
{
s/,/./g;
push @lines, $_ if (/^[\d.\t\s]+$/ || /^$/);


}

foreach my $line (@lines)
{
if ($line =~ /^$/) # David: I am not sure how to avoid the check here,
because I have to calculate things, if the lines are *not* empty! But you
see as a good pupil I inserted a last else, as you suggested it :)
{
add_one_day($year, $month, $day);
print "$wochentag, $date: hurray, there is an empty line, but one
day more!\n";
}
elsif ($line=~ /[\d.\t]+/)
{
add_one_day($year, $month, $day);
print "$wochentag, $date: hurray, there is some stuff to
calculate!\n\t$line\n";
}
else
{
print "there is something wrong ...";
}
}

sub add_one_day
{

my $day_plus = 1;
my ($year2, $month2, $day2) = Add_Delta_Days($year, $month, $day,
$day_plus);
my $dow = Day_of_Week($year2,$month2,$day2);
Language(Decode_Language("Deutsch"));
my $lang = Language_to_Text(Language());
$wochentag = Day_of_Week_Abbreviation($dow);
$month2 = sprintf("%02d", $month2);
$day2 = sprintf("%02d", $day2);
$date = "$day2.$month2.$year2";
($day, $month, $year) = ($day2, $month2, $year2);
# print "here for test reasons: $wochentag, $date, $year, $month,
$day\n\n";
return ($wochentag, $date, $year, $month, $day);

}

__DATA__

27192,1 10882,6 591 16 6138,5
27476,3 10990,7 596 16 6298,8
27737,9 11146,8 301 16 6523,1
27775,2 11158,5 604 16 6553,4


28179,1 11362,1 611 16 6863,3
28489,7 11524,2 619 16 7116,7
28752,1 11683,2 624 16 7849,6
29191,3 11882,2 618 16 7622,8
29290,8 11961,2 633 16 7746,7

29549,4 12109,9 638 16 7964,0
29778,4 12180,8 640 16 8063,2
30172,2 12364,1 644 16 8321,0
30282,0 12416,7 647 16 8401,1
30483,5 12506,1 652 16 8541,2
30769,3 12668,7 660 16 8788,6
30992,9 12725,4 662 16 8873,2
 
T

Tad McClellan

Marek Stepanek said:
My script is now like follows, if you have suggestions on style, or say
better basics, - I am unfortunately not yet there, what you call "style" -
please go ahead :)

s/,/./g;


tr/,/./; # does the same thing, only more clearly and faster too

push @lines, $_ if (/^[\d.\t\s]+$/ || /^$/);


A tab will match \s, so you don't need the \t

If you make all of the characters optional, then you can
eliminate the 2nd or clause.

I prefer not to clutter things up with parenthesis that are
not needed.

So we end up with this replacement line:

push @lines, $_ if /^[\d.\s]*$/;

add_one_day($year, $month, $day);


You never do anything with the return values from that subroutine.

sub add_one_day
{
$month2 = sprintf("%02d", $month2);
$day2 = sprintf("%02d", $day2);
$date = "$day2.$month2.$year2";


You can do the formatting all at once with one line:

$date = sprintf '%02d.%02d.%4d', $day2, $month2, $year2;

($day, $month, $year) = ($day2, $month2, $year2);


Why manipulate copies rather than the originals?

return ($wochentag, $date, $year, $month, $day);


Your code never looks at the values you are returning here.
 
M

Marek Stepanek

On 22.06.2006 00:36, in article (e-mail address removed),

....


thank you Tad. Very good lesson :) I Have learn a lot again !


marek
 

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
473,769
Messages
2,569,582
Members
45,065
Latest member
OrderGreenAcreCBD

Latest Threads

Top