您的位置:首页 > 运维架构 > Linux

20150123 【 Linux-C 文件目录操作 】 统计代码行数

2015-01-24 09:46 260 查看
主要是老师要求每天200行,

于是就写了一个用来 统计文件内代码行数的程序。

程序执行时,加上文件夹路径和文件后缀(其实是文件名的片段),

就能统计出 此文件夹下的该类文件的行数以及有效行数(一些用于格式调整【空格,制表,回车】的不算)。

----------------------------

本来还想把注释也干掉的,

可是注释两种情况(单行//和多行/**/)

其中单行好处理;

但是多行要跨行,比较麻烦

所以我就一视同仁,没有处理注释了。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>

#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <errno.h>

/**
* 默认文件目录路径	NOW_PATH
* 最大文件目录长度	DIR_LEN
* 最大文件名长度	FILE_LEN
* 最大文件数		FILE_NUM
* 默认文件后缀		SUFFIX_NAME
*/
#define NOW_PATH	"."
#define DIR_LEN		1024
#define FILE_LEN	512
#define FILE_NUM	520
#define SUFFIX_NAME	".c"

//错误描述符
const enum ERROR_STATE{OpenProgarmError=0x77889900, OpenDirError, OpenFileError};

//空白符号集合 blank_char	空白符号数目 blank_len
const char blank_char[] = {'\n', '\t', ' ', '\\', '\0'};
const int blank_len = sizeof(blank_char);

//默认文件目录路径 dirPath	默认文件后缀 fileSuffix
char dirPath[DIR_LEN]  = NOW_PATH;
char fileSuffix[FILE_LEN] = SUFFIX_NAME;

//字符串容器 tempStr	文件数 fLen
char tempStr[(DIR_LEN+FILE_LEN)<<2];
int fLen = 0;

/**
* 文件属性结构体 fileAttr
* 	文件描述号 fd
* 	文件行数 len
* 	文件有效行数 noLen
* 	文件名称 name
*/
typedef struct _fileAttr
{
int	fd;
int	len;
int	noLen;
char	name[FILE_LEN];
}fileAttr;

//文件属性组
fileAttr fAttr[FILE_NUM];

/**	判断字符串是否都是由空白字符组成的
* 输入参数:	指向目标字符串的字符指针*ss
* 函数功能:	判断该字符串是否都是由空白字符(blank_char集合)组成
* 输出参数:	1:都由空白字符组成	0:不是非空字符串
*/
int is_blank_line(char *ss)
{
int i=0, j=0, ssLen=0;

//遍历 目标字符串 (一共 ssLen 个字符)
for(i=0, ssLen=strlen(ss); i<ssLen; i++)
{
//简单粗暴的暴力查找(其实可以使用更快的数组定位,但是闲麻烦,就没写了)
for(j=0; j<blank_len && blank_char[j]!=ss[i] ; j++);

/*
* 正常情况下(都不是空白字符),
* 	遍历完 blank_char 集合才退出
* 	(此时j=blank_len,说明是非空字符串)
*/
if( j==blank_len )
return 0;
}
return 1;
}

/**	计算该文件的行数(所有行数,有效行数)
* 输入参数:文件属性结构体指针 fa
* 函数功能:获取该文件所有行,算出有效行数
* 输出参数:无
*/
void counter_line(fileAttr *fa)
{
int i=0;

//把文件描述号 fAttr.fd 转换成 文件描述指针
FILE * fp = fdopen(fa->fd, "r");
while( !feof(fp) )
{
/*
* 读入一行(假设一行不超过 (DIR_LEN+FILE_LEN)<<2 个字符 )
* 统计行数(有效行数)
*/
fgets(tempStr, (DIR_LEN+FILE_LEN)<<2, fp);
fa->len++;
fa->noLen += !is_blank_line(tempStr);
}
}

/**	输出该文件目录下所有文件的统计情况
* 输入参数:无
* 函数功能:把文件目录内所有文件信息输出
* 输出参数:无
*/
void show_code_counter(void)
{
int i=0;

//统计行数,非空行数
int sumLine=0, sumNoLine=0;

//输出标题行(当前路径;文件后缀;序号,代码行数,有效行数,文件名称)
printf("\t当前路径:\"%s\"\n", dirPath);
printf("\t文件后缀:\"%s\"\n", fileSuffix);
printf("---------------------------------------\n");
printf("%4s %8s %8s %s\n", "序号", "代码行数", "有效行数", "文件名称");

//计算该目录下所有文件
for(i=0; i<fLen; i++)
{

//该文件属性( fAttr.len , fAttr.noLen )初始化
fAttr[i].len = fAttr[i].noLen = 0;

//计算该文件行数 fAttr.len , 有效行数 fAttr.noLen
counter_line(&fAttr[i]);

//输出文件描述号,文件行数,有效行数,文件名称
printf("%4d %8d %8d %s\n", fAttr[i].fd, fAttr[i].len, fAttr[i].noLen, fAttr[i].name);

//统计文件 总行数 sumLine , 有效行数 sumNoLine
sumLine += fAttr[i].len;
sumNoLine += fAttr[i].noLen;
}

//输出统计信息 总行数 sumLine , 有效行数 sumNoLine
printf("---------------------------------------\n");
printf("一共有 %d 个文件,合计 %d 行,有效 %d 行......\n\n\n", fLen, sumLine, sumNoLine);
}

int main(int argc, char **argv)
{
int i=0;

//程序是否正确打开,失败返回 OpenProgarmError
if( argc <= 0 )
{
fprintf(stderr, "「程序运行出错」...\n\n");
exit( OpenProgarmError );
}

//如果追加路径,则更新文件目录路径 dirPath

if( argc >= 2 )
{
strncpy(dirPath, argv[1], DIR_LEN);
}

//如果追加文件后缀,则更新文件后缀 fileSuffix
if( argc >=3 )
{
strncpy(fileSuffix, argv[2], FILE_LEN);
}

//打开文件目录目录 fdDir,失败返回 OpenDirError
DIR * fdDir = opendir(dirPath);
if( fdDir == NULL )
{
fprintf(stderr, "「打开目录出错」 %s\n\n", dirPath);
exit( OpenDirError );
}

/**
* 目录内容结构体 f_dirent,
* 	获取目录内所有文件;
* 文件信息有:
* 	文件描述号 fAttr.fd
* 	文件名 fAttr.name
*/
struct dirent * f_dirent = NULL;
while( ( f_dirent=readdir(fdDir) ) != NULL )
{
//查找目标文件(具有 fileSuffix 后缀的文件)
if( strstr(f_dirent->d_name, fileSuffix) )
{

//获取文件的绝对或相对路径dirPath/fAttr.name(文件目录路径/文件名)
snprintf(tempStr, (DIR_LEN+FILE_LEN)<<2, "%s/%s", dirPath, f_dirent->d_name);

//获取文件描述号 fd 和文件名 name

fAttr[fLen].fd = open(tempStr, O_RDONLY);
strncpy(fAttr[fLen].name, f_dirent->d_name, FILE_LEN);

//文件是否打开,失败返回 OpenFileError
if( fAttr[fLen++].fd < 0 )
{
fprintf(stderr, "「打开文件失败」 %s\n\n", tempStr);
exit( OpenFileError );
}
}
}

/*
* 输出文件目录路径 dirPath 和文件后缀 fileSuffix
* 以及该路径下所有目标文件的:
* 文件描述号fd ,文件行数len ,有效行数noLen ,文件名称name
* 总计 行数sumLine 和 有效行数sumNoLine
*/
show_code_counter();

/*
* 关闭文件目录 fdDir
* 关闭所有文件 fAttr.fd
*/
closedir( fdDir );
for(i=0; i<fLen; i++)
{
close( fAttr[i].fd );
}

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: