Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Perl: Общие вопросы > Зацикливание при значение больше 2


Автор: NZero 2.12.2013, 17:51
Всем привет! Сделал цикл, который выполняет поиск в xml файле и записывает в новый xml. Собственно цикл.

Код

my $col = 2;
    
    my $j;
    
    while($col)
    {
    for($j=0;$j<$count;$j++)
    {
        if($str[$j] =~ /<$fields[$n]>/g)
        {
        while($str[$j] !~ /<\/$fields[$n]>/g)
        {
                print $fout $str[$j];
            $j++;
        }
        print $fout $str[$j];
        }
    }
    $j=0;
    $col--;
    }


Но при значение col больше 2 происходит зацикливание. Не пойму почему. Вроде должно одинаково работать при любых значениях col. 

Автор: Bulat 2.12.2013, 18:38
А может у тебя зацикливание происходит здесь

Код

while($str[$j] !~ /<\/$fields[$n]>/g)
{
    print $fout $str[$j];
    $j++;
}


Не весь код выложил, утверждать ничего не могу. smile 

Автор: noize 2.12.2013, 22:10
в подобных ситуациях меня выручает perl debugger: perl -d <скрипт>

Автор: NZero 3.12.2013, 10:10
Весь код

Код

#!/usr/bin/perl -W

use Time::localtime;
use strict;

#Объявляем переменные
my $d = localtime;
my $day;
my $mon;
my $year;
my $res;
my $n;
my $fin;
my $xfile;
 my $fout;


($day,$mon,$year) = ($d->mday,($d->mon)+1,$d->year+1900);
my $r = "../reports/report_$day.$mon.$year.html";

#Открываем файл для записи результатов
if ( -e "$r")
{
    system ("sudo echo '<tr><td colspan=3><b>Дублирование ключей</b></td></tr>' >> $r");
}
else
{
open($res,"> $r");
print $res "<html><head><title>Результат тестирования компилятора MSG1</title><meta http-equiv='content-type' content='text/html;charset=utf-8'/></head><body><table border=1><tr><td>Поле</td><td>Значение</td><td>Результат</td></tr><tr><td colspan=3><b>Дублирование ключей</b></td></tr>";
close($res);
}

#########################Начинаем тестирование####################################

my @fields = ("Transport_cfg","SIP_route","Trunk","Rule");

my $len = @fields;

for ($n=0;$n<$len;$n++)
{   
    
    #Проверяем есть ли бинарный файл
    system("sudo rm -f test.bin") if ( -e "test.bin" );

    #Открываем файл compiler_test.xml в переменную fh_in
    open($fin,"../compiler_test.xml") || die("Error open compiler_test.xml\n");

    $xfile = "$fields[$n].xml";

    #Удаляем xml файл, если такой уже есть
    system("sudo rm -f $xfile") if ( -e $xfile );


    #Открываем файл xml на запись
    open($fout,"> $xfile");

    #Записываем строки файла в массив
    my @str = <$fin>;

    #Подсчитываем количество строк в файле
    my $count = @str;

    my $i = 0;

    while ($str[$i] !~ /<$fields[$n]>/g)
    {
    print $fout $str[$i];
    $i++;
    }
    
    my $col = 3;
    
    my $j;
    
    while($col > 0)
    {
    for($j=0;$j<$count;$j++)
    {
        if($str[$j] =~ /<$fields[$n]>/g)
        {
        while($str[$j] !~ /<\/$fields[$n]>/g)
        {
            print $str[$j];
            print $fout $str[$j];
            $j++;
        }
        print $fout $str[$j];
        }
    }
    $j=0;
    $col--;
    }

    $i = $i + $j;
    
    for(;$i<$count;$i++)
    {
    print $fout $str[$i];
    }

    #Закрываем файлы
    close($fin);
    close($fout);

#    system("sudo ../cfgcomp.elf tobinary test.bin $xfile");

    if ( -e "test.bin")
    {
    system("sudo echo '<tr><td>$fields[$n]</td><td></td><td bgcolor=red>Ошибка</td></tr>' >> $r");
#    system("sudo rm -f $xfile");
    }
    else
    {
    system("sudo echo '<tr><td>$fields[$n]</td><td></td><td bgcolor=green>Успешно</td></tr>' >> $r");
#    system("sudo rm -f $xfile");
    }
}

