【现代软件工程】第一次作业——词频统计
目录
1.1基本功能
1.2设计实现
1.3代码结构
1.4测试运行
1.5性能分析
1.6项目总结
1.7 PSP展示
1.1 基本功能
1. 统计文件的字符数(只需要统计Ascii码,汉字不用考虑,换行符不用考虑,'\0'不用考虑)(ascii码大小在[32,126]之间)
2. 统计文件的单词总数
3. 统计文件的总行数(任何字符构成的行,都需要统计)(不要只看换行符的数量,要小心最后一行没有换行符的情形)(空行算一行)
4. 统计文件中各单词的出现次数,输出频率最高的10个。
5. 对给定文件夹及其递归子文件夹下的所有文件进行统计
6. 统计两个单词(词组)在一起的频率,输出频率最高的前10个。
7. 在Linux系统下,进行性能分析,过程写到blog中(附加题)
关于字符、行数与单词的统计规则详情请见:http://www.cnblogs.com/denghp83/p/8627840.html
1.2 设计实现
1.2.1 解题思路
1. 用命令行参数输入文件路径,判断其是单个文件还是文件夹。
若为单个文件则直接打开,统计字符、单词与行数;若为文件夹,则递归遍历该文件夹下的所有文件进行统计。
之前用文件操作用得较少,所以对遍历文件夹的操作不熟悉,在网上找了点资料。
(学习笔记:
1)存储文件各种信息的结构体中:unsigned attrib表示文件的属性,_A_SUBDIR表示文件夹属性。
2)_findfirst函数
long _findfirst( char*filespec,struct _finddata_t *fileinfo );
返回值:如果查找成功的话,将返回一个long型的唯一的查找用的句柄(就是一个唯一编号)。这个句柄将在_findnext函数中被使用。若失败,则返回-1。
fileinfo :这里就是用来存放文件信息的结构体的指针。这个结构体必须在调用此函数前声明,不过不用初始化,只要分配了内存空间就可以了。函数成功后,函数会把找到的文件的信息放入这个结构体中。
3)_findnext函数
int _findnext( long handle, struct_finddata_t *fileinfo );
返回值:若成功返回0,否则返回-1。
参数:handle:即由_findfirst函数返回回来的句柄。
fileinfo:文件信息结构体的指针。找到文件后,函数将该文件信息放入此结构体中。
https://blog.csdn.net/aoshilang2249/article/details/37819159)
2. 对于字符、行数与单词数统计,将字符数、行数与单词数作为全局变量,一开始最简单的想法是分三次读取文件,后来想想真的太费时间了。
最后的方案是每读一个文件,就把字符、行数与单词数统计好。
3. 对于单词和词组频率的统计:创建两个哈希表,使用ELFHASH哈希算法计算索引值,使用拉链法处理冲突。
对词组频率的统计一开始没有什么头绪,后来翻看了其他同学的博客,通过操作前后两个单词的结构体指针来实现词组在哈希表中的存储,才大概有了点头绪。
4. 输出频率前十的单词和词组:通过遍历哈希表实现。
1.2.2 实现细节
单词和词组的结构体:
typedef struct wordnode {int times;char word[MAX];//单词原型char wordhash[MAX];//去掉最末尾数字且字母全为小写struct wordnode *next;}wordnode, *wordlist;typedef struct phrasenode {int times;wordlist wordpre;//前一个单词 wordlist wordaft;//后一个单词struct phrasenode *next;}phrasenode, *phraselist;
1. 字符数统计:ASCII码值在32-126之间的字符,则字符数加一。
2. 行数统计:扫描到'\n',则行数加一。每个文件扫描结束,行数再加一。(自我感觉这个统计方法有点不太靠谱。)
3. 单词数统计:当扫描到分隔符后的第一个字母或数字时,开始将该字符存储到缓冲数组,直到遇到下一个分隔符。
再对缓冲数组中的字符串做分析,如果长度(不含末尾'\0')大于等于4并且前四个字符都为字母,则单词数加一。
为了便于计算哈希算法的键值和处理冲突,将字符串做一些处理,去掉最末尾的数字并将剩下的均转化为小写。
根据键值与字符串的大小比较在哈希表中查找,若查找失败,则创建一个新结点;若查找成功,则次数加一。
4. 词组数统计:按上述方法记录一下每一个单词的结构体指针。
若不是该文件的第一个单词,将它与上一个单词合在一起生成一个哈希键值,用与统计词频相似的方法处理哈希表。
for (i = 0; ((ch >= 'a'&&ch <= 'z') || (ch >= 'A'&&ch <= 'Z') || (ch >= '0'&&ch <= '9')) && ch != EOF; i++){charactercount++;buffer[i] = ch;ch = fgetc(fp);}charactercount--;buffer[i] = '\0';if (i >= 4 && ((buffer[0] >= 'a'&&buffer[0] <= 'z') || (buffer[0] >= 'A'&&buffer[0] <= 'Z')) && ((buffer[1] >= 'a'&&buffer[1] <= 'z') || (buffer[1] >= 'A'&&buffer[1] <= 'Z')) && ((buffer[2] >= 'a'&&buffer[2] <= 'z') || (buffer[2] >= 'A'&&buffer[2] <= 'Z')) && ((buffer[3] >= 'a'&&buffer[3] <= 'z') || (buffer[3] >= 'A'&&buffer[3] <= 'Z'))){wordtotal++;//此时i即为单词原始长度for (k = i - 1; ; k--){if ((buffer[k] >= 'a'&&buffer[k] <= 'z') || (buffer[k] >= 'A'&&buffer[k] <= 'Z'))break;//k represents the last location of a character }//my_strlwr(regular, buffer, k + 1);current = wordFrequency(buffer, k + 1);if (wordtotal > 0){//不是第一个单词 phraseFrequency(last, current);}last = current;}
1.3 代码结构
详细代码地址:https://github.com/EstherXr/learngit/blob/master/homework1.cpp
1.4 测试运行
1. 助教给的测试集
上面为我的结果,下面为助教给的测试结果。
频率前十的单词和词组及频率与助教的结果相同,但是字符数、行数与单词数都有偏差。对于单词数,我觉得是各人的定义不同,比如ab123abcd中的abcd到底算不算单词。
2. 空文件:
3. 遍历文件夹测试一:
4. 遍历文件夹测试二:
5. 单文件输出所有单词:
1.5 性能分析
CPU总使用情况
遍历文件夹函数:
统计字符数、行数与单词数:
分析:
从函数的CPU使用情况来看,大部分时间都花费在遍历文件夹与统计函数上。
1.6 项目总结
到真正写代码和做东西的时候,就会发现自己会的东西真的太少了。(所以这次基本是用纯C写的)也因为之前写代码写得太少了,所以对自己能力的估计也很不准确,导致规划的效率很低。
在交代码的那天晚上才开始做移植,但是在Linux系统上测试一直有问题,所以最后只好交了一份没有移植的代码。之后要把这个问题搞明白,也要开始学习如何使用虚拟机。
以后做项目要多些文档,可以帮助自己梳理思路,更有条理。这也是这次作业不足的地方。
最后,一定要和身边的人多交流。
1.7 PSP展示
预估耗时/min | 实际耗时/min | ||
Planning | 计划 | 30 | 45 |
-Estimate | -估计这个任务需要多少时间 | 30 | 45 |
Development | 开发 | 1220 | 1600 |
-Analysis | -需求分析 | 120 | 60 |
-Design Spec | -设计文档 | 90 | 60 |
-Design Review | -设计复审 | 30 | 20 |
-Coding Standard | -代码规范 | 20 | 20 |
-Design | -具体设计 | 120 | 240 |
-Coding | -具体编码 | 600 | 900 |
-Code Review | -代码复审 | 60 | 60 |
-Test | -测试 | 180 | 240 |
Reporting | 报告 | 180 | 265 |
-Test Report | -测试报告 | 90 | 180 |
-Size Measurement | -计算工作量 | 60 | 40 |
-Postmortem | -总结反思 | 30 | 45 |
1430 | 1910 |
转载于:https://www.cnblogs.com/Esther-SE/p/8671221.html
【现代软件工程】第一次作业——词频统计相关推荐
- 软件工程第一次作业补充
软件工程第一次作业(2) 关于<构建之法>的5个问题 1)P28,2.1.3回归测试具体怎么操作? 2)P46讲到了软件工程师的成长,那么对于我们大学生来说,需要培养哪方面的品质? 3)P ...
- 软件工程第一次作业(补充)
软件工程第一次作业补充 花20分钟写一个能自动生成小学四则运算题目的"软件",要求:除了整数以外,还要支持真分数的四则运算.将代码上传至coding.net, 并将地址发布至自己的 ...
- 广工软件工程第一次作业
这个作业属于哪个课程 广工软件工程学习 这个作业要求在哪里 软件工程第一次学习 这个作业的目标 评估当前的自己.展望未来中的所有问题和要求 其他参考文献 无 文章目录 git 自我评估 1. 个人简介 ...
- BUAA 软件工程 第一次作业
BUAA 软件工程2022 第一次作业 项目 内容 这个作业属于哪个课程 北航 2022 春季敏捷软件工程 这个作业的要求在哪里 作业说明链接 我在这个课程的目标是 了解并提高自己对软件工程的认识和实 ...
- 软件工程实践之词频统计
GitHub仓库地址: https://github.com/softwarehsc/java1 PSP表格: PSP2.1 Personal Software Process Stages 预估耗时 ...
- 软件工程第一次作业:写一篇自己的博客
这个作业属于哪个课程 18级软件工程基础 这个作业要求在哪里 第一次个人作业:阅读与准备 我在这个课程的目标是 学会创建自己的博客以及Markdown的语法 其他参考文献 git优点缺点 其他参考文献 ...
- 2017年秋季学期软件工程第一次作业(曹洪茹)
作业一 在开始作业要求的正文之前,我先简单谈谈自此课开课以来,包括读了许多大牛写的博文之后的几点感悟和思考. 首先,作为一名有四年地方大学生活经验的军校研究生,我很激动也很庆幸在研究生阶段能遇到这么一 ...
- 软件工程——第一次作业
Part one:自我介绍 首先进行一些自我介绍,我叫贾雅杰,河北廊坊人,本科就读于南昌大学计算机科学与技术专业,现有编程能力稍弱,希望通过这学期的课程有所提高.第一次使用博客,希望大家多多提出宝贵的 ...
- 李昂 软件工程第一次作业
第1次个人作业 2.分析软件 第一部分 结缘计算机 1.计算机是你喜欢的领域吗?是你擅长的领域吗? 这两个问题,不得不说我的答案都是否.我很难喜欢计算机编程,更遑论软件硬件原理等等,感觉有些晦涩了,无 ...
最新文章
- 参加LinuxCon Japan 2012
- 验证码识别,发票编号识别(转)
- 如何证明你的性能测试结果可信?
- dpi重启后会恢复_Linux 系统的备份恢复
- Centos7:查看某个端口被哪个进程占用
- linux下批量修改文件名的方法
- 解决mysql插入中文出现错误Incorrect string value: ‘\xE7\xA8\x8B\xE5\xBA\x8F...‘ for column ‘course‘ at row 1
- page cache 与free
- ubuntu 设置分辨率 亲测可用 转载的
- iOS------App之间传递数据的几种方式
- ie下滚动条样式设置
- 开源文件管理服务器,GitHub - biiliwuiid/file-manager: 文件服务器管理系统
- 基于React的贪吃蛇游戏的设计与实现
- python学什么方向就业好_学python就业都有哪些方向
- Linux系统下如何运行.sh文件
- atitit.编辑表单的实现最佳实践dwr jq easyui
- 一个软件完整的开发流程,不会程序也能自己制作手机App
- 齐全的降低笔记本电池损耗的方法
- learning java AWT Pannel
- 宏 word 更新域
热门文章
- jquery显示与隐藏效果
- 快速排序 与 归并排序
- python图书馆预约系统_python实现图书馆研习室自动预约功能
- 贪心法—LeetCode 452 用最少数量的箭引爆气球
- GameObject.Find() 和 Transform.Find()的区别
- 骨牌铺方格的3种做法
- tf.train.Saver,和模型参数微调
- 差分滤波器的实现及作用于图像提取图像的特征
- matlab hadamard(哈达玛变换)变换
- 解决laravel框架中Eloquent ORM的save方法无法插入数据的问题