免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: 无风之谷
打印 上一主题 下一主题

ChinaUnix技术实践之三——Perl编程大赛 [复制链接]

论坛徽章:
27
CU大牛徽章
日期:2013-03-13 15:15:08CU大牛徽章
日期:2013-05-20 10:46:38CU大牛徽章
日期:2013-05-20 10:46:44CU大牛徽章
日期:2013-09-18 15:24:09CU大牛徽章
日期:2013-09-18 15:24:20CU大牛徽章
日期:2013-09-18 15:24:25CU大牛徽章
日期:2013-09-18 15:24:31CU大牛徽章
日期:2013-09-18 15:24:36CU大牛徽章
日期:2013-09-18 15:24:41CU大牛徽章
日期:2013-09-18 15:24:48CU大牛徽章
日期:2013-09-18 15:24:52处女座
日期:2013-09-27 17:45:43
41 [报告]
发表于 2011-02-26 23:33 |只看该作者
本帖最后由 yifangyou 于 2011-02-27 00:00 编辑
  1. ####################################################
  2. #系统环境:windows xp sp3,centos 5
  3. #编译环境:perl, v5.6.1 built for MSWin32-x86-multi-thread,perl, v5.8.8 built for i386-linux-thread-multi
  4. #执行:     perl 5.pl "E:\tmp" 或者 perl 5.pl
  5. #题目:
  6. #5. 用最短和优的perl代码对当前目录下的文件和子目录按修改时间进行排序。
  7. #
  8. ####################################################

  9. #全局结果集
  10. our %files;
  11. #读取目录名
  12. my $inputdir=$ARGV[0];
  13. if($inputdir eq ""){
  14.         $inputdir=".";
  15. }
  16. #当前目录下的文件和子目录按修改时间进行排序
  17. get_sub_files($inputdir);

  18. #对散列的修改时间字段进行排序
  19. printf "%10s %s\n", $files{$_},$_ foreach sort {$files{$a} <=> $files{$b};} keys %files;
  20. #my @f =sort {$files{$a} <=> $files{$b};} keys %files;
  21. #foreach my $f ( @f ){
  22. #   printf "%10s %s\n", $f,$files{$f};
  23. #}
  24. #递归获取该目录下的所有目录和文件,以及对应的修改时间
  25. sub get_sub_files{
  26.   my $dir = shift @_;
  27.   #打开目录
  28.   opendir(DIR,"$dir") || die "Error in opening dir $dir\n";
  29.   my @files =readdir(DIR);
  30.   closedir(DIR);
  31.   #遍历所有文件和目录
  32.   for $file (@files){
  33.           #排除当前遍历的目录和上一级的目录
  34.           if(!($file eq "" || $file eq "." || $file eq "..")){
  35.                   my $nextfile="$dir/$file";
  36.             $files{$nextfile}=(stat($file))[9];
  37.             #若是目录则递归变量下一级
  38.             if(-d $nextfile){
  39.                     get_sub_files($nextfile);
  40.             }
  41.           }
  42.   }
  43. }
复制代码

