第三次作业 WordCount

第三次作业 WordCount

合作者:201631062403 , 201631062503

GiuHub地址:https://github.com/wangjiajia1225/WangjiaDM

本次作业的链接地址:https://edu.cnblogs.com/campus/xnsy/Test/homework/2203


 

 一、项目要求

WordCount是一个计数的软件,它可以统计文本文件的字符数、单词数以及行数,还有一些拓展功能:包括遍历所有的文件、记录更复杂的数据(代码行/空行/注册行)、支持通配符(*,?)。因为我们都比较熟悉c语言,所以是用C语言编写的,相互该起来更加的方便。

二、项目实现的功能

3.1.1基本功能(完成)

        统计file.c的字符数(实现)

         统计file.c的单词数(实现)

         统计file.c的行数(实现)

3.1.2拓展功能(完成)

       递归处理目录下符合类型的文件(实现)

         显示代码行、空行和注释行的行数(实现)

         支持通配符(* , ?)(实现)

3.1.3高级功能(未完成)

3.1.4定义

             字符:可显示的ASCII码字符,因此不包括空格和‘\n’等控制字符

        单词:由一串连续英文字母组成,遇到英文以外为单词的分隔

         行:每行以分行符或结束符为标志,分为三种:

         空行:本行只由非显示字符组成,若有代码,则不超过一个可显示字符

         代码行:本行包括多于一个字符的代码

         注释行:本行不是代码行,且包括注释

三、PSP表格

 psp阶段

 估计耗时(时)

 实际耗时(时)

 总体计划

 0.5h

 0.6h

 预计完成这个项目时间

 20h

24h

 程序开发

10h

 15h

 · 需求分析

 3h

 1h

 · 生成设计文档

 1h

 0.5h

 · 设计复审 (和同事审核设计文档)

 1h

 1h

 · 代码规范 (为目前的开发制定合适的规范)

 0.5h

 0.5h

 · 具体设计

 1h

 1h

 · 具体编码

10h

 10h

 · 代码复审

 1h

 1h

 · 测试(自我测试,修改代码,提交修改)

 2h

2h

 报告

 1h

1h

 · 测试报告

 0.5h

 0.5h

 · 计算工作量

 0.5h

 0.5h

 · 事后总结, 并提出过程改进计划

 0.5h

 1h

 合计

 22h

20h

四、解题的思路

解决这个题主要是要实现几个功能:遍历文档找到需要打开的文档进行查找、统计字符、统计单词、统计行数、统计特殊函数。分别将这几个功能写到不同的函数里面,然后在主函数里面进行调用,实现这个整个项目的实现。

五、具体代码

