需求分析:
程序处理用户需求的模式为:
- wc.exe [parameter][filename]
在[parameter]中,用户通过输入参数与程序交互,需实现的功能如下:
1、基本功能
- 支持 -c 统计文件字符数
- 支持 -w 统计文件单词数
- 支持 -l 统计文件总行数
2、拓展功能
- 支持 -a 返回高级选项(代码行 空行 注释行)
[filename] 是待处理文件名。
能力有限,没有写出来-s:递归处理目录下符合条件的文件的功能,高级功能-x。
基本功能的实现:
这次写的程序条理还比较清晰,实现四个功能写了四个子,函数其中void CharCount(FILE *fp),用于统计文件中字符的数量,void WordCount(FILE *fp),用于统计文件中单词的数量,void LineCount(FILE *fp),用于统计文件的行数,void Advance(FILE *fp),实现统计文件中的代码行,注释行,空行的数量。
利用main函数的参数传递输入内容,使用命令行程序cmd调试参数。由于没想到怎么来控制不确定参数个数的情况,只能机械的自己排序,然后判断输入情况进行程序调试与运行。之前以为自己不会用文件,现在感觉挺简单的嘛。定义文件指针保存文件地址。然后根据输入参数个数的情况进行不同情况的函数调用,偷懒了,没有把参数大于三个时的情况都写下来。肯定有宝藏待我发掘。在主函数中获得参数内容,根绝参数内容进入不同的子函数输出不同的内容。主函数代码如下:
1 int main(int argc, char* argv[]) 2 { 3 FILE *fp; 4 switch(argc) 5 { 6 //不同的输入情况 7 case 3: 8 fp=fopen(argv[2],"r"); 9 if(fp==NULL) 10 { 11 printf("不能打开文件"); 12 exit(0); 13 } 14 if(strcmp(argv[1],"-c")==0) 15 { 16 CharCount(fp); 17 } 18 else if(strcmp(argv[1],"-w")==0) 19 { 20 WordCount(fp); 21 } 22 else if(strcmp(argv[1],"-l")==0) 23 { 24 LineCount(fp); 25 } 26 else if(strcmp(argv[1],"-s")==0) 27 { 28 Advance(fp); 29 } 30 else 31 { 32 printf("格式错误! "); 33 } 34 break; 35 case 4: 36 fp=fopen(argv[3],"r"); 37 if(fp==NULL) 38 { 39 printf("不能打开文件"); 40 exit(0); 41 } 42 if(strcmp(argv[1],"-c")==0) 43 { 44 if(strcmp(argv[2],"-w")==0) 45 { 46 CharCount(fp); 47 WordCount(fp); 48 } 49 else if(strcmp(argv[2],"-l")==0) 50 { 51 CharCount(fp); 52 LineCount(fp); 53 } 54 else 55 { 56 printf("格式错误! "); 57 } 58 } 59 else if(strcmp(argv[1],"-w")==0&& 60 strcmp(argv[2],"-l")==0) 61 { 62 WordCount(fp); 63 LineCount(fp); 64 } 65 else 66 { 67 printf("格式错误! "); 68 } 69 break; 70 case 5: 71 fp=fopen(argv[4],"r"); 72 if(fp==NULL) 73 { 74 printf("不能打开文件"); 75 exit(0); 76 } 77 if((strcmp(argv[1],"-c")==0)&& 78 (strcmp(argv[2],"-w")==0)&& 79 (strcmp(argv[3],"-l")==0)) 80 { 81 CharCount(fp); 82 WordCount(fp); 83 LineCount(fp); 84 } 85 else 86 { 87 printf("格式错误! "); 88 } 89 break; 90 case 6: 91 fp=fopen(argv[5],"r"); 92 if(fp==NULL) 93 { 94 printf("不能打开文件"); 95 exit(0); 96 } 97 if((strcmp(argv[1],"-c")==0)&& 98 (strcmp(argv[2],"-w")==0)&& 99 (strcmp(argv[3],"-l")==0)&& 100 (strcmp(argv[4],"-s")==0)) 101 { 102 CharCount(fp); 103 WordCount(fp); 104 LineCount(fp); 105 Advance(fp); 106 } 107 else 108 { 109 printf("格式错误! "); 110 } 111 break; 112 default: 113 { 114 printf("参数个数不正确! "); 115 exit(0); 116 } 117 } 118 return 0; 119 }
测试文件如下,第一行没有字符直接回车,第二行三个空格一个tab行缩进,主要用来测试空行:
当捕捉到用户的输入的指令含有-c时,调用统计文件中字符的数量的函数,每读取一个字符,字符数量增加一,最后输出总字符的数量。最后把文件的指针重新指向文件流的开头,避免其他函数读文件时出错。代码和程序运行截图如下:
1 void CharCount(FILE *fp) 2 { 3 int charcount=0; 4 char ch; 5 ch=fgetc(fp); 6 //使用feof函数判断文件是否结束,feof函数适合于各种文件 7 //读取一个字符,字符数增1 8 while(!feof(fp)) 9 { 10 charcount++; 11 ch=fgetc(fp); 12 } 13 14 printf("字符数:%d ",charcount); 15 //文件指针指向流的开头 16 rewind(fp); 17 }
当捕捉到用户输入的指令含有-w时,调用统计文件中单词的数量的函数,我把单词定义为字母数字或者下划线开头并且由字母数字或下划线构成的字符串,所以每当第一个字符属于字母数字或者下划线的话这个字符串至少有一个单词了,然后继续往下读字符,直到下个字符不是字母数字或者下划线,然后单词数量增一。单个数字也会被当成字符串,可以把第一个字符的判断改成字母或者下划线就行了,判断是不是字母可以用isalpha函数。isalnum函数用来判断是不是字母或者数字。下划线的ASCII码为95,也可以直接写:'_'。代码和程序运行截图截图如下:
1 void WordCount(FILE *fp) 2 { 3 int wordcount=0; 4 char ch; 5 ch=fgetc(fp); 6 while(!feof(fp)) 7 { 8 //字母数字或者下划线开头 9 if(isalnum(ch)||ch==95) 10 { 11 //而且后续字符也是字母数字或者下划线 12 while(isalnum(ch)||ch==95) 13 { 14 ch=fgetc(fp); 15 } 16 //单词数量增加1 17 wordcount++; 18 } 19 20 ch=fgetc(fp); 21 } 22 printf("单词数:%d ",wordcount); 23 rewind(fp); 24 }
当捕捉到用户输入的指令含有-l时,调用统计文件的行数的函数,每遇到’ ‘或者’ ‘时,行数加一。代码和程序运行截图如下:
void LineCount(FILE *fp) { int linecount=0; char ch; ch=fgetc(fp); //遇到换行符或者文件结尾行数增1 while(!feof(fp)) { if(ch==' '||ch=='