论坛徽章:
27
CU大牛徽章
日期:2013-03-13 15:15:08CU大牛徽章
日期:2013-05-20 10:46:38CU大牛徽章
日期:2013-05-20 10:46:44CU大牛徽章
日期:2013-09-18 15:24:09CU大牛徽章
日期:2013-09-18 15:24:20CU大牛徽章
日期:2013-09-18 15:24:25CU大牛徽章
日期:2013-09-18 15:24:31CU大牛徽章
日期:2013-09-18 15:24:36CU大牛徽章
日期:2013-09-18 15:24:41CU大牛徽章
日期:2013-09-18 15:24:48CU大牛徽章
日期:2013-09-18 15:24:52处女座
日期:2013-09-27 17:45:43
42 [报告]
发表于 2011-02-26 23:36 |只看该作者
本帖最后由 yifangyou 于 2011-02-26 23:58 编辑
  1. ####################################################
  2. #系统环境:windows xp sp3,centos 5
  3. #编译环境:perl, v5.6.1 built for MSWin32-x86-multi-thread,perl, v5.8.8 built for i386-linux-thread-multi
  4. #执行:     perl 6.pl 1,2,3,5,6,7,8,24,25,26,2
  5. #题目:
  6. #6.传入一串数字并返回所有大于平均值的数字。
  7. #
  8. ####################################################

  9. sub get_big_avg {
  10.                 my $total = 0;
  11.                 #计算总和
  12.                 for my $n (@_) {
  13.                         $total+=$n;
  14.                 }
  15.                 my $num=@_;
  16.                 #计算平均值
  17.                 my $avg=$total/$num;
  18.                 @result=();
  19.                 #比较获取大于平均值的数字
  20.     for my $n (@_) {
  21.                         if($n > $avg){
  22.                           push(@result,$n);
  23.                         }
  24.     }
  25.     return @result;
  26. }
  27. #例子
  28. #print "result:".join(",",join_int(1,2,3,5,6,7,8))."\n";

  29. #判断输入合法性
  30. if(!($ARGV[0]=~/(\d+,)*\d+/)){
  31.         die("please add a number list param like 1,2,3,5,6,7,8\n");
  32. }
  33. #分割成数组
  34. @input_list=split(/,/,$ARGV[0]);
  35. print "input :".join(",",@input_list)."\n";
  36. print "result:".join(",",get_big_avg(@input_list))."\n";
复制代码

论坛徽章:
27
CU大牛徽章
日期:2013-03-13 15:15:08CU大牛徽章
日期:2013-05-20 10:46:38CU大牛徽章
日期:2013-05-20 10:46:44CU大牛徽章
日期:2013-09-18 15:24:09CU大牛徽章
日期:2013-09-18 15:24:20CU大牛徽章
日期:2013-09-18 15:24:25CU大牛徽章
日期:2013-09-18 15:24:31CU大牛徽章
日期:2013-09-18 15:24:36CU大牛徽章
日期:2013-09-18 15:24:41CU大牛徽章
日期:2013-09-18 15:24:48CU大牛徽章
日期:2013-09-18 15:24:52处女座
日期:2013-09-27 17:45:43
43 [报告]
发表于 2011-02-26 23:37 |只看该作者
本帖最后由 yifangyou 于 2011-02-27 16:22 编辑
  1. ####################################################
  2. #系统环境:centos 5
  3. #编译环境:v5.8.8 built for i386-linux-thread-multi
  4. #执行:     perl 7.pl
  5. #题目:
  6. #7.让用户不断猜测范围从1到100的秘密数字,直到猜中为止。程序应该以魔术公式lnt(1+rand 100)来随机产生秘密数字。
  7. #当用户猜错时,程序应相应“too high”或者“too low”。
  8. #如果用户quit或者exit或者键入一个空白行程序就中止。当然如果用户猜到了,程序也应该中止。
  9. #
  10. ####################################################

  11. $min_number=1;
  12. $max_number=100;
  13. #获取随机数
  14. $rand_number=int($min_number+rand($max_number));
  15. print "program have create a randrom num between $min_number and $max_number,enter a number to guess it\n";
  16. print "or enter 'quit' or 'exit' or blank line to exit\n";
  17. $guess_time=0;
  18. while(<STDIN>){
  19.         #获取输入并转小写
  20.         $enter_str = lc($_);
  21.         #去掉空白字符
  22.         $enter_str =~ s/\s//g;
  23.         #判断是否是整数
  24.         if(!($enter_str=~/\d+/)){
  25.                 #判断是否退出
  26.                 if($enter_str eq "exit" || $enter_str eq "quit" || $enter_str eq ""){
  27.                         #退出
  28.                         print("sorry,you lose $guess_time times\n");
  29.                         die("exit ok\n");
  30.                 }
  31.                 print("please enter the number between $min_number and $max_number or enter 'quit' or 'exit' or blank line to exit\n");       
  32.         }else{
  33.                 $guess_time++;
  34.                 #判断是否相等
  35.                 if($enter_str==$rand_number){
  36.                         #相等则退出
  37.                         print("you win the number is $rand_number,you have guess $guess_time times\n");
  38.                         die("exit ok\n");
  39.                 }else{
  40.                         #提示输入的是大还是小
  41.                         if($enter_str > $rand_number){
  42.                                 print("too high,you lose $guess_time times\n");
  43.                         }else{
  44.                                 print("too low,you lose $guess_time times\n");
  45.                         }
  46.                 }
  47.         }
  48. }
