第一次工作报告

要求

1.      对源文件(*.txt,*.cpp,*.h,*.cs,*.html,*.js,*.java,*.py,*.php等)统计字符数、单词数、行数、词频,统计结果以指定格式输出到默认文件中,以及其他扩展功能,并能够快速地处理多个文件。

2.      使用性能测试工具进行分析,找到性能的瓶颈并改进

3.      对代码进行质量分析,消除所有警告

4.      设计10个测试样例用于测试,确保程序正常运行(例如:空文件,只包含一个词的文件,只有一行的文件,典型文件等等)

5.      使用Github进行代码管理

6.      撰写博客

基本功能

1.      统计文件的字符数

2.      统计文件的单词总数

3.      统计文件的总行数

4.      统计文件中各单词的出现次数

5.      对给定文件夹及其递归子文件夹下的所有文件进行统计

6.      统计两个单词(词组)在一起的频率,输出频率最高的前10个。

7.      在Linux系统下,进行性能分析,过程写到blog中(附加题)

PSP

 

前期的分析:

首先看到了题目就立刻想到了会有巨大的数据需要进行处理,自然就会联想应该如何去解决数据的存放问题与查找问题,从功能需求中一步步想到了使用哈希表对此进行存储,于是便有了初步的想法:

1、打开一个文件,读取文件内容;

2、将读取的信息进行处理;

3、构造一个哈希函数,创建一个哈希表。

之后有关测试文件出来了,便遇到了一个很棘手的问题:对于文件的遍历,这个起初是打算用C语言中的fopen函数,但仔细一分析发现并不能实现具体的要求,于是便寻求一个可以遍历文件的操作,在查阅资料后找到了C++语言中的findfirst和findnext函数可以实现文件操作,于是便开始对其的学习,由于之前未接触过C++,对于其中过程的了解耗费了很长的时间,于是便对测试文件进行了初步的遍历实验,起初的结果很不近人意,只能遍历文件的第一个子目录里的文件,无法进入子文件夹,进过判定条件的修改,最终实现了所有文件的遍历。       

此刻第一步便达到了目的,于是开始了文件读取问题的思考,找到了两个函数,get和getline函数,首先get函数可以很好的读取文件中的字符,依靠对文件是否结束的判定可以持续读取,这个的好处就在于可以无所谓文件中全部的字符总量,可以一边读一边根据判定条件进行对单词与词组的操作,并且可以按照换行符的数量判断一个文件中的行数,这个可以说是很理想;其次是getline函数,它可以一次读取一行,这个可以省去单独统计换行符的工作,每次调用的时候就可以进行行数的累加,然后可以直接用一行一行的处理单词与词组,这个可以更加模块化,但是缺点便是文件中会出现一行中有数十万的字符,就会使得数组溢出导致失败;经过考虑,我选择了getline函数。

然后就是开始对这个项目进行框架的搭建,从字符、单词到词组,每一个都单独进行搭建,互不相关,为了达到这个目的,分别为单词与词组设计了各自的哈希表,由于要同时对出现频率的统计,决定构造一个结构体数组,里面存储字符串与整型数据,而数组的地址则用设计的哈希函数进行计算。

代码设计:

1、 文件遍历

利用已经试验过的findfirst与findnext函数进行操作;

2、 文件读取

利用ifstream函数打开文件,再利用getline函数对文件内容进行读取,在文件函数中直接调用字符的函数、单词的函数、词组的函数;

3、 字符统计

对传入的字符数组,进行遍历,并随之进行数据的统计;

4、 单词统计

对传入的字符数组进行有条件的遍历,筛选出符合条件的单词,调用单词的哈希表构造函数

(1)      单词哈希表构造

消除大小写的影响,即在计算哈希函数时使用单词前四个字母时,全部化为小写进行求解,利用平方取中法构造哈希函数,利用开放定址发解决冲突,其中需要调用单词比较函数和单词优先级比较函数;

1)   单词比较函数

比较新单词与哈希表中同一位置单词是否为相同单词;

 2)单词优先比较函数

比较两个相同单词在字典输出的情况下的先后次序;

5、 词组统计

对传入的字符数组进行有条件的遍历,筛选出符合条件的词组,调用词组的哈希表构造函数 ,其中判断词组需要大量的判定条件;

(1)      词组哈希表构造

消除大小写的影响,即在计算哈希函数时使用第一个单词与第二个单词各前四个字母时,全部化为小写进行求解,利用平方取中法构造哈希函数,利用开放定址发解决冲突,其中需要调用词组比较函数和词组优先级比较函数;

1) 词组比较函数

比较新词组与哈希表中同一位置词组是否为相同单词;

