Forum Webscript.Ru

Программирование => Perl => Тема начата: Skif от 31 Мая 2005, 13:42:00

Название: Помогите "объяснить" самому себе ошибку
Отправлено: Skif от 31 Мая 2005, 13:42:00
Вот код


sub copy_mess_head {

my $mail =shift @_;

my $line;

my $result = -1;
my @cc = $mail->header("cc");

if (!undef $cc[-1]) {
foreach my $str (@cc) {
if (undef $str){
if (($str ne \'\')or ($str ne \' \')) {
$line = "$line$str";
}
}
}
}

@cc = ();

@cc = $mail->header("CC");

if (!undef $cc[-1]) {
foreach my $str (@cc) {
if (undef $str){
if (($str ne \'\')or ($str ne " ")) {
$line = "$line$str";
}
}
}
}

if (undef $line) {      ###### это 77 строка . Здесь ругается.
$result = $line;
}
elsif ($line eq \'\') {
$result = -1;
}
return  $result;
}



в результате работы выдается такое вот сообщение
[root@skif.bsd] /usr/local/script/filters/:chmod 755 ./my_filter.pl && ./my_filter.pl
Use of uninitialized value in string eq at ./my_filter.pl line 77.

Я немогу понять, почему? Ведь это как раз проверка на то, определена переменная или нет. А идет ругань....
Название: Помогите "объяснить" самому себе ошибку
Отправлено: NeoNox от 31 Мая 2005, 13:49:42
perldoc -f undef
perl -de0

  DB<1> $test = 1

  DB<2> undef $test

  DB<3> print $test
Название: Помогите "объяснить" самому себе ошибку
Отправлено: commander от 31 Мая 2005, 13:51:31
Skif
если бы логическая конструкция была такой:
if (undef $line)
{
$result = $line;
}
else
{
$result = -1;
}
ругани бы не было...
выводы делаем сами... ;)
Название: Помогите "объяснить" самому себе ошибку
Отправлено: Skif от 31 Мая 2005, 13:53:25
да ступил, надо
!undef
Название: Помогите "объяснить" самому себе ошибку
Отправлено: Mog. от 31 Мая 2005, 13:53:57
undef $line делает переменную $line неопределенной
для проверки надо
if(defined $line)
Название: Помогите "объяснить" самому себе ошибку
Отправлено: Skif от 31 Мая 2005, 14:00:35
нет, сегодня я определенно торможу - надо использовать define замутил не ту функцию :)
Название: Помогите "объяснить" самому себе ошибку
Отправлено: Skif от 31 Мая 2005, 14:07:28
выглядеть все должно так:


sub copy_mess_head {

my $mail =shift @_;

my $line;

my $result = 1;
my @cc = $mail->header("cc");

if (defined $cc[-1]) {
foreach my $str (@cc) {
if (defined $str){
if (($str ne \'\')or ($str ne \' \')) {
$line = "$line$str";
}
}
}
}

@cc = ();

@cc = $mail->header("CC");

if (defined $cc[-1]) {
foreach my $str (@cc) {
if (defined $str){
if (($str ne \'\')or ($str ne " ")) {
$line = "$line$str";
}
}
}
}
if ($line eq \'\') {
$result = 1;
}
elsif (defined $line) {
$result = $line;
}
else {
$result = 1
}
return  $result;
}
Название: Помогите "объяснить" самому себе ошибку
Отправлено: Phoinix от 31 Мая 2005, 14:49:44
Skif

В такой конструкции, warning получишь сразу


...
if ($line eq \'\') {
    $result = 1;
}
elsif (defined $line) {
    $result = $line;
}
else {
    $result = 1
}
return  $result;
...

И последнее условие немного странное... переменная может быть либо определена, либо не определена, но никак не "наполовину определена".

Проще всего записать так, и не морочится:

$result = $line || 1;
Название: Помогите "объяснить" самому себе ошибку
Отправлено: cr4ck3r от 01 Июня 2005, 10:52:45
Вот эта конструкция вообще надуманная:


if (defined $cc[-1]) {
    foreach my $str (@cc) {
        if (defined $str){
            if (($str ne \'\')or ($str ne \' \')) {
                $line = "$line$str";
            }
        }
    }
}

Зачем проверять определенность последнего элемента в массиве?
Код можно упростить в разы:

foreach my $str (@cc) {
        $str=~s/^\\s//;
        $line = "$line$str" if(length($str)>0);
    }
Название: Помогите "объяснить" самому себе ошибку
Отправлено: Skif от 01 Июня 2005, 15:36:44
Phoinix

нет, такой вариант не подходит.  $line может принимать три вида значений undef, \'\' и строку(символ). Во всех случаях кроме строки - мне нужно вернуть результат = 1, в случае строки - вернуть строку. (пример ниже)
cr4ck3r
частично согласен. Но мне еще надо проверить имеется ли пустой символ.

вот пример:

#!/usr/bin/perl -w

$a=\'\';
$b=\'\';
$c=\'\';

push @arr, $a;
push @arr, $b;
push @arr, $c;


$size = @arr;

print "$size\\n";
exit(0);



а вот что он возвращает:
Цитировать

[root@skif.center.klo] /usr/local/script/:./1.pl
3


тобишь проверка на "пустиой символ" мне просто необходима.
Название: Помогите "объяснить" самому себе ошибку
Отправлено: Skif от 01 Июня 2005, 15:49:03
cr4ck3r
$line = "$line$str" if(length($str)>0);
Невнимательный был. Да ты прав, эта конструкция проще.
Название: Помогите "объяснить" самому себе ошибку
Отправлено: Phoinix от 01 Июня 2005, 18:20:16
Skif

Цитировать
нет, такой вариант не подходит. $line может принимать три вида значений undef, \'\' и строку(символ). Во всех случаях кроме строки - мне нужно вернуть результат = 1, в случае строки - вернуть строку. (пример ниже)


Для самопроверки:
#!/usr/bin/perl -w
use strict;

    my $var1 = \'2\';
    my $var2 = $var1 || 1;
    print $var2, "\\n";

    $var1 = \'\';
    $var2 = $var1 || 1;
    print $var2, "\\n";

    $var1 = undef;
    $var2 = $var1 || 1;
    print $var2, "\\n";

exit;
Результат:

2
1
1

Как раз то что нужно...

cr4ck3r

Еще немного упростить:

foreach my $str (@cc) {
        $str=~s/^\\s//;
        $line .= $str if length($str) > 0;
}
Название: Помогите "объяснить" самому себе ошибку
Отправлено: cr4ck3r от 02 Июня 2005, 10:09:38
Цитировать
Phoinix:
Еще немного упростить:


foreach my $str (@cc) {
$str=~s/^\\s//;
$line .= $str if length($str) > 0;
}

5 баллов :)