20180912-3 词频统计
此作业的要求参见[https://edu.cnblogs.com/campus/nenu/2019fall/homework/6583]
本项目代码地址为:[https://e.coding.net/secret/ASETest1.git]
• 词频统计 SPEC
写个程序名字叫wf,统计英文作品的单词量并给出每个单词出现的次数
具体要求:
功能1 小文件输入。
功能2 支持命令行输入英文作品的文件名。
功能3 支持命令行输入存储有英文作品文件的目录名,批量统计。
功能4 从控制台读入英文单篇作品。
• 整体分析:
1、c语言对于文本文件、目录文件的操作比较复杂,调试的时候比较花时间
2、对于单词的处理,包括大小写转换、统计、记录、排序等需要定义合适的数据结构
3、对于不同命令的识别和区分,也是比较麻烦的一部分
4、四个功能逻辑上相互独立,但在实现上又含有相似的部分,因此代码还有可简化的空间
• 重要代码及执行结果
功能一:
1、重点/难点
由于此部分数据来源于文件,因此相对于其他功能,功能一的复杂之处,主要是文件操作以及空间利用上。
2、关键代码片段
(1)动态利用空间
//初始化空间 wordNode* words = (wordNode*)malloc(600 * s * sizeof(wordNode));
//单词数大于600重新申请空间 if (count == 600 * s) { s++; words = (wordNode*)realloc(words, 600 * s * sizeof(wordNode)); for (k = count; k < 600 * s; k++) { (words + k)->frequent = 0; } }
(2)文件操作
//读文件,若文件为空则报提示 FILE* file = fopen(filename, "r"); if (file == NULL) { printf("there is no text\n"); }
//操作完后切记关闭文件 fclose(file);
3、运行结果
功能二:
1、重点/难点
与功能一的主要区别在于命令参数不同,最主要的单词来源都是读文件,因此在“功能一”的基础上,此部分额外要做的就是识别和区分控制台指令
2、关键代码片段
//单词小写化处理 w = tolower(fgetc(file)); while ((!feof(file)) && (isspace(w))) { w = tolower(fgetc(file)); } while (!feof(file)) { //判断单词类型是否为英文或十进制数字 if ((isdigit(w)) || isalpha(w)) { flag = 1; temp[i++] = w; } else//识别特殊符号 { if (flag) { if ((w == '\'') || (w == '-')) { temp[i++] = w; flag = 1; } else { flag = 0; temp[i] = '\0'; i = 0; for (j = 0; j < count; j++) { if (strcmp((words + j)->words, temp) == 0) { (words + j)->frequent++; break; } } if (j == count) { (words + count)->frequent = 1; strcpy((words + count)->words, temp); count++; } if (count == 600 * s) { s++; words = (wordNode*)realloc(words, 600 * s * sizeof(wordNode)); for (k = count; k < 600 * s; k++) { (words + k)->frequent = 0; } } } } } w = tolower(fgetc(file)); }
3、运行结果
功能三:
1、重点/难点
此功能要求不仅要读取文件,还要批量的读取目录下所有文件内容,因此,识别目录、批量读取目录下所有文件是此部分的重点和难点
2、关键代码片段
//功能三 if (_S_IFDIR & buf.st_mode) { strcat(temp1, argv[1]); //文件夹下的文件绝对目录 strcpy(name, temp1); strcat(name, temp2); count = strlen(name); strcat(temp1, s2); printf("dir\n"); if ((handle = _findfirst(temp1, &filedetial)) != -1L) { do { strcat(name, filedetial.name); printf("%s\n", filedetial.name); function1(name); name[count] = '\0'; printf("-------\n"); } while (_findnext(handle, &filedetial) == 0); } else { printf("无匹配项目\n"); } //退出机制 _findclose(handle); }
3、运行结果
功能四:
1、重点/难点
功能四有两种命令模式:
第一种模式通过标准输入重定向为文件的方式,第二种模式通过控制台输入的方式输入文章,与之前读取文件的方式的不同,是此部分的难点和重点
2、关键代码片段
/* 对每个单词设置结构体 */ typedef struct word { int frequent;//单词频度 char words[50];//单词 }wordNode;
//按照单词频度排序 qsort(words, count, sizeof(wordNode), cmpWords);
/* 按单词频度比较大小 */ int cmpWords(const void* w1, const void* w2) { wordNode* t1 = (wordNode*)w1, * t2 = (wordNode*)w2; if (((t2->frequent) - (t1->frequent)) != 0) { return (t2->frequent) - (t1->frequent); } else { return (t1->words) - (t2->words); } }
3、运行结果
• PSP
要求1 估算你对每个功能 (或/和子功能)的预计花费时间,填入PSP阶段表格,时间颗粒度为分钟。
要求2 记录词频统计项目实际花费时间,填入PSP阶段表格,时间颗粒度要求分钟。
要求3 对比要求1和要求2中每项时间花费的差距,分析原因。