Chinaunix

标题: foreach循环的疑问。 [打印本页]

作者: lucash    时间: 2010-05-05 18:39
标题: foreach循环的疑问。
本帖最后由 lucash 于 2010-05-05 18:45 编辑

  1. open AA,"<",$ARGV[0];
  2. open BB,"<",$ARGV[1];

  3. my %hash;

  4. foreach(<AA>){
  5.     chomp;
  6.     my $word = $_;
  7.     foreach(<BB>){
  8.          chomp;
  9.          print "$word ---- $_ \n";
  10.     }
  11. }
复制代码
为什么在这里第一个foreach只循环了一次就退出了呢?


改成这样后就成了:

  1. my %hash;
  2. my @word=<AA>;
  3. my @value=<BB>;

  4. foreach $word (@word){
  5.     chomp $word;
  6.     foreach $value(@value){
  7.          chomp $value;
  8.          print "$word ---- $value\n";
  9.     }
  10. }
复制代码
但把foreach里的@word替换成@word=<AA>,@value替换成@value=<BB>,又出现了相同的问题
第一个foreach 又只循环一次就退出了。

  1. my %hash;
  2. foreach $word (@word = <AA>){
  3.      chomp $word;
  4.      foreach $value (@value = <BB>){
  5.            chomp $value;
  6.            print "$word ---- $value\n";
  7.      }
  8. }
复制代码
这是为什么呢?本人初学perl,希望各位指点指点,如果问题太幼稚,还希望各位多多包涵。
作者: iamlimeng    时间: 2010-05-05 18:39
我认为是这样的:
你OPEN一次文件,只可以通过操作符<>遍历一次OPEN的文件内容,不能多次重复遍历,除非你再OPEN一次。在你第一次用foreach (<>)遍历完文件内容时,该文件句柄就自动关闭了,相当于close AA了。

一楼的第一段代码的第一个foreach,并不是象你说的只循环了一次,而是把<AA>的内容遍历了一遍,只不过<AA>的第二行是接在<BB>的最后一行以后打印,因为<BB>已经被遍历了一次,所以在读<AA>第二行时,BB已经被关闭了,所以不再有内容输出。

下面的例子更容易看懂,Second time后面什么也不会打印,因为AA已经被关闭了:
  1. #!/usr/bin/perl

  2. $file1 = "test1.pl";

  3. open AA,"<",$file1;
  4. print "Fist time:\n";
  5. foreach (<AA>) {
  6.         print;
  7. }
  8. print "\n\nSecond time:\n";
  9. foreach (<AA>) {
  10.         print;
  11. }
  12. close AA;

  13. <STDIN>;
复制代码
但如果你用@array=<AA>存储了文件内容,那么作为一个数组变量,当然是可以多次读取内容了。
作者: 李寻欢92    时间: 2010-05-05 18:44
回复 1# lucash


    应该这样吧
  1. open AA,"<",$ARGV[0];
  2. my %hash;

  3. foreach(<AA>){
  4.     chomp;
  5.     my $word = $_;
  6.     open BB,"<",$ARGV[1];
  7.     foreach(<BB>){
  8.          chomp;
  9.          print "$word ---- $_ \n";
  10.     }
  11. }
复制代码

作者: lucash    时间: 2010-05-05 18:46
回复  lucash


    应该这样吧
李寻欢92 发表于 2010-05-05 18:44



    为什么呢?
作者: lucash    时间: 2010-05-05 18:50
为什么要在第一个foreach块里打开另外的文件才有行呢?
作者: 李寻欢92    时间: 2010-05-05 18:57
回复 4# lucash


    因为你循环时把BB已经读完了,下一次AA循环就不读了!
作者: lucash    时间: 2010-05-05 19:06
回复 5# 李寻欢92


       foreach(<BB>){}

即使在这个foreach前面打开BB,这个foreach还是会把BB读完啊,那为什么却会进行下一个循环了呢?
作者: 李寻欢92    时间: 2010-05-05 19:19
回复 6# lucash


    因为在下一次循环又打开了BB
作者: lucash    时间: 2010-05-05 19:36
    回复 4# lucash


    因为你循环时把BB已经读完了,下一次AA循环就不读了!


回复  lucash


    因为在下一次循环又打开了BB
李寻欢92 发表于 2010-05-05 19:19


既然循环时把BB读完了下一次AA循环就不读了。那你说的下一次循环又打开了BB是怎么来的?不是已经不读了么?
作者: iamlimeng    时间: 2010-05-05 19:49
本帖最后由 iamlimeng 于 2010-05-05 19:52 编辑

建议楼主多用print,看输出了什么,就知道程序究竟是如何运作的,比如把代码改成这样:
  1. open AA,"<",$ARGV[0];
  2. open BB,"<",$ARGV[1];

  3. foreach(<AA>){
  4.     print;            #加一行,你看见输出,就知道是怎么回事了
  5.     chomp;
  6.     my $word = $_;
  7.     foreach(<BB>){
  8.          chomp;
  9.          print "$word ---- $_ \n";
  10.     }
  11. }
复制代码

作者: 李寻欢92    时间: 2010-05-05 19:53
回复 8# lucash

你看代码阿,每此都重新打开了阿!!
不回了!!!
作者: yybmsrs    时间: 2010-05-05 20:34
AA循环了一次,BB也循环了一次。在AA读第二个之前,BB已经循环结束,BB句柄也到了文件的最后,下次就不会再读。然后AA接着循环。
作者: nonultimate    时间: 2010-05-05 20:52
9楼正解。这样你就明白了。第一个foreach并不执行了一次,文件读取遍历只执行一次,除非重新打开。
  1. open AA,"<",$ARGV[0];
  2. open BB,"<",$ARGV[1];

  3. my %hash;
  4. foreach (<AA>){
  5.      chomp;
  6.      my $word = $_;
  7.      print "$word\n";
  8.      foreach (<BB>){
  9.            chomp;
  10.            print "$word ---- $_\n";
  11.      }
  12. }
复制代码

作者: nuclearxin    时间: 2010-05-06 15:16
(<XXX>) 只能用在while里
作者: lucash    时间: 2010-05-06 16:32
回复 9# iamlimeng


    原来是这样。明白了。
哈哈。

还多谢各位的解答。
作者: lucash    时间: 2010-05-09 14:23
回复 16# nonultimate


    是给的iamlimeng的 啊 。。????




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2