个人项目作业——wc.exe
个人项目作业——wc.exe
1.Github项目地址:
https://github.com/Vicky-Leung/wc.exe
2.PSP表格:
| PSP2.1 | Personal Softwear Process Stages |
预估耗时 (分钟) |
实际耗时 (分钟) |
| Planning | 计划 | 20 | 20 |
| Estimate | 估计这个任务需要多少时间 | 10 | 10 |
| Development | 开发 | 240 | 240 |
| Analysis | 需求分析(包括学习新技术) | 120 | 240 |
| Design Spec | 生成设计文档 | 20 | 20 |
| Design Review | 设计复审 | 0 | 0 |
| Coding Standard | 代码规范 | 10 | 10 |
| Design | 具体设计 | 60 | 60 |
| Coding | 具体编码 | 60 | 60 |
| Code Review | 代码复审 | 60 | 60 |
| Test | 测试 | 30 | 60 |
| Reporting | 报告 | 30 | 30 |
| Test Report | 测试报告 | 30 | 30 |
| Size Measurement | 计算工作量 | 10 | 10 |
| Postmortem&Process Improvement Plan | 事后总结,并提出过程改进计划 | 30 | 30 |
|
合计 |
730 | 880 |
3.解题思路:
- 语言选择:C语言,虽然说其实用C++,C#,java做这个设计会简单一些,没那么乱,但可惜我不会啊,于是便选择了C语言
- 因为是要打开文件,对文件内容进行阅读的,所以先想到的是用fopen打开指定路径下的文件,用fgetc进行阅读
- 递归函数这边因为要用到文件的信息,涉及_finddata_t file结构体
4.设计实现过程:
- 先设置一个主函数,利用主函数调用各个功能
-
基本功能
-c //返回文件 file.c 的字符数
-w //返回文件 file.c 的词的数目
-l //返回文件 file.c 的行数 -
扩展功能
-s 参数 //递归处理目录下符合条件的文件。(有bug)
-a 参数 //返回更复杂的数据(代码行 / 空行 / 注释行)(未完成) -
高级功能(未完成)
基本的Windows GUI 程序操作
支持通过图形界面选取文件
支持通过图形界面展现文件的信息
5.代码说明:
1 #include <stdio.h> 2 #include <string.h> 3 #include <stdlib.h> 4 #include <io.h> 5 #include<Windows.h> 6 #define OK 1 7 8 9 /*----------主函数----------*/ 10 int main(){ 11 char ask[10],fname[100]; //ask记录功能,fname记录文件名 12 attention(); //引用注释函数 13 while(1){ 14 15 printf("\n请输入功能请求:wc.exe-"); 16 scanf("%s",&ask); 17 18 if(ask[0]=='c'){ //统计字符数 19 printf("请输入文件路径及文件名:"); 20 scanf("%s",&fname); 21 int charnum=0; 22 charnum=Cnum(fname); 23 printf("文件的字符数为:%d\n",charnum); 24 continue; 25 } 26 27 else if(ask[0]=='w'){ //统计词的数目 28 printf("请输入文件路径及文件名:"); 29 scanf("%s",&fname); 30 int wordnum=0; 31 wordnum=Wnum(fname); 32 printf("文件的单词数为:%d\n",wordnum); 33 continue; 34 } 35 36 else if(ask[0]=='l'){ //统计行数 37 printf("请输入文件路径及文件名:"); 38 scanf("%s",&fname); 39 int linenum=0; 40 linenum=Lnum(fname); 41 printf("文件的行数为:%d\n",linenum); 42 continue; 43 } 44 45 else if(ask[0]=='s'){ //递归处理目录下符合条件的文件 46 char add[200]; //add用于记录文件夹地址 47 char type[10]; //typ用于记录文件类型 48 printf("\n请输入文件夹路径:"); 49 scanf("%s",&add); /* add=C:\Users\jennifer\Desktop\软工2 */ 50 printf("\n请输入需要提取的文件类型:*."); 51 scanf("%s",&type); /* type=c */ 52 find(add,type); 53 continue; 54 } 55 56 /* else if(ask[0]=='a'){ //返回更复杂的数据(代码行 / 空行 / 注释行) 57 printf("请请输入文件路径及文件名:"); 58 scanf("%s",&fname); 59 more(fname); 60 continue; 61 } (未完成)*/ 62 63 else if(ask[0]=='0'){ //退出程序 64 printf("感谢您使用本程序!\n"); 65 exit(0); 66 } 67 68 else{ //输入错误 69 printf("请以正确的格式输入!"); 70 continue; 71 } 72 73 }//end while 74 return 0; 75 }//end main
1 int attention(){ /*注释函数*/ 2 printf("\n"); 3 printf("基本功能列表: \n"); 4 printf("输入'c':返回文件 file.c 的字符数\n"); 5 printf("输入'w':返回文件 file.c 的词的数目\n"); 6 printf("输入'l':返回文件 file.c 的行数\n"); 7 printf("输入's':递归处理目录下符合条件的文件\n"); 8 //printf("输入'a':返回更复杂的数据(代码行 / 空行 / 注释行)\n"); 9 printf("输入'0':退出程序\n"); 10 return OK; 11 }
1 int Cnum(char file_name[]){ /*字符数统计函数 */ 2 FILE *fp=NULL; 3 int cnum=0; 4 fp=fopen(file_name,"r"); 5 if(fp==NULL){ 6 printf("查找文件失败\n"); 7 } 8 char current_char; 9 current_char = fgetc(fp); 10 while(current_char!=EOF){ 11 current_char = fgetc(fp); 12 cnum++; 13 } 14 fclose(fp); 15 return cnum; 16 }
1 int Wnum(char file_name[]){ /*单词数目统计函数 */ 2 FILE *fp=NULL; 3 int wnum=0; 4 fp=fopen(file_name,"r"); 5 if(fp==NULL){ 6 printf("查找文件失败\n"); 7 } 8 char current_char; 9 current_char = fgetc(fp); 10 while(current_char!=EOF){ 11 if(current_char>='a'&¤t_char<='z'||current_char>='A'&¤t_char<='Z'||current_char=='_') { 12 while(current_char>='a'&¤t_char<='z'||current_char>='A'&¤t_char<='Z'||current_char=='_'){ 13 current_char=fgetc(fp); //光标在单词内部后移 14 }//end while 结束while意味着光标已经走完了这个单词 15 wnum++; 16 }//end if 记录个数加一 17 current_char=fgetc(fp); 18 }//end while 19 fclose(fp); 20 return wnum; 21 }
1 int Lnum(char file_name[]){ /*行数统计函数 */ 2 FILE *fp=NULL; 3 int lnum=0; 4 fp=fopen(file_name,"r"); 5 if(fp==NULL){ 6 printf("查找文件失败\n"); 7 } 8 char current_char; 9 current_char = fgetc(fp); 10 while(current_char!=EOF){ 11 if(current_char=='\n') 12 lnum++; 13 current_char = fgetc(fp); 14 } 15 fclose(fp); 16 lnum++; 17 return lnum; 18 }
1 int find(char *path,char *type) /*递归函数 (有bug)*/ 2 { /* path=C:\Users\jennifer\Desktop\软工2 */ 3 char now_path[200]; 4 char file_path[200]; 5 strcpy(now_path,path); 6 strcpy(file_path,path); 7 strcat(path,"\\"); /* path=C:\Users\jennifer\Desktop\软工2\ */ 8 strcat(file_path,"\\*."); 9 strcat(file_path,type); /* file_path=C:\Users\jennifer\Desktop\软工2\*.c*/ 10 strcat(now_path,"\\*.*");/* path=C:\Users\jennifer\Desktop\软工2\*.* */ 11 12 13 struct _finddata_t file; 14 long handle; 15 16 handle=_findfirst(file_path,&file); 17 if (handle == -1) 18 return -1; 19 else { 20 do { 21 if(file.attrib != _A_SUBDIR){ 22 printf("%s%s\n",path,file.name); //输出文件名 23 } 24 } while (_findnext(handle, &file) == 0); 25 } 26 _findclose(handle); 27 28 char next_path[200]; 29 handle=_findfirst(now_path,&file); 30 if (handle == -1) 31 return -1; 32 else { 33 do { 34 if(file.attrib == _A_SUBDIR && 35 strcmp(file.name, ".") && strcmp(file.name, "..") ){ 36 // printf("%s%s\n",path,file.name); //输出文件夹名 37 strcpy(next_path,path); 38 strcat(next_path,file.name); 39 find(next_path,type); //递归 40 } 41 } while (_findnext(handle, &file) == 0); 42 } 43 _findclose(handle); 44 45 }
6.测试运行:
关于基本功能,这里用C:\Users\jennifer\Desktop\软工2\code.c进行测试
code.c内容如图:

与wc.exe的基本功能运行结果如图:

接下来是-s功能,设置路径为C:\Users\jennifer\Desktop\软工2,命令为搜索所有文件,经校对,结果显示正确

但这个代码有bug,当我指定文件后缀为*.c时,结果显示与预期不符,程序无法读取新建文件夹3下的cccc.c文件

输入错误时,如图

最后,输入0结束使用程序

7.项目小结:
1.要肯在需求分析和项目进程规划方面下功夫,需求分析和项目规划做得马虎,有过多漏洞的话,后续写代码的时候发现一开始思路有误的话,很容易浪费大量的时间去重新整改思路,回去修改原已写好的代码,越是这样,整个项目下来就会越乱,代码可读性也会有所降低,最后项目所用时间也会比预期要多很多。
2.知识储备真的很重要,在写这个项目的过程中,我大部分时间都是在查资料的,比如说_finddata_t file结构体,我两个晚上的时间都是在查这个结构体,去看应该怎么使用它,很遗憾的是,我还是没能学会它,导致我的递归函数出现了bug,这个bug修改了很久依旧无果,还是要把知识点吃透一点才行。
3.关于-a扩展功能,本来是打算写一个名叫more的函数,函数里面先调用行数统计函数得到line_count,然后计算空行行数empty_count,计算注释行数note_count,再用line_count减去empty_count减去note_count得到代码行code_count的,但是写的时候在注释块这边卡住了,并且后来发现,不能用减的方法得到代码行,因为有可能一行里面,它既是代码行又是注释行,所以最后这个功能也就没实现了
4.通过这次的项目,认识到自己有很多很多不足,还是要多多学习,努力提升自己呀!
浙公网安备 33010602011771号