2014-03-27 3 views
0

Я пишу простую программу, которая заглаживает каждое слово в предложении. Он получает многострочный ввод. Затем я прохожу через входные строки, разбивая каждое слово в строке, заглавные буквы, а затем снова присоединяюсь к строке. Это хорошо работает, если вход одно предложение, но как только я ввода двух строк моя программа падает (и если я слишком долго ждать мой компьютер зависает.)Почему моя программа падает после одной строки ввода?

Вот мой код

@input = <STDIN>; 
foreach(@input) 
{ 
     #reset @words 
    @words=(); 

    #readability 
    $lines =$_; 

    #split sentence 
    @words = split(/ /, $lines); 
    #capitalize each word 
    foreach(@words){ 
      $words[$k] = ucfirst; 
      $k++; 
    } 

    #join sentences again 
    $lines = join(' ', @words); 

    #create output line 
    $output[$i]=$lines; 
    $i++; 
} 

#print the result 
print "\nResult:\n"; 
foreach(@output){ 
     print $output[$j],"\n"; 
     $j++; 
} 

Может кто-то скажите, пожалуйста, почему он падает?

+1

Подумайте о том, где '$ k' начинается на второй линии ... но серьезно, объявив все переменные через' my' и заставить себя сделать это с помощью 'использовать strict' будет гораздо лучше, чем кладжи как«сброс @words». – amon

+1

Это можно сделать намного проще, используя 's/(\ W +)/\ u $ 1/g'. Тоже на ['Зачем использовать строгие предупреждения и предупреждения?"] (Http://stackoverflow.com/questions/8023959/why-use-strict-and-warnings) – Miller

+0

Спасибо, я новичок, мне жаль, что не зная о строгих и предупреждениях. Мой код работает сейчас, спасибо.Мне не разрешалось использовать регулярное выражение, мне пришлось использовать ucfirst. –

ответ

0
  1. использование строго (и говоря о неправильном обращении переменных, таких как индексы)
  2. использовать для вара (массива), чтобы получить полезный элемент без индекса (Perl не Javascript)
  3. Что ISN «т не может быть неправильно (например, нажать вместо индекса)

В коде:

use strict; # always! 

my @input = <STDIN>; # the loop need in- and output 
my @output =(); 

for my $line (@input) # for makes readability *and* terseness easy 
{ 
    chomp $line; # get rid of eol 

    #split sentence 
    my @words = split(/ /, $line); 

    #capitalize each word 
    for my $word (@words){ # no danger of mishandling indices 
     $word = ucfirst($word); 
    } 

    #join sentences again 
    $line = join(' ', @words); 

    #create output line 
    push @output, $line; 
} 

#print the result 
print "\nResult:\n"; 
for my $line (@output){ 
    print $line, "\n"; 
} 
0

проблема заключается в том, что вы используете г во всех переменных, поэтому они сохраняют свои значения в итерациях цикла. Вы сбросили @words в пустой список, хотя вам это не нужно - он перезаписывается, когда вы назначаете результат split, но $k увеличивается бесконечно.

$k изначально установлен в undef который оценит как нулевой, так что для первого предложения все в порядке. Но вы оставляете $k установленным для количества элементов в @words, поэтому он начинается оттуда вместо нуля для следующего предложения. Ваша петля над @words становится бесконечной, потому что вы назначаете (и так создаете) $words[$k], чтобы массив становился все длиннее, как вы зацикливаетесь на нем.

Эта же проблема применяется к $i и $j, но выполнение никогда не доходит до их повторного использования.

Alshtough это был единственный способ работать в Perl 4, более двадцати лет назад, Perl 5 сделал программирование очень приятным для написания и отладки. Теперь вы можете объявить переменными с my, и вы можете use strict, который (среди прочего) настаивает на том, что каждая переменная, которую вы используете, должна быть объявлена, иначе ваша программа не будет компилироваться. Вы также можете воспользоваться нашим навигатором слева на странице, чтобы сузить свой поиск или узнайте больше о use warnings. В этом случае он предупредил бы вас, что вы использовали неопределенную переменную $k и т. Д. Для индексации массивов.

Если я применил use strict и use warnings, объявить все ваши переменные и инициализировать счетчики до нуля, тогда я получу рабочую программу. Это все еще не очень элегантно, и есть намного лучшие способы сделать это, но ошибка ушла.

use strict; 
use warnings; 

my @input = <STDIN>; 
my @output; 
my $i = 0; 

foreach (@input) { 

    # readability 
    my $lines = $_; 

    # split sentence 
    my @words = split ' ', $lines; 

    # capitalize each word 
    my $k = 0; 
    foreach (@words) { 
    $words[$k] = ucfirst; 
    $k++; 
    } 

    # join sentences again 
    $lines = join ' ', @words; 

    #create output line 
    $output[$i] = $lines; 
    $i++; 
} 

print "\nResult:\n"; 
my $j = 0; 
foreach (@output) { 
    print $output[$j], "\n"; 
    $j++; 
} 
Смежные вопросы