第2周个人作业:WordCount
github地址
https://github.com/FangStars/WCProject
PSP表格
PSP2.1 |
PSP阶段 |
预估耗时(分钟) |
实际耗时(分钟) |
Planning |
计划 |
20 |
30 |
· Estimate |
· 估计这个任务需要多少时间 |
10 |
15 |
Development |
开发 |
800 |
900 |
· Analysis |
· 需求分析 (包括学习新技术) |
100 |
150 |
· Design Spec |
· 生成设计文档 |
20 |
30 |
· Design Review |
· 设计复审 (和同事审核设计文档) |
30 |
40 |
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
5 |
10 |
· Design |
· 具体设计 |
50 |
55 |
· Coding |
· 具体编码 |
500 |
600 |
· Code Review |
· 代码复审 |
100 |
150 |
· Test |
· 测试(自我测试,修改代码,提交修改) |
200 |
200 |
Reporting |
报告 |
100 |
120 |
· Test Report |
· 测试报告 |
40 |
50 |
· Size Measurement |
· 计算工作量 |
10 |
20 |
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
20 |
30 |
合计 |
2005 |
2400 |
解题思路
根据控制台输入给main函数的参数个数来判断输出的格式,是只输出单词,还是输出行数,或进行文件操作等。统计时只要根据文本每个符号进行分析全部统计就行了,用全局变量进行保存,最后输出或写文本。
程序设计实现过程
本项目采用C语言实现,一个main函数和两个主要函数countAll和countStop分别用来统计全部和停用词。main函数主要是用来判断程序参数的个数,然后根据参数的类型选择输出,其余两个函数接下来用代码分析。写代码时一步步查找需要实现的资料,如怎样命令行输入,怎样扫描目录等,网址最后给出。
代码说明
countAll,根据一次次搜到的不同的char来判断是增加char还是word,或者line,例如每遇到一个换行符就line+1,注意的是最后一行一般没有换行符,所以保存的行line[]数组最后需要单独判断一遍,其中line和word 的判断条件依据示例来进行设计。
1 void countAll(char ch, FILE *fp) 2 { 3 int i = 0;//用于更新getWord 4 int j = 0;//用于更新lineWord 5 while ((ch = fgetc(fp)) != EOF) 6 { 7 if (isaldig(ch)) 8 {....14 } 15 else if ((ch == ' '&&isaldig(lineWord[j-1]))||ch==',')//忽略连续空格,遇到空格或逗号则单词数加一 16 {....27 } 28 else if (ch == '\n') 29 {....47 } 48 else 49 {...53 } 54 } 55 wc_line++;//最后一行再判断一遍
....................... 71 wc_codeLine = wc_line - wc_empLine - wc_expLine; 72 }//顺序查找文件中字符
countStop:主要设计思路是首先将停用次扫描进入到stopWord中,然后重复一次countAll但是不计数,每次读取到一个单词都进行对比,若对比成功则stopWord++;
1 void countStop(char ch,FILE *fp, FILE *fps) 2 { 3 int i=0;//计数单词 4 char stopWord[5][20] = {}; 5 while ((ch = fgetc(fps)) != EOF) 6 { 7 //添加停用词25 } //最后一行再判断一次 34 memset(getWord, 0, sizeof(getWord)); 35 i = 0;//此时stopword里保存的为停用词 36 int j = 0;//计数行 37 while ((ch = fgetc(fp)) != EOF)//此函数中与上函数类似,但不计数 38 {
........;
92 } 93 memset(getWord, 0, sizeof(getWord)); 94 i = 0; 95 memset(lineWord, 0, sizeof(lineWord)); 96 j = 0; 97 }
main函数:可以看出是根据参数来置数组的Flag来确定输出什么数据,其顺序根据需求说明的顺序来确定。如果有-s则扫描exe的文件目录下的c文件,然后保存到filename下,递归对所有的file进行count,然后若有-o则顺序输出到output.txt上。
1 else if (argc > 3) 2 { 3 int flag[7] = { 0 };//记录哪些功能需要打印 4 char otext[200];//输出文本 5 char stopFile[20]; 6 for (int i = 0; i < argc; i++) 7 { 8 if (strcmp(argv[i], "-c") == 0) 9 { 10 flag[0] = 1; 11 } 12 else if (strcmp(argv[i], "-w") == 0) 13 { 14 flag[1] = 1; 15 } 16 else if (strcmp(argv[i], "-l") == 0) 17 { 18 flag[2] = 1; 19 } 20 else if (strcmp(argv[i], "-a") == 0) 21 { 22 flag[5] = 1; 23 } 24 else if (strcmp(argv[i], "-o") == 0) 25 { 26 flag[3] = 1; 27 } 28 else if (strcmp(argv[i], "-s") == 0) 29 { 30 flag[4] = 1; 31 } 32 else if (strcmp(argv[i], "-e") == 0) 33 { 34 flag[6] = 1; 35 strcpy(stopFile, argv[i + 1]); 36 } 37 } 38 if (flag[4] == 1) 39 { 40 // 文件内容读取,得看内内容是什么样的了43 while ((strlen(filesName[fileNum]) != 0)) 44 { 45 fp = fopen(filesName[fileNum], "r");//读取文件数组 46 notFound(fp); 47 countAll(ch, fp); 48 if (flag[6] == 1) 49 {.... 50 } 51 if (flag[3] == 1) 52 {.... 53 } 54 if (flag[0] == 1) 55 {.... 56 } 57 if (flag[1] == 1) 58 {.... 59 } 60 if (flag[2] == 1) 61 {.... 62 } 63 if (flag[5] == 1) 64 {.... 65 } 66 fclose(fp); 67 wc_char = 0; 68 wc_word = 0; 69 wc_line = 0; 70 wc_codeLine = 0; 71 wc_empLine = 0; 72 wc_expLine = 0; 73 wc_stopWord = 0; 74 fileNum++; 75 } 76 } 77 if (flag[4] != 1) 78 {....//若不是文件读取,则默认读取file.c 79 } 80 if (flag[3] == 1) 81 fclose(fpw); 82 } 83 }
测试设计过程
由于参数main函数的参数可以有多个,所以每个都要进行一次测试,文本中文本也有多变性,需要对不同文本进行测试进行。统计风险最高的地方在与每个节点判断处,与其它的地方相比更易出错。以下进行测试并给出测试结果
以下首先用file.c进行测试
1 test() 2 { 3 File writename = new File(outputPath); 4 writename.createNewFile(); 5 codeLine*/ 6 7 BufferedWriter out = new BufferedWriter(new FileWriter(writename)); 8 //noteLine 9 out.write(outputBuffer); 10 11 /*noteLine 12 /*noteLine 13 */ 14 /*noteLine*/ 15 /*noteLine 16 //noteLine 17 */codeLine 18 out.flush(); 19 out.close(); 20 }//noteLine 21 for(){ 22 }/*noteLine*/
停用词表stopList.txt为:
noteLine codeLine
以下为逐个单项功能测试(不含文本输出)
1.wc.exe -w file.c 2.wc.exe -c file.c 3.wc.exe -l file.c 4.wc.exe -a file.c 5.wc.exe -e stopList.txt -w file.c
测试截图为
文本输出:-o
1.wc.exe -w -o file.c
2.wc.exe -w -c -o file.c
3.wc.exe -w -c -l -0 file.c
4.wc.exe -w -a -l -c -o file.c
5.wc.exe -a -c -e StopList.txt -o file.c
输出截图:(举两例4,5),其余可自行验证
文件目录下遍历-s(文件目录为exe同目录,其他file并不展示)
1.wc.exe -w -s *.c -o 2.wc.exe -w -c -l -s *.c -o 3.wc.exe -a -w -s *.c -o 4.wc.exe -a -w -s *.c -e stopList.txt -o
以下输出截图仅提供3,4,其它自行测试
其他测试则更改输入文本来进行,不提供测试截图
测试脚本:(与exe放同一目录可进行批处理)
1 @echo off 2 wc.exe -w file.c 3 wc.exe -c file.c 4 wc.exe -l file.c 5 wc.exe -a file.c 6 wc.exe -e stopList.txt -w file.c 7 wc.exe -w -o file.c 8 wc.exe -w -c -o file.c 9 wc.exe -w -c -l -0 file.c 10 wc.exe -w -a -l -c -o file.c 11 wc.exe -a -c -e StopList.txt -o file.c 12 wc.exe -w -s *.c -o 13 wc.exe -w -c -l -s *.c -o 14 wc.exe -a -w -s *.c -o 15 wc.exe -a -w -s *.c -e stopList.txt -o