WordCount程序及测试
Github地址:https://github.com/CG0317/WordCount
PSP表:
PSP2.1 |
PSP阶段 |
预估耗时 (分钟) |
实际耗时 (分钟) |
Planning |
计划 |
30 | 30 |
· Estimate |
· 估计这个任务需要多少时间 |
720 | 1200 |
Development |
开发 |
360 | 600 |
· Analysis |
· 需求分析 (包括学习新技术) |
30 | 120 |
· Design Spec |
· 生成设计文档 |
30 | 30 |
· Design Review |
· 设计复审 (和同事审核设计文档) |
20 | 20 |
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
20 | 20 |
· Design |
· 具体设计 |
30 | 60 |
· Coding |
· 具体编码 |
300 | 420 |
· Code Review |
· 代码复审 |
30 | 60 |
· Test |
· 测试(自我测试,修改代码,提交修改) |
120 | 240 |
Reporting |
报告 |
30 | 120 |
· Test Report |
· 测试报告 |
30 | 30 |
· Size Measurement |
· 计算工作量 |
10 | 10 |
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
30 | 20 |
合计 |
710 | 1180 |
解题思路:
看到题目首先想到的是上学期编译技术课设实现的编译器,通过对输入文件的词法分析对单词,字符和行进行计数,通过语法分析区分代码行,注释行和空行。所以就参照编译器对这次作业进行实现。主要问题有:代码行,空行和注释行的定义,输入内容的需求及报错,实现过程源代码的管理。
程序设计实现过程:
首先定义判定字符的变量,然后函数wc对单词,行和字符进行计数。对于输入,通过count函数判定输入的正确性,同时实现输入所需求的功能。
代码说明:
函数wc:
void wc()//统计单词,字符,行的数量 { chars = 0; words = 0; lines = 0; while ((c = fgetc(file)) != EOF) { chars++;//字符+1 if (!isSeparator(c)) { words++;//不是分隔符则单词+1 while ((c = fgetc(file)) != EOF) { chars++; if (!isSeparator(c)) { }//不是分隔符依然算一个单词,若是则继续判定 else if (isLine(c))//若是新行,行数+1 { lines++; break; } else if (isSpace(c) || isComma(c) || isTab(c))//单词判定结束 { break; } } } else if (isLine(c)) lines++; } if (chars !=0)//有字符的最后一行无换行符依然令行数+1 lines++; }
逐个读入字符,字符数+1,若不是分隔符,单词数+1,知道读到分隔符,单词计数结束,循环读入,若读到分隔符为换行符,则行数+1,有字符的最后一行没有换行符但行数显然也应该+1.
count函数部分:
char *resultFile = "result.txt", *fileName = NULL,*outputFile = NULL; int isc=0, isw=0, isl=0,iso = 0;//是否有字符、单词、行数计数和指定文件输出结果的需求 for (int i = 0; i < argc; i++) { if (strcmp(argv[i], "-o") == 0)//若有-o,则接着输入指定输出文件名 { if (iso == 0) iso = i; else { cout << "error :input format is wrong." << endl;//参数输入重复 return 2; } if (i < argc - 1) outputFile = argv[i + 1]; else { cout << "error :output file is empty." << endl;//没有输入指定输出文件报错 return 3; } } else if (strcmp(argv[i], "-c") == 0) { if (isc == 0) isc = i; else { cout << "error :input format is wrong." << endl; return 2; } } else if (strcmp(argv[i], "-w") == 0) { if (isw == 0) isw = i; else { cout << "error :input format is wrong." << endl; return 2; } } else if (strcmp(argv[i], "-l") == 0) { if (isl == 0) isl = i; else { cout << "error :input format is wrong." << endl; return 2; } } else if (i!=0 && i < 5 && fileName == NULL && argv[i][0] != '-') { fileName = argv[i]; } }
对输入输出文件定义,按照输入参数的顺序规定输入格式,同时对不规则的输入进行判断,给出错误提示。
输出结果:
fstream resFile; resFile.open(resultFile, ios_base::out); for (int i = 0; i < argc; i++) { if (strcmp(argv[i], "-c") == 0) { cout << "字符数:" << chars << endl; if (resFile.is_open()) { resFile << fileName << ", 字符数:" << chars << endl; } } else if (strcmp(argv[i], "-w") == 0) { cout << "单词数:" << words << endl; if (resFile.is_open()) { resFile << fileName << ", 单词数:" << words << endl; } } else if (strcmp(argv[i], "-l") == 0) { cout << "行数:" << lines << endl; if (resFile.is_open()) { resFile << fileName << ", 行数:" << lines << endl; } } } resFile.close(); }
将计算结果输入到默认输出文件,若判定有“-o”输入到指定文件。
测试设计过程:
测试需要覆盖程序中所有可执行语句,所以要尽量测试出程序功能的问题,程序易出现风险的地方有:注释行判定,输入参数规范判定,停用词表的判定等。程序功能有,统计单词,字符,行数,统计代码行,注释行,空行数,将统计结果输入到默认或指定文件,递归处理目录下符合条件的文件,排除停用词表内容的单词计数,错误输入的报错等。测试用例对应代码的功能及易出错的地方进行检验,测试用例如下:
test1:测试-c功能
输入:WCtest.exe -c file.c
test2:测试-w功能
输入:WCtest.exe -w file.c
test3:测试-l功能
输入:WCtest.exe -l file.c
test4:测试-a功能
输入:WCtest.exe -a file.c
test5: 测试-o功能
输入:WCtest.exe -c file.c -o outputFile.txt
test6: 测试-e功能
输入:WCtest.exe -c file.c -e stop.txt
test7:测试多个参数共用
输入:WCtest.exe -c -w -l -a file.c -e stop.txt -o outputFile.txt
test8: 测试-s功能
输入:WCtest.exe -s -c -w -l *.c
test9:测试参数错误报错
输入:WCtest.exe -c -c -b file.c
test10:测试输入/输出文件为空报错
输入:WCtest.exe -c -w -o outputFile.txt/WCtest.exe -c -w file.c -o
参考文献如下:
【1】:https://www.cnblogs.com/xiaoyongwu/p/5303132.html
【2】:http://www.cnblogs.com/xinz/p/5044037.html
【3】:http://www.cnblogs.com/xinz/archive/2011/10/22/2220872.html
【4】:http://www.cnblogs.com/xinz/archive/2011/11/20/2255830.html