2) 单词优先比较函数

比较两个相同词组在字典输出的情况下的先后次序;

6、 排序

   利用冒泡排序法对哈希结构体进行排序,将前十出现频率的结构体返回主函数

7、文件输出

利用ofstream函数进行reasult.txt文件的构造;

具体编码:

1、 文件遍历函数:

利用findfirst函数与findnext函数,不断利用文件地址对文件进行遍历,在遍历的同时将地址字符串传入到文件读取子函数中;

2、 文件读取函数:

在文件遍历中调用此函数,利用传入的地址和ifstream函数对文件进行打开操作,设置一个字符数组,再用getline函数将文件中的数据传入数组中,由于getline是读取文件的一行,此时便可以记录行数的变化,当生成一个数组时便调用字符统计子函数并返回一个值代表字符数,调用单词统计子函数并返回一个单词数,调用词组统计子函数不返回值。

3、 字符统计函数:

判断从文件读取子函数传入的字符数组中的字符,并计数

4、 单词统计函数:

从字符数组的首地址开始依次判断,符合单词的条件便调用单词哈希构造子函数;

(1)单词哈希构造函数:

利用单词的前四位相同的条件,将其ASCLL码值进行求和,再平方取模,得到的便是存入的地址,为了同时统计单词的个数,构造了结构体数组,在结构体中存入单词与频率,在存入哈希表中时,如果地址处已存单词,需要进行相同性的比较与优先级的比较,于是调用单词比较子函数与单词优先比较子函数;

(2)单词比较函数:

比较传入的两个单词,依次字符进行比较,遇见不同地方便进行判断,如果相同字符数小于4个,则返回不同,如果大于4,则判断之后是否全是数字;

(3)单词优先比较函数:

此函数在单词比较之后调用,此时传入的两个单词均为相同,则先判断相同字符的优先,如果相同则判断不同的优先;

5、 词组统计函数:

为了不与单词发生交互,进行单独构造,遇见单词则判断之后是否有单词出现,如果没有,从新的地址进行第一个单词的判断,如果有则调用词组哈希构造,之后重复;

(1)      词组哈希构造函数:

利用词组的第一个单词前4个字符与第二个单词前4个字符的ASCLL值求和,平方取模,获得地址,存入哈希表,构造一个结构体存储词组与频率,在存储的时候调用词组比较与词组优先比较函数,类似单词哈希构造

(2)      词组比较函数:

    先判断第一个单词是否相同,再判断第二个,具体操作类似单词比较;

(3)      词组优先判断函数:

    先判断第一个单词的优先,再判断第二个,具体操作类似单词优先比较;

6、 排序函数:

将单词哈希表与词组哈希表中的频率进行排序,采取的是冒泡排序方法,为了同时输出字符串和频率,单独构造了一个结构体存储,此结构体存储的是前十的字符串与频率;

7、 文件输出函数:

利用ofstream函数生成result.txt文件,并将答案写入文件。

8、 main函数

主函数中调用了一次文件遍历子函数,便是输出的代码。

 

测试结果:

自己构造的测试集:

文件小的时候只能输出正确的行数、字符数与单词数,文件一大程序就会崩溃;

助教给的测试集:

无法全部跑完;

崩溃原因分析:

1、 在读取字符的时候使用的是getline,但之后的调试与编译的时候,出现了数组溢出的事情,所以在get与getline的选择上出现了错误,应该选择更加安全的get,

2、 对于哈希表的构造不够好,由于自己是用结构体数组,也会出现数据溢出的问题,还有关于哈希函数的构造也不够好,容易发生冲突,导致的大量的计算与调用函数,使得程序运行很慢;

3、 在判断单词与词组的时候,需要考虑的东西很多,很容易就会忽视一个,导致程序无法正常运行,由于多条条件的判断导致自己很容易出错;

4、 比较难以实现的是对哈希表的排序,最终确定了使用冒泡排序,这也导致了运行时间过长;

5、 各类细节问题,例如一开始使用的是int型数据,到最后才意识到了需要使用长整型,导致了代码很多地方需要修改,以至于发生了一些不可描述的问题;

代码优化:

1、 在一些循环语句中,例如for循环,一开始判定的条件是到达数组地址最大值的时候停止,经过考虑,于是使用了计算字符串长度的函数,将条件表达式的里的值改成了字符串真正懂得长度,但任然大量的调用了strlen函数,在代码交上以后又想到了可以直接使用do……while循环,直接判断数组为空,便可停止循环;

2、 尽量使用有符号长整型,但为了答案不会出错,我选择了无符号,这会大量浪费运行时间,应该将不需要无符号的数改为有符号;

