软工作业二:Word Count

GitHub地址:https://github.com/Guyuefangzheng/Word-Count

项目要求

wc.exe 是一个常见的工具,它能统计文本文件的字符数、单词数和行数。这个项目要求写一个命令行程序,模仿已有wc.exe 的功能,并加以扩充,给出某程序设计语言源文件的字符数、单词数和行数。

实现一个统计程序,它能正确统计程序文件中的字符数、单词数、行数,以及还具备其他扩展功能,并能够快速地处理多个文件。
具体功能要求:
程序处理用户需求的模式为:

wc.exe [parameter] [file_name]

基本功能列表:

wc.exe -c file.c //返回文件 file.c 的字符数 (实现)

wc.exe -w file.c //返回文件 file.c 的词的数目 (实现)

wc.exe -l file.c //返回文件 file.c 的行数 (实现)

扩展功能:
-s 递归处理目录下符合条件的文件(实现)
-a 返回更复杂的数据 (实现)

2、psp表

*PSP2.1* *Personal Software Process Stages* *预估耗时(分钟)* *实际耗时(分钟)*
Planning 计划 60 30
·Estimate · 估计这个任务需要多少时间 60 30
Development 开发 1220
· Analysis · 需求分析 (包括学习新技术) 150 180
· Design Spec · 生成设计文档 40 20
·Design Review · 设计复审 (和同事审核设计文档) 40 20
·Coding Standard · 代码规范 (为目前的开发制定合适的规范) 30 20
· Design · 具体设计 60 60
· Coding · 具体编码 600 360
· Code Review · 代码复审 100 60
· Test · 测试(自我测试,修改代码,提交修改) 200 150
Reporting 报告 120
· Test Report · 测试报告 60 30
·Size Measurement · 计算工作量 30 30
· Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 30 30
合计 1400

3、解题思路

​ 一开始看到题时想的是用c来实现还是用Java,最后还是选择了熟悉的c。这次的题目涉及到的知识点命令行参数、文件操作这两部分以前没有去深究,因为书都在学校,所以面向搜索引擎来学习这部分的内容。

4、设计实现过程

​ 每一个功能一个函数,再加上一个main函数一共六个函数,在这几个功能模块中WordCount()调用CharCount()来判断该文件是否为空,SearchFile()调用三个基础功能的函数来实现批量操作。

5、代码说明

头文件

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<io.h>
#include<time.h>

基本功能:获取字符数

int CharCount(char *file){  //字符数统计 
    FILE *fp = NULL;
    fp = fopen(file,"r");
    if(fp==NULL){
        printf("没有找到此文件!\n");
        exit(-1);
    }
    
    int Ccount = 0;
    char temp;
    while(!feof(fp)){   //文件结束判断 
        temp = fgetc(fp);
        if(temp!=' '&&temp!='\n'&&temp!='\t'&&temp!=EOF)
            Ccount++;
    } 
    fclose(fp);
    return Ccount; 
}

首先判断该文件是否存在,不存在就退出,不是一个有效字符有四种情况:空格、换行、缩进格、txt文件结束符。

.
基本功能:获取词数

int WordCount(char *file){  //词数统计 
    if(CharCount(file)==0)
        return 0;
        
    int Wcount = 0;
    bool b = 0; //用来标记是否是字符 
    char temp;
    FILE *fp = NULL;
    fp = fopen(file,"r");
    while(!feof(fp)){
        temp = fgetc(fp);
        if(temp==' '||temp=='\t'||temp=='\n'||temp==EOF){   //四种情况,包括文件结束 
            if(b==1){    //前面是字符,词数+1 
                Wcount++;
                b = 0;
            }
        } 
        else
            b = 1;  //如果是字符,b标记为1 
    }
    fclose(fp);
    return Wcount;
}

通过调用字符统计函数来判断该文件是否存在和是否为空,用一个bool变量来标记,当bool值为1时词数加一。

.
基本功能:获取行数

int LineCount(char *file){  //行数统计 
    FILE *fp = NULL;
    fp = fopen(file,"r");
    if(fp==NULL){
        printf("没有找到此文件!\n");
        exit(-1);
    }
    
    int Lcount = 1;
    char temp;
    while(!feof(fp)){
        temp = fgetc(fp);
        if(temp=='\n')
            Lcount++;
    }
    fclose(fp);
    return Lcount;
}

行数初始为1,遇到\n加1。

.
扩展功能:处理目录下符合条件的文件

