Chinaunix首页 | 论坛 | 博客
  • 博客访问: 103056
  • 博文数量: 31
  • 博客积分: 115
  • 博客等级: 民兵
  • 技术积分: 165
  • 用 户 组: 普通用户
  • 注册时间: 2011-10-19 16:02
文章分类
文章存档

2013年(1)

2012年(9)

2011年(21)

分类:

2011-12-14 01:51:50

先看一个具体的程序例子,假设我们要实现一个简单的ls命令,它打印出给定目录下的所有文件的文件名。代码如下:

  1. void ls(char *dir_name){
  2.     struct dirent * dp;
  3.     DIR * dirp = opendir(dir_name);
  4.     if(dirp==NULL) return;
  5.     while ((dp = readdir(dirp)) != NULL){
  6.         printf("%s\n",dp->d_name);
  7.     }
  8.     closedir(dirp);
  9. }
然后在另外一个程序中需要在给定目录下查找以find_str开头,文件大小大于min_byte字节的文件。代码如下:
  1. void find(char *dir_name, char *find_str, int min_byte){
  2.     struct dirent * dp;
  3.     DIR * dirp = opendir(dir_name);
  4.     if(dirp==NULL) return;
  5.     while ((dp = readdir(dirp)) != NULL){
  6.         if(strncmp(dp->d_name, find_str, strlen(find_str))==0){
  7.             struct stat statbuf;
  8.             char buf[1024]={0};
  9.             strcat(buf,dir_name);
  10.             strcat(buf,dp->d_name);
  11.             if (stat(buf, &statbuf) !=-1){
  12.                 if(statbuf.st_size>=min_byte) printf("%s, %d\n",dp->d_name, (int)statbuf.st_size);
  13.             }
  14.         }
  15.     }
  16.     closedir(dirp);
  17. }

上面两个代码块中,有很多行代码是重复的。这部分重复的代码用于控制迭代一个目录。一个杰出程序员一定会对这种代码重复深恶痛绝。对这类控制流代码的抽象化就需要闭包来支持了。比如在Ruby中实现类似的功能是很方便的。实现ls的ruby代码如下:

  1. Dir.open(".").each {|x| puts x}
实现文件名和文件大小查询的ruby代码如下:

  1. def find(dir,find_str,min_byte)
  2.   Dir.open(dir).each do |x|
  3.     full_path = dir+x
  4.     puts x if x.start_with?(find_str) && File.size(full_path)>min_byte
  5.   end
  6. end
如果能够在C语言中实现类似ruby中each方法生活该多美好!

参照ruby的写法,理想的C语言的API如下:

  1. typedef void (*pDirentVisitor)(struct dirent * dp);

  2. extern void each(pDirentVisitor visitor, char *dir_name);
其中库作者需要实现each函数,而调用者实现pDirentVisitor函数。

要在C语言中实现这个特性,可以有三种方法:利用GCC的nested function,利用Clang的block,以及自己实现闭包参数传递。这里的难点在于pDirentVisitor函数中要能访问dir_name、find_str、min_byte这些context相关的本地局部变量,这就是闭包的含义。

本文中代码的完整可运行版本放在了Github:


下一篇文章中会讲解如何利用GCC的nest function实现上面的接口。

阅读(874) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~