3、 函数调用过于深,这次的程序发生了5层函数的调用,最好可以将其简化;

4、 有一点没用注意,便是没用多使用const,因为如果一个const声明的对象的地址不被获取,允许编译器不对它分配储存空间。这样可以使代码更有效率,而且可以生成更好的代码。

5、 热行分析

 

由于采用了无比慢的排序方法导致的两个sorting函数运行所占时间很多;

 

教训与总结

首先从架构来说,自己在项目一开始的时候没有确定一个特别明确的架构,导致在编码的时候发现了思路不清楚的问题,之后才逐渐完善了架构,便浪费了不少时间,一个好的架构不仅在开发上有助于代码的实现,还能解决程序耦合的问题;其次是没有一个明确的设计方案,只是大致一想,就开始编码,一边编一边想解决方案,导致了很深的函数调用,最终不易于调试与修改;再是自己在编码的时候忘记了先编好输出以便于一边编一边测试,导致了自己苦于编好了很多函数却在测试时跳出了无数的bug,而且不易于修改,这个问题老师很早在课堂上提到过,要编几行就进行测试,而自己却没有注意,运行的时候十分的后悔,过于复杂的程序导致了我不知如何去修改;最后就是书到用时方恨少,对于文件遍历的问题自己将近花费了五分之一的时间,就是由于自己对于这个方面了解的太少,只能临时抱佛脚,还有本来可以用C++的一些类就可以很容易解决的问题,只能自己利用C语言复杂的进行编写,例如同学使用了一个C++中map的类就可以解决存储的问题,自己感觉用的方法都很“蠢”,不够灵活。

在这次个人作业中,我深深地感受到了自己在编码方面的严重不足,不仅是对于各个语言的理解,还有是对于它们的灵活运用,由于自己知识储备的严重不足,遇到问题都无法及时给出一个合适的解决方案,需要一个个去百度,甚至是去从头去看书,在这个地方花费的时间将近有四分之一,导致了自己的思路不够流畅,所以要加强自己对于编程书的阅读,不能再拘泥于老师布置的任务,从现在开始要学习C++等更加便捷的语言,还有以后在编程之前要进行一次对于设计的思考,等到自己感觉设计已经明确并且可行时,再进行编码,还有就是要注意好每一个细节,尽量在编码的时候就最好注意到,最后也是我印象最深刻的就是随时编码随时测试,多写注释,避免遗忘。综上所述,简言之就是“无他,唯手熟尔”,以后自己要多思考、多编程。

 

转载于:https://www.cnblogs.com/Whydd/p/8678068.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/466290.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

树莓派Pico的一些有趣的基本实验

▲ 实验电路板Raspberry PI Pico小型MCU模块,以其价格低廉,功能丰富,开发方便为很多非电子类专业的同学进行创意项目原型设计提供了方便的平台。下面的一些实验给CDIE课程设计同学们制作的一些基本演示实验。▌01 PI Pico实验板在 RASPBERRY …

Gabor变换

gabor变换分析非平稳信号有弊端主要是时频窗宽度固定 小波wavelet a小窗窄a大窗宽 窗口或短时傅氏变换在时域上和频域上的局部化程度主要由窗函数g(x)的有效时宽Δt 和有效带宽Δf 决定。Δt 和Δf 越小, 表明局部性越好。但Heisenberg 测不准原理指出[ 6] :Δt 和Δf 不可能任…

30块钱的树莓派跑unix系统,源码全部开源,香

▌ 1、前言之前做活动抽奖送的几个树莓派,但是因为好几个人都没有填写地址,所以就只能把东西寄回来给我,然后手痒自己玩了下,觉得这个东西确实很香,比一般的Linux开发板都好。PICO这个开发板可以玩很多东西1 、运行pic…

为什么大家都只谈薪资,却不谈梦想?

说个薪资的问题,最近在帮一个朋友物色工作,当然,除了我那个朋友以外,也有挺多同学向我咨询offer薪资的问题。先说我那个朋友。高中毕业后去当兵,服兵役结束后去4s店修车,我车子的很多问题也会向他咨询&…

差生的 8 年程序员总结

今年终于从大菊花厂离职了,离职前收入大概60w不到吧,在某乎属于比较差的,今天终于有空写一下自己的职场故事,也算是给自己近8年的程序员工作做个总结复盘。近8年有些事情做对了,也有更多事情做错了,在这里记…

Python简单的抓取静态网页内容