主要代码:
 1 int CodeCount(char *Path) { //计算字符个数 
 2 FILE *file = fopen(Path, "r"); 
 3 assert(file != NULL); //若文件不存在则报错 
 4 char code; 
 5 int count = 0; 
 6 while ((code = fgetc(file)) != EOF) //读取字符直到结束 
 7 count+= ((code != ' ') && (code != '\n') && (code != '\t')); //判断是否是字符 
 8 fclose(file); 
 9 return count; 
10 }

 

 1 int WordCount(char *Path) { //计算单词个数 
 2 
 3 FILE *file = fopen(Path, "r"); 
 4 assert(file != NULL); 
 5 
 6 char word; 
 7 int is_word = 0; //用于记录字符是否处于单词中 
 8 int count = 0; 
 9 
10 while ((word = fgetc(file)) != EOF) { 
11 if ((word >= 'a' && word <= 'z') || (word >= 'A' && word <= 'Z')) { //判断是否是字母
12 count += (is_word == 0); 
13 is_word = 1; //记录单词状态 
14 } 
15 else 
16 is_word = 0; //记录不处于单词状态 
17 } 
18 fclose(file); 
19 
20 return count; 
21 }

 

 1 int LineCount(char *Path) { //计算行数 
 2 
 3 FILE *file = fopen(Path, "r"); 
 4 assert(file != NULL); 
 5 
 6 char *s = (char*)malloc(200 * sizeof(char)); 
 7 int count = 0; 
 8 
 9 for (; fgets(s, 200, file) != NULL; count++); //逐次读行 
10 
11 free(s); 
12 fclose(file); 
13 
14 return count; 
15 }

 

 

 1 void AllDetail(char *Path) { //显示空行, 代码行,注释行 
 2  
 3 FILE *file = fopen(Path, "r"); 
 4 assert(file != NULL); 
 5  
 6 char *s = (char*)malloc(200 * sizeof(char));//申请空间 
 7 int i;  
 8 int is_codeline = 0; //状态记录变量 
 9 int is_annoline = 0;  
10 int AnnoLock = 0; 
11 int AnnoFileLock = 0; 
12  
13 int codecount = 0; 
14 int annocount = 0; 
15 int blankcount = 0; 
16  
17 while (fgets(s, 200, file) != NULL) { //逐次取文件中的行 
18 for (i = 0; *(s+i) != '\0'; i++) { 
19  
20 if ( ( ( *(s+i) >= 'a' && *(s+i) <= 'z') || ( *(s+i) >= 'A' && *(s+i) <= 'Z') ) && AnnoFileLock == 0) {//判断是否是代码行 
21 codecount += (is_codeline == 0 && AnnoLock == 0); //进入代码行的时候代码行加一  
22 is_codeline = 1; 
23 } 
24  
25 if ( *(s+i) == '/' && *(s+i+1) == '/' && is_codeline == 0 && AnnoFileLock == 0){ //判断是否为注释行 
26 annocount++; 
27 AnnoLock = 1; 
28 } 
29  
30 if (*(s + i) == '/' && *(s + i + 1) == '*'){ //判断文档注释开始 
31 AnnoFileLock = 1; 
32 annocount -= is_codeline; //注释在代码后不算注释行,因此减一 
33 } 
34  
35 if (*(s + i) == '*' && *(s + i + 1) == '/') { //判断文档注释结束 
36 AnnoFileLock = 0; 
37 annocount += (*(s + i + 2) == '\n'); //注释后换行情况 
38 } 
39 }  
40 annocount += AnnoFileLock; //注释行结束时算作注释行加一 
41  
42 blankcount++; //每一行结束计数加一,并清空状态 
43 is_codeline = 0; 
44 is_annoline = 0; 
45 AnnoLock = 0; 
46 } 
47 free(s); 
48 fclose(file); 
49  
50 blankcount = blankcount - codecount - annocount;  
51 printf("codeline:%d, annoline:%d, blankline:%d\n", codecount, annocount, blankcount); 
52 } 

 

 

 1 void Scan(char *Path, char Type) { 
 2 char *FileName = NULL; 
 3 char *FileType = NULL; 
 4 char Temp[30]; //用于暂存改变得字符串 
 5 long Head; 
 6 struct _finddata_t FileData; 
 7 int i = 0; 
 8  
 9 FileName = Path; 
10 while (*(Path + i) != '\0') { //找出文件名和文件类型的位置 
11 if (*(Path + i) == '\\') 
12 FileName = Path + i + 1; 
13 if (*(Path + i) == '.') 
14 FileType = Path + i + 1; 
15 i++; 
16 } 
17  
18 strcpy(Temp, FileType);//调整字符串 
19 *FileType = '*'; 
20 *(FileType + 1) = '\0'; 
21  
22 Head = _findfirst(Path, &FileData); 
23  
24 strcpy(FileType, Temp);//恢复字符串 
25  
26 do { 
27 if ( !strcmp(FileData.name, "..") || !strcmp(FileData.name, ".")) //去除前驱文件路径 
28 continue; 
29  
30 if (_A_SUBDIR == FileData.attrib) //是文件夹 
31 {  
32 strcpy(Temp, FileName); //调整字符串 
33 for (i = 0; *(FileData.name + i) != '\0'; i++) { 
34 *(FileName + i) = *(FileData.name + i); 
35 } 
36 *(FileName + i) = '\\'; 
37 *(FileName + i + 1) = '\0'; 
38 strcat(Path, Temp); 
39  
40 Scan(Path, Type); 
41  
42 strcpy(FileName, Temp); //恢复字符串  
43 } 
44 else//是文件  
45 {  
46 for (i = 0; *(FileData.name + i) != '.'; i++); 
47 if (!strcmp(FileData.name + i + 1, FileType)) { //是指定类型的文件 
48  
49 strcpy(Temp, FileName); 
50 strcpy(FileName, FileData.name); //调整字符串 
51  
52 printf("%s:  ", FileData.name); 
53 Run(Type, NULL, Path); //将地址及功能传到启动函数 
54 printf("\n"); 
55  
56 strcpy(FileName, Temp);//恢复字符串 
57 } 
58 } 
59 } while (_findnext(Head, &FileData) == 0); 
60  
61 _findclose(Head);  
62 }  

 

 

 1 void Run(char Type, char Type2, char *Path) { 
 2  
 3 switch (Type) { 
 4 case 'c': printf("code count: %d\n", CodeCount(Path)); break; 
 5 case 'w': printf("word count: %d\n", WordCount(Path)); break; 
 6 case 'l': printf("line count: %d\n", LineCount(Path)); break; 
 7 case 'a': AllDetail(Path); break; 
 8 case 's': Scan(Path, Type2); break; 
 9 default: printf("type input error"); break; 
10 } 
11 } 

 

 

 1 int main(int argc, char *argv[]) { 
 2  
 3 char Path[100] = "*.c"; //默认参数 
 4 char Type = 's'; 
 5 char Type2 = 'c'; 
 6  
 7 if (argv[1]) { //有输入参数则以输入为准 
 8 Type = *(argv[1] + 1); 
 9 if (Type == 's') { 
10 Type2 = *(argv[2] + 1); 
11 strcpy(Path, argv[3]); 
12 } 
13 else 
14 strcpy(Path, argv[2]); 
15 } 
16  
17 Run(Type, Type2, Path); //调用启动函数 
18  
19 printf("\nPress any key to continue"); 
20 getchar(); 
21  
22 return 0; 
23 }

 