int SearchFile(){   //处理目录下符合条件的文件
    struct _finddata_t fileinfo;    //文件存储信息结构体 
    long fHandle;   //保存文件句柄
    int t=0;    //文件数记录器
    fHandle = _findfirst("*.txt",&fileinfo);    //查找当前目录下的txt文件
     
    if(fHandle==-1L)
        printf( "当前目录下没有txt文件\n");
    else
        do{
            t++; 
            printf("找到文件:%s\n",fileinfo.name);
            printf("字符数为:%d\n",CharCount(fileinfo.name));
            printf("词数为:%d\n",WordCount(fileinfo.name));
            printf("行数为:%d\n\n",LineCount(fileinfo.name));
        }while(_findnext(fHandle,&fileinfo)==0);
        _findclose(fHandle);    //关闭文件链接
        return t; 
}

通过头文件io.h中的文件结构体 _finddata_t ,使用 _findfist 和 _findnext 两个函数来查找文件,找到文件,调用基础模块。

.
扩展功能:返回更复杂的数据(代码行 / 空行 / 注释行)

int MoreLine(char *file){   //返回更复杂的数据(代码行 / 空行 / 注释行)
    FILE *fp = NULL;
    fp = fopen(file,"r");
    if(fp==NULL){
        printf("没有找到此文件!\n");
        exit(-1);
    }
    
    int nNum = 0,cNum = 0,aNum = 0;
    bool b = 0; // 
    int c;
    char temp;
    while(!feof(fp)){
        temp = fgetc(fp);
        if(temp=='\n'||temp==EOF){  //换行或者文件结束 
        //在换行或者文件结束时判断出类型 
            if(c==0)    //空行 
                nNum++;
            else if(c==1){  //代码行 
                cNum++;
                c = 0;
            }
            else{   //注释行 
                aNum++;
                c = 0;
            }
        }
        else if(temp!=' '&&temp!='\t'&&temp!='{'&&temp!='}'){
            //判断出代码行和注释行,剩下的即是空行 
            if(temp=='/'){
                if(c==0&&b==0)
                    b = 1;
                else if(c==0&&b==1){
                    c = 2;
                    b = 0;
                }
            } 
            else if(c!=2)
                c = 1;   
        }
    }
    fclose(fp);
    printf("空行数为:%d\n",nNum);
    printf("代码行数为:%d\n",cNum);
    printf("注释行数为:%d\n",aNum);
    return nNum+cNum+aNum;
}

//设置两个标记变量,一个整形变量用0,1,2来标记该行是空行、代码行还是注释行,一个bool变量用来判断注释行。标记所有的代码行和注释行,剩下的就都是空行了。

.
main函数

int main(int argc,char *argv[]){
    clock_t start_t,finish_t;
    double Total_time;
    if(!strcmp(argv[1],"-c")){
        start_t = clock();
        printf("charnumber: %d\n",CharCount(argv[2]));
        finish_t = clock();
        Total_time = (double)(finish_t - start_t) / CLOCKS_PER_SEC;//将时间转换为秒
        printf("%f seconds\n",Total_time);
    }
    else if(!strcmp(argv[1],"-w")){
        start_t = clock();
        printf("wordnumber: %d\n",WordCount(argv[2]));
        finish_t = clock();
        Total_time = (double)(finish_t - start_t) / CLOCKS_PER_SEC;//将时间转换为秒
        printf("%f seconds\n",Total_time);
    }   
    else if(!strcmp(argv[1],"-l")){
        start_t = clock();
        printf("linenumber: %d\n",LineCount(argv[2]));
        finish_t = clock();
        Total_time = (double)(finish_t - start_t) / CLOCKS_PER_SEC;//将时间转换为秒
        printf("%f seconds\n",Total_time);
    }
    else if(!strcmp(argv[1],"-s")){
        start_t = clock();
        printf("find txt number: %d\n",SearchFile());
        finish_t = clock();
        Total_time = (double)(finish_t - start_t) / CLOCKS_PER_SEC;//将时间转换为秒
        printf("%f seconds\n",Total_time);
    }
    else if(!strcmp(argv[1],"-a")){
        start_t = clock();
        MoreLine(argv[2]);
        finish_t = clock();
        Total_time = (double)(finish_t - start_t) / CLOCKS_PER_SEC;//将时间转换为秒
        printf("%f seconds\n",Total_time);
    }
    else
        printf("请输入正确的指令!\n");
}

用头文件time.h中的 clock_t 函数来计算时间。

6、测试运行

7、项目小结

1、这次项目暴露出了我其实对c语言还只是处于最基础的了解,文件操作、时间函数都不熟悉,都是现找现做的,需要加深学习
2、没能对项目的完成时间有个正确的预估,对如何估算PSP的时间还需学习
3、查资料的时候注意到一点,feof(FILE *fp)如果文件结束,则返回非0值,否则返回0,但是读完最后一个字符后,fp->flag仍然没有被设置为_IOEOF,因为还有个文件结束符,直到再次调用fgetc(),feof()才能探测到文件结尾。并且不应用EOF来代替feof(),因为fgetc()返回-1时有两种情况:读到文件结尾或是读取错误。

猜你喜欢

转载自www.cnblogs.com/cheng-/p/12485370.html