这个问题的思考其实对于某一种语言而言,基本都能实现,只是简单和复杂而已。而此次我讨论就是只是在linux下面使用了shell和c对源代码进行行 数的讨论。本打算是实现一个python版本的,由于python这块还不是太熟,所以就等以后熟了把这块补上。

shell版

shell的强大快捷之处就在此体现出来了。我们使用find命令就直接能将目标的文件进行检索,然后我们就直接对检索出来的对象进行统计。统计 我们知道使用wc这个命令,但是我们观察一下wc的输出:

206 ./2014-03-09-jekyll-blog.md

前面是我们想要的内容,而后面的文件名却不是我们要得,怎么解决?一个思路就是将这个结果保存到一个文件中,然后使用cut等命令对文件进行改造,接着再去统计,这个方法个人感觉比较麻烦。那么第二个思路就是用awk,直接对我们的结果进行分割。按照思路二,那我们就对此进行编码了

  1. 使用find,对于find,参数较多,考虑到有时候源代码中目录层次不一,我们需要加上参数maxdepth, 再考虑到所统计的语言项目不一样,我们同样要指定name这个参数,而且采用一个简单的正则表达式。所以基本的find语句如下:

    find $1 -type f -maxdepth $2 -name "*.$3"

这边的$1是路径名 $2 指定的最大深度 $3 文件的后缀名或是一些正则的表达式,$3的这个设计我原先的打算是做一个test,根据用户输入,然后最后自己生成正则,感觉这样有点多此一举了。一个项目中使用的文件后缀一般不会很多,统计的是核心代码,所以这一块就可以简便一点了。

  1. 统计行数的核心就是如下的这个:

    w =(wc -l $file | awk "{print $1}")

这边的file就是之前find的返回值,我们将上面的这个代码放在一个循环中。这边是awk的最简单使用了,将一个记录的第一个字段打印出来。但是不要混淆了这边的$1和shell脚本的中的$1是不一样的,这在awk的命令中,所以不要担心会出错。

  1. 加一些修饰

我们为了让输出变得好看一点,对echo的输出加一些修饰,主要是颜色的修饰:

echo -e "$s: \e[1;32m $t \e[0m"
echo -e "\e[1,31m total: \e[1;32m $w \e[0m"

好了,至此一个基本上能够满足要求的代码统计的脚本就完成了,一个完整的版本可以到我的gist看。

效果截图

C版本

之所以想到使用c来统计,是因为这是在linux平台上,可以使用系统编程方面的一些东西来解决这个问题。因为这个不在标准c中提供对目录的操作 对于windows下面,我没有去研究,所以不好多加叙述。

我们来看看如何实现C版本的统计程序?首先等解决的就是一个文件遍历的问题,这个解决不了接下去的工作就不用考虑。好在在linux中提供了一个 dirent.h的头文件,相关的函数都在这里面。我们可以用的是opendir readdirtelldir seekdir closedir着几个函数,这写函数基本就是差不多了,还缺的一个就是更改目录的函数chdir这个函数的实现在unistd.h中,所以这些基本上就齐了。

readdir返回的是一个结构体,结构体中有一个参数d_name,这是保存的文件的名字,所以有了这个,我们就可以对其进行属性的判断了。因为我们要判断这是文件还是目录。

如何判断?没有shell中if [ -d filename ]这样快捷的判断,但是我们要想到的一点就是,这是在liunx中,一切皆文件,对于文件的属性的判断,我们可以利用lstat()

这个函数是在sys/stat.h中,我们使用lstat(filename,&statbuf) 然后就可以用宏还进行判断了S_ISDIR(statbuf.st_mode). 这样就解决了文件类型的判断。

接着我们来考虑如何来遍历一个文件夹呢?首先的着肯定是在一个循环下。因为一个目录下有时不止一个文件,但是对于不同的目录的时候呢?例如一个目录下的一个子目录,如何去实现遍历?我们考虑到的是使用递归,递归调用我们写的那个函数。因为每次读取的目录只有一个。而且当readdir 读到文件尾的时候回返回一个NULL。 也许你会问这个递归是如何实现的。我们在循环结束后,调用了chidr("..") 回到上层,这样就继续遍历。这就是递归终止的条件。

是时候统计代码了,我们剔除了目录的文件,剩下的就是真正的文件了。对于统计使用fgets来实现遍历一个文件,然后加个循环就解决问题。这边一个不好的就是没有办法去判断文件的类型,统计是对目录下所以的文件进行的统计,这一点不如shell的灵活。

下面是源代码,基本的思路就是这样,还要注意的一个细节是有两个特殊的目录就是...我们要忽略掉,不然会产生一个死循环。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <dirent.h> /*some functions option on dir*/
#include <sys/stat.h> #define MAXLINE 200 int linecount=0; /*for save the countline*/ int getLine(char *fname)
{
FILE *fp;
char line[MAXLINE];
int total = 0; fp = fopen(fname,"r"); while(fgets(line,200,fp) != NULL)
total++; return total;
} /*Recurse a the target dirent*/
void Recur_dir(const char *dir, int depth)
{
DIR *dp; /*dir pointer*/
struct dirent *entry; /*structure to save dir info*/
struct stat statbuf; /*use to charge which is dir and which is file*/ /*get the decriptor*/
if((dp = opendir(dir)) == NULL)
{
printf("cannot open directory:%s\n",dir);
fprintf(stderr,"opendir error:%s\n",strerror(errno));
exit(1);
} chdir(dir); /*enter into target dir*/
while((entry = readdir(dp)) != NULL)
{
lstat(entry->d_name,&statbuf);/*get the entry status*/
if(S_ISDIR(statbuf.st_mode))
{
/*is a dirctory and ignore the .. and .*/
if(strcmp(".",entry->d_name)== 0 || strcmp("..",entry->d_name) == 0)
continue;
//printf("%*s%s\n",depth,"",entry->d_name);
Recur_dir(entry->d_name,depth+4); /*continue to open */
}
else /*if not a dirctroy and we count the line*/
{
linecount += getLine(entry->d_name); /*count everyfile line*/
}
} chdir("..");
closedir(dp);
} int main(int argc, const char *argv[])
{
char *topdir = "."
if(argc > 2)
{
printf("Usage:%s dir\n",argv[0]);
exit(1);
}
if(argc == 2)
{
topdir = argv[1];
} Recur_dir(topdir,0);
printf("Total:%d\n",linecount);
return 0;
}

如果不提供参数,就遍历当前目录,提供了就统计给出的目录。

效果截图

<转>统计源代码行数的一些实现方法的更多相关文章

  1. c#统计代码行数

    小编,已经快学了两年编程了.昨天突发奇想,想统计下这些年到底写过多少行代码,于是做了一个这个小程序来统计代码行数.老规矩,先上图. 比较惭愧,写了两年只有2万多行.那我们还是进入下一项吧. 界面搭建我 ...

  2. Eclipse统计代码行数

    开发过程中,经常需要统计代码行数,这时可以通过Eclipse的Search功能来实现. 步骤: 1.在Package Explorer中选中需要统计的包: 2.单击菜单Search-->File ...

  3. 在Flash Builder或者Eclipse统计代码行数的方法

    在Flash  Builder或者Eclipse统计代码行数的方法如下图菜单栏--搜索--搜索文件

  4. 【Linux】常用命令-统计代码行数

    公司人员流动大,经常有新的维护任务,交接时喜欢看看新来的模块的代码量,那么问题来了, 如何统计代码行数? 1,最先想到的肯定是 wc. wc -l *.h 将查看[当前目录]下头文件的代码行数,输出结 ...

  5. (转载)MySQL 统计数据行数 Select Count

    (转载)http://www.5idev.com/p-php_mysql_select_count.shtml 统计数据行数 SELECT COUNT() FROM 语法用于从数据表中统计数据行数. ...

  6. Shell脚本统计文件行数

    Shell脚本统计文件行数 转自 http://www.jb51.net/article/61943.htm    示例:row_count.sh文件 awk '{print NR}' row_cou ...

  7. 【未解决】对于使用Windows的IDEA进行编译的文件,但无法在Linux系统中统计代码行数的疑问

    在我学习使用Windows的IDEA的过程中,将代码文件转移到Linux虚拟机当中,但无法在Linux系统中统计代码行数. 注意:拷贝进虚拟机的文件均能编译运行. 具体过程如下: root@yogil ...

  8. Visual Studio 统计代码行数

    介绍一种简单的统计代码行数的小技巧, 使用正则表达式,用VS强大的查找功能 b[^:b#/]+.$ 最后结果:

  9. 用django统计代码行数+注释行数

    实现统计代码行数: 1.首先在url.py中配置 from django.conf.urls import url from django.contrib import admin from app0 ...

随机推荐

  1. SVN仓库导入文件

    分两种: 1.导入文件版本库从0开始 (适合新项目) 2.将其他SVN服务器中的版本库导入进来,版本库继承原SVN服务器的(适合SVN版本库迁移) 第一种: #mkdir –p /home/code/ ...

  2. PHP统计当前在线用户数实例

    HTML 我们在页面上放置一个显示当前在线人数的div#total以及一个用于展示访客地区分布的列表#onlinelist,默认我们在列表中放置一张与加载动画图片,后面我们用jQuery控制当鼠标滑向 ...

  3. Windows 2003 IIS 不支持ASP的问题

    Windows 2003 IIS 不支持ASP的问题 问题: HTTP 错误 404 - 文件或目录未找到. Internet 信息服务 (IIS) 第一步,启用Asp,进入:控制面板 -> 管 ...

  4. 只读事务(@Transactional(readOnly = true))的一些概念

    念:从这一点设置的时间点开始(时间点a)到这个事务结束的过程中,其他事务所提交的数据,该事务将看不见!(查询中不会出现别人在时间点a之后提交的数据) 应用场合: 如果你一次执行单条查询语句,则没有必要 ...

  5. Bi-shoe and Phi-shoe 欧拉函数 素数

    Bamboo Pole-vault is a massively popular sport in Xzhiland. And Master Phi-shoe is a very popular co ...

  6. c++ 打飞机游戏开发日志

    设计思路:控制台模式 初始化: 建立画面,初始化数据 游戏过程: 1.获取操作 2.修改数据 3.更新画面 结束: 关闭画面,delete动态分配数据 4.29日 创建游戏背景,实现飞机移动操作,实现 ...

  7. 关于Excel导入导出POI工具类

    import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import ...

  8. IT人才异军突起 有招网引领业界精英

    随着网络时代的到来,IT人才也在不断的增长.当然,不仅IT行业对IT人才需求旺盛.部分传统企业为打造互联网时代下的企业,也在紧锣密鼓的招聘IT人才.据统计.眼下我国各地对IT人才的需求已经占领总体人才 ...

  9. 4443: [Scoi2015]小秃玩矩阵|二分答案|匈牙利

    第K大看成第K小各种WA. .. 第K大也就是第n−K+1小.所以就能够愉快的二分答案了 二分答案找出比当前答案小的数的位置的坐标.推断一下能否够选出满足不在同一行同一列的n−K+1个数,然后就能够愉 ...

  10. 我的IIS7.5竟然不支持ASP.NET路由

    MVC模式下那些友好,屏蔽具体物理文件的URL让我眼馋,咱也想在WEB FORM项目用上一用. 按照指引,添加global.asax,写上路由代码什么的: <%@ Application Lan ...