六、测试用例

采用等价类划分法

输入

有效等价类

无效等价类

 

 

读取文件命令

-c

 

 

除了-c,-w,-l,-a之外的任何输入

-w

-l

-a

-s

基于等价类划分法的测试用例:

 

有效等价类测试:

E:\软件质量\作业\WordCount>WordCount.exe -c text

测试所有文件内容字符数

E:\软件质量\作业\WordCount>WordCount.exe -w text

测试所有文件内容单词数

E:\软件质量\作业\WordCount>WordCount.exe -l text

测试所有文件内容行数

E:\软件质量\作业\WordCount>WordCount.exe -a text

测试所有文件内容的代码行、注释行和空行

E:\软件质量\作业\WordCount>WordCount.exe -s -a *.c

测试遍历文件

无效等价类测试:

E:\软件质量\作业\WordCount>WordCount.exe -k text2.txt

type input error

七、测试的文件内容以及测试结果

8.1测试的文件内容

test.c 

@@ -1,3 +1,4 @@
/*this is a test file*/ 
/* 
 
@@ -10,7 +11,8 @@ manson ye
#include<string.h> 
int main() { //main method 
int main() //main method 
{  
int i = 100 / 4; 
printf("hello world");/**/ 

 

 字符数

单词数

行数

代码行,注释行,空行

文件遍历

 

八、代码互审

我们在了解了具体需要实现的功能以及具体的代码计划之后,分别进行了代码的编写,一个写完了大体的代码,一个没有写出文件遍历的内容,是直接输入文件名,然后对字数、行数、字符数、代码行数等进行统计。进行互审的过程中发现了一些问题:比如只能显示字符数,不能显示字母和行数,要写在一起才能显示出来,如果分开了就只能显示第一个。

九、总结

总结:为了完成这次项目开发,我和我的搭档花费大量精力,通过网上查找资料和相互交流磨合,完成这次的Word Count开发,网上有很多相关的博客和代码,他们都是通过不同的思维和语言编写的,由于我平时项目开发经验少,所以在看每种开发方法都感觉一头雾水。后来我们还是选择了自己相对熟悉的C语言完成项目开发。

在这次项目开发中,由于对工具测试较为陌生,我们选择较为简单的等价划分法测试,通过设置测试用例,检测代码是否有误。在测试过程中,我们多次用到cmd,熟悉了cmd的相关命令。

同过此次实验,我们体验了软件程序的测试过程,认识到了自己在这方面的一些不足,并为以后的进步做出有计划的引导。整个过程中,我们的学习生活都十分充实,我希望以后还能有机会体验这种项目开发过程。

 

 

 

posted on 2018-10-21 02:11  安然若梦  阅读(167)  评论(0编辑  收藏  举报

导航