LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
楼主: conke

统计行数?

[复制链接]
发表于 2004-4-26 23:58:53 | 显示全部楼层

  1. open (FILE,"roby.txt");@roby=<FILE>;print ++$#roby;
复制代码
发表于 2004-4-27 00:06:47 | 显示全部楼层
这样也可以吧? :help
[php]@line=`cat file`;
print scalar@line;[/php]
发表于 2004-4-28 15:24:25 | 显示全部楼层

一个初步统计c/c++文件行数的程序

忽略注释行,包括/* */跟//两种形式的注释。
忽略空白行。
将用‘\’分开的行并成一行。
其它的就将源文件中的行作为行。


  1. #!/usr/bin/perl -w
  2. #To count the lines for c/c++ header/source files, omitting comments, empty line, and joining the lines seperated by '\'.
  3. use strict;

  4. my $total = 0;
  5. foreach my $src(@ARGV){
  6. #        print "to count file $src\n";
  7.         my $lines = &countline($src);
  8.         $total += $lines;
  9.         print "\t$lines : $src\n";
  10. }
  11. print "\t$total : total\n";


  12. sub countline{
  13.         my $src = $_[0];
  14.         my $count = 0;
  15.         open(SRC, "<$src") or die("Can't open file $src for reading due to: $!\n");
  16.         READLINE:
  17.         while(<SRC>){
  18.                 if($_ =~ /\\$/){
  19. #                print "To be countinued:$_";
  20.                         $_ .= <SRC>;
  21.                         redo READLINE;
  22.                 }
  23.                 elsif($_ =~ /^\s*\/\*/){
  24. #                        print "comments begin:\n";
  25.                         while(my $next = <SRC>){
  26.                                 if($next =~ /.*\*\/(.*)/){ #comments may be followed by a statement which should be counted.
  27. #                                        print "comments end\n";
  28.                                         $_ = $1;
  29.                                         last;
  30.                                 }
  31.                         }
  32.                 }
  33.                 if(($_ !~ /^\s*\/\*.*\*\/$/) # /* */ comments
  34.                         && ($_ !~ /^\s*\/\//)# // comments
  35.                         && ($_ !~ /^\s*$/) # empty line
  36.                 ){
  37. #                        print "Counted $count : $_";
  38.                         $count++;
  39.                 }
  40.         }
  41.         close(SRC);
  42.         return $count;
  43. }
复制代码
发表于 2004-4-28 16:20:26 | 显示全部楼层
好像有点小问题。
有单行注释/*……*/的情况,你试过吗?

另外我也想了个算法,你看看怎么样:

1、读入整个文件;
2、删除所有\和相邻的回车(包括中间的空格);
3、删除所有/*和*/之间的部分(包括中间的回车);
4、删除所有//和回车之间的部分;
5、删除所有的空行;
6、统计\n的数量,即所求的行数。
发表于 2004-4-29 00:05:18 | 显示全部楼层
最初由 BBDD 发表
好像有点小问题。
有单行注释/*……*/的情况,你试过吗?

这个我当时是测试过的, 没问题的。

  1. $_ !~ /^\s*\/\*.*\*\/$/) # /* */ comments
复制代码

这行代码就是做这个的。
不过现在在windows下,没装perl,没法测试了。

另外我也想了个算法,你看看怎么样:

1、读入整个文件;
2、删除所有\和相邻的回车(包括中间的空格);
3、删除所有/*和*/之间的部分(包括中间的回车);
4、删除所有//和回车之间的部分;
5、删除所有的空行;
6、统计\n的数量,即所求的行数。

感觉这样会比较有条理,思路很清晰,但效率会不会有所下降?
我现在所使用的算法中是,边处理行,边计算行数;而你的是处理完所有行之后再来统计行数。 时间复杂度跟空间复杂度都会有所增加。
发表于 2004-4-29 08:54:15 | 显示全部楼层
1、如果有/*……*/的话,它就会掉到
elsif($_ =~ /^\s*\/\*/)
这里,然后是while(my $next = <SRC>)和if($next =~ /.*\*\/(.*)/),但这个if可能永远也不会成立,直到EOF。

2、一次读入整个文件的效率要比一次读一行高得多,
一次处理整个文件的效率也比一次处理一行要高。
这样做可能多占了些内存,但我们现在讨论的是*.h和*.c,这样的文件通常不会很大,所以没问题。
发表于 2004-4-29 12:58:55 | 显示全部楼层

修改了一下