复制代码
第8题
  1. #!/usr/bin/perl
  2. ####################################################
  3. #系统环境:centos 5
  4. #编译环境:perl, v5.8.8 built for i386-linux-thread-multi
  5. #执行:     perl 8.pl 或者 perl 8.pl 1234 (端口)
  6. #题目:
  7. #8. 写一个简单的TCP Echo Server,在linux/unix环境运行,侦听在特定端口,接受用户的网络输入,并返回同样的数据给对方,能接受quit命令。
  8. #基本要求:
  9. #(1)无阻塞IO。
  10. #(2)daemon方式运行。
  11. #(3)能接受kill -HUP重启信号
  12. # 发送hup信号命令:kill -s hup 进程号
  13. #
  14. ####################################################
  15. #use POSIX ();
  16. use FindBin ();
  17. use File::Basename ();
  18. use File::Spec::Functions;
  19. use IO::Socket::INET;
  20. use IO::Select;
  21. use Carp;
  22. our $server;
  23. our $server_port=5555;#默认端口
  24. our $zombies = 0;
  25. our $script = File::Basename::basename($0);
  26. our $logfile="/tmp/8.log";
  27. our $read_handles;

  28. # 获取重新启动命令
  29. our $SELF = "perl ".catfile $FindBin::Bin, $script;
  30. our $isrestart=0; #标识是否重新启动
  31. $SIG{CHLD} = sub {$zombies++};
  32. $SIG{HUP} = sub {
  33.         logs("get HUP,restart server");
  34.         $isrestart=1;
  35.         stopServer();
  36. };

  37. #从参数获取端口
  38. if(isPort($ARGV[0])){
  39.         $server_port=$ARGV[0];
  40. }
  41. #deamon方式
  42. daemonize();
  43. #启动服务
  44. startServer();
  45. exit;
  46. #函数部分-----------------------------------------------
  47. sub isPort{
  48.         my $port=shift(@_);
  49.         if($port=~/d+/){
  50.                 #判断端口合法性,必须是整数,并且大于1024
  51.                 if($port > 1024){
  52.                         return $port;
  53.                 }
  54.         }       
  55.         return 0;
  56. }

  57. #记录日志
  58. sub logs{
  59.         my $msg=shift;
  60.         open(LOGFILE,">>$logfile") or die("cannot open $logfile");
  61.                 my($sec,$min,$hour,$mday,$mon,$year)=localtime();
  62.         print LOGFILE sprintf("%04d-%02d-%02d %02d:%02d:%02d ",($year< 2000?($year+1900):$year),($mon+1),$mday,$hour,$min,$sec),$msg,"\n";
  63.         close(LOGFILE);
  64. }

  65. #deamon方式
  66. sub daemonize {
  67.     chdir '/'                 or croak "Can't chdir to /: $!";
  68.     open STDIN, '/dev/null'   or croak "Can't read /dev/null: $!";
  69.     open STDOUT, '>/dev/null' or croak "Can't write to /dev/null: $!";
  70.     defined(my $pid = fork)   or croak "Can't fork: $!";
  71.     exit if $pid;
  72.     setsid                    or croak "Can't start a new session: $!";
  73.     open STDERR, '>&STDOUT'   or croak "Can't dup stdout: $!";
  74. }

  75. # 停止或者重新启动server
  76. sub stopServer{
  77.         $server->close();
  78.         $read_handles->remove($server);
  79.         # 清除所有的客户端
  80.         foreach $fd ($read_handles->handles){
  81.                 $read_handles->remove($fd);
  82.                 close $fd;       
  83.         }
  84.         logs("server shutdown");
  85.         # 判断是否重新启动
  86.         if($isrestart==1){
  87.                 $isrestart=0;
  88.                 # 重新启动
  89.                 logs($SELF, @ARGV);
  90.                 exec($SELF, @ARGV) or die "Couldn't restart: $!\n";
  91.         }
  92.         exit;                    # 退出
  93. }
  94. # 启动server
  95. sub startServer{
  96.         # 创建套接字
  97.         $server = IO::Socket::INET->new(
  98.         LocalPort => $server_port,
  99.         Type    => SOCK_STREAM,
  100.         Reuse   => 1,
  101.         Listen   => 10,# 或者 SOMAXCONN
  102.   Blocking  => 0)# 设置非阻塞   
  103.         or die "Couldn't be a tcp server on port $server_port: $!\n";

  104.         $read_handles = IO::Select->new();
  105.   $read_handles->add($server);
  106.        
  107.         local  $| = 1;
  108.         logs("server start ok binding port $server_port\n");
  109.         my $fds;
  110.         while (1) {
  111.                 ($fds) =IO::Select->select($read_handles, undef, undef,0 );
  112.                 foreach $fd ( @$fds ){
  113.                          if( $fd== $server ){
  114.                                  if($server->opened){
  115.                                          #server收到新的客户端连接
  116.                                          my $client = $server->accept();
  117.                 $read_handles->add($client);
  118.               }else{
  119.                               #server被关闭了
  120.                               stopServer();
  121.                               last;
  122.               }
  123.                          }else{
  124.          $msg = <$fd>;           
  125.          if($msg){
  126.                  #获取输入并转小写
  127.                                   $enter_str = lc($msg);
  128.                                         #去掉回车
  129.                                         chomp $enter_str;
  130.                                         # 判断是否退出
  131.                                   if($enter_str eq "quit"){
  132.                                           logs("server quit");
  133.                                     stopServer();
  134.                                   }
  135.                  $fd->print($msg);
  136.          }else{
  137.                  # client has finished/closed
  138.                  $read_handles->remove($fd);
  139.                  close $fd;
  140.         }
  141.       }
  142.                 }
  143.         }
  144.         stopServer();
  145. }