import requests from bs4 import BeautifulSoup res requests.get(http://news.sina.com.cn/china/)#获取目标网页 res.encoding utf-8#抓取网页出现乱码 #print(res.text) soup BeautifulSoup(res.text,html.parser)#爬取网页 for news in soup.select(.news-item): if le…

直观感受电路信号波形:半波整流电路

前言电子电路的理论很抽象,所以多看电子电路的信号波形,对掌握理论知识非常有帮助。让我们通过形象的电路信号波形,直观地了解电路的世界!半波整流电路半波整流电路,电路图很简单,通过一个二极管实现半波整…

【nodejs】安装browser-sync 遇到错误提示

首先我用的是mac电脑在我执行安装browser-sync时遇到如下问题: 因为不被允许所以我只能不安装全局了: 但是又出现了如下的新问题 纠结了半个小时,终于知道为什么会出现这个问题了, node只有--global or -g才是全局安装的包&#x…

本机获取Intel AMT IP地址的例子

转自:http://software.intel.com/zh-cn/blogs/2009/02/10/intel-amt-ip/?cidsw:51cto Intel AMT的IP地址设置有两种模式:静态IP和动态IP。 在动态IP,也就是DHCP自动分配的情况下,本机的操作系统起来后,Intel AMT的I…

如何解密单片机内程序?

▌单片机解密是什么?单片机解密又叫单片机破解,芯片解密,IC解密,但是这严格说来这几种称呼都不科学,但已经成 了习惯叫法,我们把CPLD解密,DSP解密都习惯称为单片机解密。单片机只是能装载程序芯…

拆解玩具电池充电器:充久了可能会爆,廉价电路方案让人震惊!

▲ 本文要分析的电路家里有不少给小孩子买的电动玩具,感叹现在的电动玩具虽然才几十块钱,但是不仅包邮,还附送充电器和可充电电池,真的很便宜,大家都买得起。下图这款充电器忘了是哪个玩具附送的,看起来像模…

炒股从负债百万,到“睡后收入”上百万,我做了这件事!

问你一个很残酷的问题:你炒股到现在,赚钱了吗?因为股市里永远存在着“7亏2平1赢”的规律。如果你想要在市场里保持持续的盈利状态,你就得成为其中的“1”,而不是7和2!也就是说,想要在市场里立足…

I/O流总结

一,I/O流概述I/O流简单的理解就是数据的输入与输出;那数据的的输入与输出又怎么理解呢?首先我们知道,所有的数据在计算机中都是以二进制的形式存储的.我们看到的字节或者字符形式的文件都是计算机经过解析之后形成的.那么数据的输入与输出简单地说,就是我们向计算机(通信设备)…

单片机显示原理

▌一.接口LCD1602是很多单片机爱好者较早接触的字符型液晶显示器,它的主控芯片是HD44780或者其它兼容芯片。与此相仿的是LCD12864液晶显示器,它是一种图形点阵显示器,能显示的内容比LCD1602要丰富得多,除了普通字符外&…

Overview of ISA and TMG Networking and ISA Networking Case Study (Part 2)

老方说:此篇文章摘自ISASERVER.ORG网站,出自Thomas Shinder达人之手。严重建议ISA爱好者看看。Published: Dec 16, 2008 Updated: Jan 21, 2009 Author: Thomas Shinder In our last article . ISA and TMG firewall networking, I talked about how I…

WIN10 vagrant和virtualbox虚拟机和一键搭建lnmp环境配置thinkphp虚拟主机

版本:win10系统  virtualbox:5.1.26  vagrant :1.9.7  centos 7.0  xshell/git 首先下载好对应版本的软件 配置vagrant和virtualbox 一.把虚拟机加载到box容器中 vagrant box add CentOs7.0 D:\soft\Vagrantfile\package.boxCentOs7.0 是给虚拟机起的名字 D:\soft\Vagr…

Linux 驱动开发 | 驱动世界里的宏伟建筑

哈喽,我是老吴。是否每一个上进的人都会觉得自己还可以再努力一点?事情到了最后,只要没达成目的,总能把失败的原因归为 "没有再努力一点"。但是,对努力的最大错误认知就是:时间越长,过…

【乡音】海安话四级考试

海安话四级考试海安话国家四级考试试卷-------------启用前★绝密------------(中国标准话语言研究中心命题) 准考证号___________ 姓名_____________ 座位号___________ 一、选择题(共五题&#xf…

POJ1179 Polygon 【例题精讲】

题意:多边形游戏是一个单人玩的游戏,开始时有一个由n个顶点构成的多边形。每个顶点被赋予一个整数值,每条边被赋予一个运算符“”或“*”。所有边依次用整数从1到n编号游戏第1步,将一条边删除随后n-1步按以下方式操作(1)选择一条边…