Regex 为什么我的程序在一行输入后崩溃?

Regex 为什么我的程序在一行输入后崩溃?,regex,perl,loops,multiline,Regex,Perl,Loops,Multiline,我正在写一个简单的程序,将句子中的每个单词大写。它获得多行输入。然后我循环输入行,将行中的每个单词拆分,大写,然后再次连接行。如果输入的是一句话,这很好,但一旦我输入两行,我的程序就会崩溃(如果我等待太久,我的计算机就会冻结) 这是我的密码 @input = <STDIN>; foreach(@input) { #reset @words @words= (); #readability $lines =$_; #split

我正在写一个简单的程序,将句子中的每个单词大写。它获得多行输入。然后我循环输入行,将行中的每个单词拆分,大写,然后再次连接行。如果输入的是一句话,这很好,但一旦我输入两行,我的程序就会崩溃(如果我等待太久,我的计算机就会冻结)

这是我的密码

@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++;
}
@input=;
foreach(@input)
{   
#重置@words
@单词=();
#可读性
$lines=$\ux;
#分句
@字=拆分(/,$行);
#每个单词大写
foreach(@words){
$words[$k]=ucfirst;
$k++;
}
#再次连接句子
$lines=join(“”,@words);
#创建输出行
$output[$i]=$line;
$i++;
}
#打印结果
打印“\n结果:\n”;
foreach(@output){
打印$output[$j],“\n”;
$j++;
}
有人能告诉我为什么它会崩溃吗

  • 使用strict(并被告知未正确处理变量,如索引)
  • 用于var(array)以获取没有索引的可用项(Perl不是Javascript)
  • 没有什么是不会错的(例如,推送而不是索引)
  • 代码:

    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";
    }
    
    使用strict;#总是
    我的@input=;#循环需要输入和输出
    我的@output=();
    对于我的$line(@input)#for使可读性*和*简洁性变得容易
    {
    chomp$line;#摆脱eol
    #分句
    我的@words=split(/,$line);
    #每个单词大写
    对于我的$word(@words){#没有错误处理索引的危险
    $word=ucfirst($word);
    }
    #再次连接句子
    $line=join(“”,@words);
    #创建输出行
    按@输出,$line;
    }
    #打印结果
    打印“\n结果:\n”;
    对于我的$行(@output){
    打印$line“\n”;
    }
    
    问题在于,您在整个过程中都在使用全局变量,因此它们在循环的迭代中保持其值。您已将
    @words
    重置为空列表,即使您不需要-当您将
    拆分的结果分配给它时,它会被覆盖-但是
    $k
    正在不断增加

    $k
    最初设置为
    undef
    ,其计算结果为零,因此对于第一句话,一切正常。但是您将
    $k
    设置为
    @words
    中的元素数,因此下一个句子从那里开始,而不是从零开始。您在
    @words
    上的循环变得无穷无尽,因为您正在分配(并因此创建)
    $words[$k]
    ,因此数组的长度和循环速度一样快

    同样的问题也适用于
    $i
    $j
    ,但执行永远不会达到重用它们的程度

    尽管这是在Perl4中工作的唯一方法,但在20多年前,Perl5使编程更加易于编写和调试。您现在可以使用
    my
    声明变量,也可以
    使用strict
    ,它(除其他外)坚持您使用的每个变量都必须声明,否则您的程序将无法编译。还有同样宝贵的
    使用警告。在这种情况下,它会警告您正在使用未定义的变量
    $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++;
    }
    
    使用严格;
    使用警告;
    我的@input=;
    我的@output;
    我的$i=0;
    foreach(@input){
    #可读性
    我的$行=$\;
    #分句
    我的@words=拆分“”,$line;
    #每个单词大写
    我的$k=0;
    foreach(@words){
    $words[$k]=ucfirst;
    $k++;
    }
    #再次连接句子
    $lines=连接“”,@words;
    #创建输出行
    $output[$i]=$line;
    $i++;
    }
    打印“\n结果:\n”;
    我的$j=0;
    foreach(@output){
    打印$output[$j],“\n”;
    $j++;
    }
    
    想想,
    $k
    从第二行开始的位置……但是说真的,通过
    my
    声明所有变量并强迫自己通过
    使用strict
    这样做要比使用诸如“reset@words”这样的废话好得多。使用
    s/(\W+/\u$1/g
    可以简单得多。同上,谢谢,我是一个初学者,我很抱歉不知道严格和警告。我的代码现在可以用了,谢谢。我不被允许使用正则表达式,我必须先使用UCEX。真的吗?不允许使用正则表达式?在学生练习中,它们通常会让你使用新材料:)