复制代码
  1. ####################################################
  2. #系统环境:centos 5
  3. #编译环境:perl, v5.8.8 built for i386-linux-thread-multi
  4. #执行:     perl 8_client.pl 或者 perl 8_client.pl 127.0.0.1 5555
  5. #题目:
  6. #测试题目8的客户端,输入end:退出客户端;输入quit:发quit命令给服务端并退出客户端;
  7. #
  8. ####################################################

  9. use IO::Socket::INET;
  10. our $server_ip="127.0.0.1"; #默认IP
  11. our $server_port=5555;      #默认端口
  12. $msg="Why don't you call me anymore?\n";

  13. #从参数获取server的ip
  14. if(isIP($ARGV[0])){
  15.         $server_ip=$ARGV[0];
  16. }
  17. #从参数获取端口
  18. if(isPort($ARGV[1])){
  19.         $server_port=$ARGV[1];
  20. }

  21. $socket = IO::Socket::INET->new(PeerAddr =>$server_ip,
  22. PeerPort  => $server_port,
  23. Proto => "tcp",
  24. Type => SOCK_STREAM,
  25. Timeout=>1)
  26. or die "Couldn't connect to $server_ip:$server_port: $!\n";
  27. $socket->autoflush(1);
  28. print "enter something to send to server,enter 'quit' to shutdown server or enter 'end' to quit client\n";

  29. # 通过套接字发送某些东西,
  30. while(<STDIN>){
  31.         #获取输入并转小写
  32.         $enter_str = lc($_);
  33.         #去掉回车
  34.         chomp $enter_str;
  35.        
  36.         #判断是否退出
  37.         if($enter_str eq "end" || $enter_str eq "quit" ){
  38.                         #退出客户端
  39.                         print "exit ok\n";
  40.                         if($enter_str eq "quit"){
  41.                                 $socket->print($_);
  42.                                 print "send ok:$_\n";       
  43.                         }
  44.                         last;
  45.         }
  46.         $socket->print($_);       
  47.         print "send ok:$_\n";
  48.        
  49.         # 读取远端响应
  50.         $answer = <$socket>;
  51.         if($answer eq ""){
  52.                 last;
  53.         }
  54.         print "answer:$answer\n";
  55. }
  56. # 然后在结束之后终止联接。
  57. close($socket);

  58. sub isPort{
  59.         my $port=shift(@_);
  60.         if($port=~/d+/){
  61.                 #判断输入合法性
  62.                 if($port > 1024){
  63.                         return $port;
  64.                 }
  65.         }       
  66.         return 0;
  67. }

  68. sub isIP {
  69.         my $ip=shift(@_);
  70.         if($ip=~/d{3}\.d{3}\.d{3}\.d{3}/){
  71.                 my @ipn=split(".",$ip);
  72.                 for my $n (@ipn){
  73.                         if($n > 255){
  74.                                 return 0;       
  75.                         }
  76.                 }
  77.         }else{
  78.                 return 0;       
  79.         }
  80.   return 1;
  81. }