system("sudo echo '</table></body></html>' >> $r");


Автор: Bulat 3.12.2013, 12:05
NZero, лично у меня бесконечный цикл появился здесь
Код

    while ($str[$i] !~ /<$fields[$n]>/g)
    {
    print $fout $str[$i];
    $i++;
    }


мой скрипт - урезанный твой код :

Код

#!/usr/bin/perl -W

my @fields = ("Transport_cfg","SIP_route","Trunk","Rule");

my @str = ("Transport_cfg", "1", "1");
#Подсчитываем количество строк в файле
my $count = @str;
my $i = 0;
while ($str[$i] !~ /<$fields[$n]>/g)
{
  print $i, "\n";
  #print $fout $str[$i];
  $i++;
}


лечил:
Код

while (defined $str[$i] && $str[$i] !~ /<$fields[$n]>/g)


здесь:

Код

while($str[$j] !~ /<\/$fields[$n]>/g)
{
  print $str[$j];
  print $fout $str[$j];
  $j++;
}


очевидно, та же бага.

других подозрительных мест вроде не обнаружил  smile 

Автор: arto 3.12.2013, 12:06
какой смысл в выражении system "sudo echo '<tr><td colspan=3><b>Дублирование ключей</b></td></tr>' >> $r" ?
для чего запускать /bin/echo из-под sudo?

Автор: NZero 3.12.2013, 12:38
Цитата(arto @  3.12.2013,  12:06 Найти цитируемый пост)
какой смысл в выражении system "sudo echo '<tr><td colspan=3><b>Дублирование ключей</b></td></tr>' >> $r" ?
для чего запускать /bin/echo из-под sudo? 

Это уже исправил на
Код

print $res "<tr><td colspan=3><b>Дублирование ключей</b></td></tr>";


Добавлено через 2 минуты и 4 секунды
Цитата(Bulat @  3.12.2013,  12:05 Найти цитируемый пост)
лечил:
Код

while (defined $str[$i] && $str[$i] !~ /<$fields[$n]>/g)



Так тоже не работает( и там не $i а $j, но это не суть важно)


Автор: Bulat 3.12.2013, 12:55
Цитата(NZero @  3.12.2013,  12:38 Найти цитируемый пост)
и там не $i а $j, но это не суть важно

ну в одном месте у тебя $i, а в другом $j. А если суть понял - то зачем мне писать одно и то же дважды.

Цитата(NZero @  3.12.2013,  12:38 Найти цитируемый пост)
Так тоже не работает

Ну тогда по очереди втыкай внутрь цикла что-нить типа

Код

print "I : ", $i, "\n";


Код

print "J : ", $j, "\n";


прогоняй и смотри какой из счетчиков не меняется в соответствии с ожиданием. Локализуешь счетчик - найдешь семантическую ошибку - и глядишь самостоятельно докрутишь.

или дебажь - perl -d - тебе в помощь. 

Автор: NZero 3.12.2013, 14:58
переписал код, получилось вот так

Код

my $i = 0;
 
    my @dup_key;
    
    for(;$i<$count;$i++)
    {
    if($str[$i] =~ /<$fields[$n]>/g)
    {
        while($str[$i] !~ /<\/$fields[$n]>/g)
        {
        push @dup_key, $str[$i];
        $i++;
        }
        push @dup_key, $str[$i];
    }
    }
    
    my $len_key = @dup_key;
    
    $i = 0;
    
    while ($str[$i] !~ /<$fields[$n]>/g)
    {
    print $fout $str[$i];
    $i++;
    }
    
    
    my $col = 3;
    
    my $j;
    
    while($col)
    {
    for($j=0;$j<$len_key;$j++)
    {
        print $fout $dup_key[$j];
    }
    $col--;
    }
 
    $i = $i + $len_key;
 
    for(;$i<$count;$i++)
    {
    print $fout $str[$i];
    }


Теперь работает)

Автор: Bulat 3.12.2013, 15:20
NZero, ну вот видишь - можешь же, когда захочешь. И советы других остались неудел!  smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)