一、GitHub
https://github.com/LiFengONE/WordCount
二、PSP表格
PSP2.1 |
PSP阶段 |
预估耗时 (分钟) |
实际耗时 (分钟) |
Planning |
计划 |
10 |
15 |
· Estimate |
· 估计这个任务需要多少时间 |
700 |
885 |
Development |
开发 |
180 |
600 |
· Analysis |
· 需求分析 (包括学习新技术) |
30 | 60 |
· Design Spec |
· 生成设计文档 |
30 |
30 |
· Design Review |
· 设计复审 (和同事审核设计文档) |
10 |
10 |
· Coding Standard |
· 代码规范 (为目前的开发制定合适的规范) |
10 |
10 |
· Design |
· 具体设计 |
30 |
60 |
· Coding |
· 具体编码 |
120 |
360 |
· Code Review |
· 代码复审 |
30 |
30 |
· Test |
· 测试(自我测试,修改代码,提交修改) |
60 |
60 |
Reporting |
报告 |
30 |
20 |
· Test Report |
· 测试报告 |
30 |
20 |
· Size Measurement |
· 计算工作量 |
10 |
10 |
· Postmortem & Process Improvement Plan |
· 事后总结, 并提出过程改进计划 |
30 |
20 |
|
合计 |
700 | 1305 |
三、解题思路
拿到题目后,首先看大致的需求:
基本功能
wc.exe -c file.c //返回文件 file.c 的字符数
wc.exe -w file.c //返回文件 file.c 的单词总数
wc.exe -l file.c //返回文件 file.c 的总行数
wc.exe -o outputFile.txt //将结果输出到指定文件outputFile.txt
扩展功能
wc.exe -s //递归处理目录下符合条件的文件
wc.exe -a file.c //返回更复杂的数据(代码行 / 空行 / 注释行)
wc.exe -e stopList.txt // 停用词表,统计文件单词总数时,不统计该表中的单词
然后就动手去做了,边做边查,有的语法不太记得的了,需要去复习。
四、程序设计实现过程
通过读取目标文件的每一行字符,并用空格和逗号进行分割,然后通过循环遍历针对切割后的数进行判断,根据输入的命令写入文本中
五、代码说明
1 #include2 #include 3 #include 4 using namespace std; 5 6 void main() 7 { 8 bool cfuc = false;//四个变量用来表示是否只行对应的操作 9 bool wfuc = false; 10 bool lfuc = false; 11 bool ofuc = false; 12 char rdfile[20] = { '\0' }; //储存要计数的文件名 13 char wrfile[20] = { '\0' }; //储存输出文件名 14 char a[30]; //储存用户输入指令 15 cin.get(a, 30); 16 int i; 17 for (i = 0; i < 30; i++) 18 { //将要计数的文件名存入字符数组rdfile 19 if (a[i] >= 'a'&&a[i] <= 'z' || a[i] >= 'A'&&a[i] <= 'Z'){ 20 for (int j = 0; j < 20; j++){ 21 rdfile[j] = a[i + j]; 22 if (a[i + j] == ' ' || a[i + j] == '\n' || a[i + j] == '\0') { i = i + j; break; } 23 } 24 } 25 if (a[i] == '-'){ //判断用户要执行的操作 26 if (a[i + 1] == 'c') { 27 cfuc = true; i++; 28 } 29 else if (a[i + 1] == 'w') { 30 wfuc = true; i++; 31 } 32 else if (a[i + 1] == 'l') { 33 lfuc = true; i++; 34 } 35 else if (a[i + 1] == 'o') { 36 if ((cfuc || wfuc || lfuc) == false) { cout << "-o操作不能单独使用" << endl; break; } 37 else{ 38 ofuc = true; i = i + 3; 39 for (int j = 0; j < 20; j++){//读取输出文件名 40 wrfile[j] = a[i + j]; 41 if (a[i + j] == ' ' || a[i + j] == '\n' || a[i + j] == '\0') { i = i + j; break; } 42 } 43 } 44 } 45 else{ 46 cout << "未定义标识符" << endl; break; 47 } 48 } 49 } 50 //cout << "读取的文件名为:" << rdfile << '\n' << "输出文件名为:" << wrfile << '\n' << endl; 51 //cout << cfuc << wfuc << lfuc << ofuc << endl; 52 53 FILE *p; 54 p = NULL; 55 errno_t err; 56 if (ofuc){ //通过指定文件输出 57 ofstream fout(wrfile); 58 if (cfuc){ //计算字符数 59 err = fopen_s(&p, rdfile, "r"); 60 int c_count = 0; 61 char ch; 62 while (!feof(p)){ 63 ch = fgetc(p); c_count++; 64 } 65 fclose(p); 66 fout << rdfile << "的字符数为:" << c_count << endl; 67 } 68 69 if (wfuc){ //计算单词数 70 err = fopen_s(&p, rdfile, "r"); 71 int w_count = 0; 72 char ch; 73 bool flag = false; 74 while (!feof(p)){ 75 ch = fgetc(p); 76 //cout << "字符为:" << ch << "已记单词数" << w_count << endl; 77 if (ch >= 'a'&&ch <= 'z' || ch >= 'A'&&ch <= 'Z' || ch >= '0'&&ch <= '9' || ch == '&' || ch == '-' || ch == '_' || ch == '^') 78 flag = true; 79 else { 80 if (flag) 81 { 82 flag = false; 83 w_count++; 84 } 85 } 86 } 87 fclose(p); 88 fout << rdfile << "的单词数为:" << w_count << endl; 89 } 90 91 if (lfuc){ //计算行数 92 err = fopen_s(&p, rdfile, "r"); 93 int l_count = 1; 94 char ch; 95 while (!feof(p)){ 96 ch = fgetc(p); 97 if (ch == '\n') l_count++; 98 } 99 fclose(p); 100 fout << rdfile << "的行数为:" << l_count << endl; 101 } 102 } 103 else { //控制台输出 104 if (cfuc){ 105 err = fopen_s(&p, rdfile, "r"); 106 int c_count = 0; 107 char ch; 108 while (!feof(p)){ 109 ch = fgetc(p); c_count++; 110 } 111 fclose(p); 112 cout << rdfile << "的字符数为:" << c_count << endl; 113 } 114 115 if (wfuc){ 116 err = fopen_s(&p, rdfile, "r"); 117 int w_count = 0; 118 char ch; 119 bool flag = false; 120 while (!feof(p)){ 121 ch = fgetc(p); 122 //cout << "字符为:" << ch << "已记单词数" << w_count << endl; 123 if (ch >= 'a'&&ch <= 'z' || ch >= 'A'&&ch <= 'Z' || ch >= '0'&&ch <= '9' || ch == '&' || ch == '-' || ch == '_' || ch == '^') 124 flag = true; 125 else { 126 if (flag) 127 { 128 flag = false; 129 w_count++; 130 } 131 } 132 } 133 fclose(p); 134 cout << rdfile << "的单词数为:" << w_count << endl; 135 } 136 137 if (lfuc){ 138 err = fopen_s(&p, rdfile, "r"); 139 int l_count = 1; 140 char ch; 141 while (!feof(p)){ 142 ch = fgetc(p); 143 if (ch == '\n') l_count++; 144 } 145 fclose(p); 146 cout << rdfile << "的行数为:" << l_count << endl; 147 } 148 } 149 system("pause"); 150 }
六、测试设计
测试用例的设计主要力求全面,可以覆盖到每一个程序执行的路径,尽力测试出程序的漏洞,提高程序的质量。
代码中分支最多,最复杂, 处理情况最多,最容易出错的部分是处理程序参数和进阶统计部分。
对于其他的统计量没有特别的设计测试数据,而是在进阶统计部分的测试数据里顺便加上了对于其他统计的测试
测试四种操作单独使用的情况:
1、-c text.c(计算字符数)
2、-w text.c(计算单词数)
3、-l text.c(计算行数)
4、-o wrfile.txt(指定输出文件)
5、-c text.c -o wrfile.txt
改变命令的参数个数,可同时得到他们各自的效果
对特殊的单词进行计数:
-w wordtext.c
七、参考文献链接
http://www.cnblogs.com/xinz/archive/2011/10/22/2220872.html
https://bbs.csdn.net/topics/392006952?page=1
借鉴http://www.cnblogs.com/ldisbest/p/8619377.html