复制代码

论坛徽章:
1
CU十二周年纪念徽章
日期:2013-10-24 15:41:34
44 [报告]
发表于 2011-02-27 09:20 |只看该作者
6
  1. #!/usr/bin/perl -w

  2. my $sum = 0;
  3. my $average;
  4. foreach(@ARGV)
  5. {
  6.         $sum += $_;
  7. }
  8. $average = $sum / @ARGV;
  9. foreach(@ARGV)
  10. {
  11.         if($_ > $average)
  12.         {
  13.                 print $_;
  14.                 print "\n";
  15.         }
  16. }

复制代码

论坛徽章:
0
45 [报告]
发表于 2011-02-27 09:49 |只看该作者
第一题
  1. sub func{
  2.     $x = ...
  3.     $x;
  4. }
复制代码
其他的太难不会

论坛徽章:
1
CU十二周年纪念徽章
日期:2013-10-24 15:41:34
46 [报告]
发表于 2011-02-27 10:20 |只看该作者
7.
  1. #!/usr/bin/perl -w

  2. my $key = int(1 + rand 100);
  3. print"please input a number\n";
  4. while(my $guess = <STDIN>)
  5. {
  6.         chomp ($guess);
  7.         if( $guess eq "quit" || $guess eq "exit" || $guess =~/\s+/ )
  8.         {
  9.                 exit(1);
  10.         }
  11.         elsif($guess > $key)
  12.         {
  13.                 print "too high,please input again\n";
  14.         }
  15.         elsif($guess < $key)
  16.         {
  17.                 print "too low,please input again\n";
  18.         }
  19.         elsif($guess == $key)
  20.         {
  21.                 print "you got it,bye!\n";
  22.                 exit;
  23.         }
  24. }
复制代码

论坛徽章:
1
CU十二周年纪念徽章
日期:2013-10-24 15:41:34
47 [报告]
发表于 2011-02-27 10:51 |只看该作者
本帖最后由 rubylc_unix 于 2011-02-27 11:00 编辑

5.
  1. #!/usr/bin/perl -w
  2. print for ( system "tree -t");
复制代码

论坛徽章:
0
48 [报告]
发表于 2011-02-27 22:57 |只看该作者
本帖最后由 lkk2003rty 于 2011-03-14 15:14 编辑

1. 请正确的精简如下代码。

sub myfunc {
    # $x = ...;

    if ( $x ) {
        return 1;
    } else {
        return;
    }
}
  1. sub myfunc{
  2.         $x?1:return;
  3. }
复制代码
2. $x=()结果是什么?列表位于标量上下文是什么情况?()是不是用来创建空的list?请解释原因。
$x是undef
比如$x = (1, 2, 3)会使x被赋值为列表最后一个元素3
是的,可以用诸如@x = ();这样的语句来清空数组
3. 1,2,3,5,6,7,8 如何合并成1-3,5-8?
  1. #!/usr/bin/perl -w
  2. my @arr = (1, 2, 3, 5, 6, 7, 8);
  3. my $str = shift( @arr );
  4. my $pre = $str;
  5. my $flag = 0;
  6. foreach(@arr)
  7. {       
  8.         if($_ == $pre + 1)
  9.         {
  10.                 $pre = $_;
  11.                 $flag = 1;
  12.                 next;       
  13.         }
  14.         $str .= "-".$pre.",".$_;
  15.         $pre = $_;
  16.         $flag = 0;
  17. }
  18. if($flag == 1)
  19. {
  20.         $str .= "-".$pre;
  21. }
  22. print "$str\n";