确实是存在单行/* */会出错的问题,我前面没发现是因为所使用的测试文件没选好。
修改后的代码如下:

  1. #!/usr/bin/perl -w
  2. #To count the lines for c/c++ header/source files, omitting comments, empty line, and joining the lines seperated by '\'.
  3. use strict;

  4. my $total = 0;
  5. foreach my $src(@ARGV){
  6. #        print "to count file $src\n";
  7.         my $lines = &countline($src);
  8.         $total += $lines;
  9.         print "\t$lines : $src\n";
  10. }
  11. print "\t$total : total\n";


  12. sub countline{
  13.         my $src = $_[0];
  14.         my $count = 0;
  15.         open(SRC, "<$src") or die("Can't open file $src for reading due to: $!\n");
  16.         READLINE:
  17.         while(<SRC>){
  18.                 if($_ =~ /\\$/){ #line to be continued
  19.                         $_ .= <SRC>;
  20.                         redo READLINE;
  21.                 }elsif($_ =~ /^\s*\/\*.*\*\/(.*)$/){ #single line comments, which may be followed by a statement/comments.
  22.                         $_ = $1;
  23.                         redo READLINE;
  24.                 }elsif(($_ =~ /^\s*\/\//)# // comments
  25.                         || ($_ =~ /^\s*$/) # empty line
  26.                 ){
  27.                         next;
  28.                 }elsif($_ =~ /^\s*\/\*/){ #multi-line comments begins
  29.                         while(my $next = <SRC>){
  30.                                 if($next =~ /.*\*\/(.*)/){ #comments may be followed by a statement which should be counted.
  31.                                         $_ = $1;
  32.                                         redo READLINE; #$_ may be comments too.
  33.                                 }
  34.                         }
  35.                 }else{
  36. #                        print "Counted line $count : $_\n";
  37.                         $count++;
  38.                 }
  39.         }
  40.         close(SRC);
  41.         return $count;
  42. }
复制代码

所选用的测试文件为:

  1. /*
  2. * =====================================================================================
  3. *
  4. *        Filename:  test.cpp
  5. *
  6. *     Description:  test clines.pl
  7. *
  8. *         Version:  1.0
  9. *         Created:  04/28/04 14:19:51 CST
  10. *        Revision:  none
  11. *        Compiler:  gcc
  12. *
  13. *          Author:  Shixin Zeng (pupilzeng), [email]shixinzeng@sjtu.edu.cn[/email]
  14. *         Company:  Shanghai Jiaotong University
  15. *
  16. * =====================================================================================
  17. */
  18. #include <iostream>
  19. using namespace std;

  20. int
  21. main()
  22. {
  23.         /* pure comments line */
  24.         int j = 0;
  25.         // pure comments lines.
  26.         /* comments followed by a statement */ int i = 0;
  27.         /* multi line comments
  28.          * followed by a statement
  29.          */ int j = 0;
  30.         char * str = "this is a very long\
  31.                           line";
  32.         /* comments followed by comments */ /*comments */
  33.         cout<< "hello, world\n";
  34.         /* multi-line comments
  35.          * fllowed by multi-line coments */ /* another
  36.                                                                                  * multi-line comments*/
  37.         return 0;
  38. }
复制代码

运行结果:
[php]
        12 : test.cpp
        12 : total
[/PHP]
发表于 2004-4-29 13:04:32 | 显示全部楼层
最初由 BBDD 发表

2、一次读入整个文件的效率要比一次读一行高得多,
一次处理整个文件的效率也比一次处理一行要高。
这样做可能多占了些内存,但我们现在讨论的是*.h和*.c,这样的文件通常不会很大,所以没问题。


不好意思,我是刚刚才学perl,还不知道怎么样一次读取整个文件。
发表于 2004-4-29 13:08:05 | 显示全部楼层
最初由 BBDD 发表
好像有点小问题。
有单行注释/*……*/的情况,你试过吗?

另外我也想了个算法,你看看怎么样:

1、读入整个文件;
2、删除所有\和相邻的回车(包括中间的空格);
3、删除所有/*和*/之间的部分(包括中间的回车);
4、删除所有//和回车之间的部分;
5、删除所有的空行;
6、统计\n的数量,即所求的行数。

这都是应用程序的做法,如果找到如sysctl的C源码,照PERL 写一个,就是啦。
发表于 2004-4-29 14:27:30 | 显示全部楼层
不用这么夸张吧?


  1. open FH, "test.c" or die "$!";
  2. $line=join '',<FH>; # we got a real big line...
  3. $line =~ s#/\*.*?\*/|//.*?$##gms; #well,strip the comments
  4. for(split /\n/, $line)
  5. {
  6.         next if (/^\s*$/);
  7.         print "$_\n";
  8.         $num++;
  9. }
  10. print $num, "\n";
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表