复制代码
4.@x=(5,7,9); $x[1]与@x[1]的区别是什么?
$x[1]是数组x的第二个元素7,是一个标量
@x[1]是只有数组x第二元素7着一个元素的列表,是一个列表
5. 用最短和优的perl代码对当前目录下的文件和子目录按修改时间进行排序。
  1. #!/usr/bin/perl -w
  2. my $dh;
  3. my %files;
  4. opendir($dh,".") or die "Can't opendir \".\":$!";
  5. foreach my $file(readdir $dh) {
  6.         $files{$file} = (stat($file))[9];
  7. }
  8. foreach my $key(sort ascd(keys %files)) {
  9.         print "$key\n";
  10. }

  11. sub ascd {
  12.         $files{$a} <=> $files{$b};
  13. }
复制代码
6.传入一串数字并返回所有大于平均值的数字。
  1. echo "12 23  24 54 64 3 234  3      2" | perl -ane '$ave = 0; foreach(@F){ $ave += $_; } $ave /= @F; @big = grep {$_ > $ave} @F;print "@big";'
复制代码
7.让用户不断猜测范围从1到100的秘密数字,直到猜中为止。程序应该以魔术公式lnt(1+rand 100)来随机产生秘密数字。当用户猜错时,程序应相应“too high”或者“too low”。如果用户quit或者exit或者键入一个空白行程序就中止。当然如果用户猜到了,程序也应该中止。
  1. #!/usr/bin/perl -w
  2. use 5.010;
  3. my $num = int (1+rand 100);
  4. print $num."\n";
  5. print "Input your guess number!\n";
  6. while(<>)
  7. {
  8.         given($_)
  9.         {
  10.                 when( /^(quit)?(exit)?\s*\n$/ )
  11.                 {
  12.                         last;
  13.                 }
  14.                 when( /^\s*\d+\s*\n$/ )
  15.                 {
  16.                         chomp;                       
  17.                         if($num < $_)
  18.                         {
  19.                                 print "Too low\n";
  20.                         } elsif($num > $_)
  21.                         {
  22.                                 print "Too high\n";
  23.                         } else {
  24.                                 print "Bingo!U got it!";                       
  25.                         }
  26.                         next;               
  27.                 }
  28.                 print "Error input!\n";       
  29.         }
  30.        
  31. }
复制代码
8. 写一个简单的TCP Echo Server,在linux/unix环境运行,侦听在特定端口,接受用户的网络输入,并返回同样的数据给对方,能接受quit命令。
基本要求:
(1)无阻塞IO。
(2)daemon方式运行。
(3)能接受kill -HUP重启信号。
代码太长了 传文件上来吧 测试环境是 Linux Zealot 2.6.32.11-99.fc12.i686 #1 SMP Mon Apr 5 16:32:08 EDT 2010 i686 i686 i386 GNU/Linux
服务器端要以root启动。。。
ser.pl是服务端的代码
cli.pl是客户端的代码
code.rar (2.04 KB, 下载次数: 50)
总算是完成了。。。。

论坛徽章:
0
49 [报告]
发表于 2011-02-28 11:00 |只看该作者
才看到,占个地方。

1.
  1. sub myfuc {
  2. return unless $x||1;
  3. }
复制代码

论坛徽章:
59
2015七夕节徽章
日期:2015-08-24 11:17:25ChinaUnix专家徽章
日期:2015-07-20 09:19:30每周论坛发贴之星
日期:2015-07-20 09:19:42ChinaUnix元老
日期:2015-07-20 11:04:38荣誉版主
日期:2015-07-20 11:05:19巳蛇
日期:2015-07-20 11:05:26CU十二周年纪念徽章
日期:2015-07-20 11:05:27IT运维版块每日发帖之星
日期:2015-07-20 11:05:34操作系统版块每日发帖之星
日期:2015-07-20 11:05:36程序设计版块每日发帖之星
日期:2015-07-20 11:05:40数据库技术版块每日发帖之星
日期:2015-07-20 11:05:432015年辞旧岁徽章
日期:2015-07-20 11:05:44
50 [报告]
发表于 2011-02-28 11:06 |只看该作者
回复 43# yifangyou


    不愧是Perl强人啊。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP