欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

第二次作业-个人项目

程序员文章站 2022-05-22 13:06:44
...

对代码的改进地址:https://www.cnblogs.com/031602401chl/p/9665968.html
Github项目地址:(https://github.com/AsianLazyMan/personal-project/tree/master/Cplusplus
PSP表格
===========

PSP2.1 Personal Software Process Stages 预估耗时(分钟) 实际耗时(分钟)
Planning 计划 40 80
· Estimate · 估计这个任务需要多少时间 20 50
Development 开发 300 450
· Analysis · 需求分析 (包括学习新技术) 60 120
· Design Spec · 生成设计文档 20 45
· Design Review · 设计复审 30 10
· Coding Standard · 代码规范 (为目前的开发制定合适的规范) 20 25
· Design · 具体设计 60 35
· Coding · 具体编码 180 240
· Code Review · 代码复审 60 120
· Test · 测试(自我测试,修改代码,提交修改) 120 300
Reporting 报告 60 45
· Test Repor · 测试报告 60 40
· Size Measurement · 计算工作量 10 10
· Postmortem & Process Improvement Plan · 事后总结, 并提出过程改进计划 10 30
合计 1050 1560

需求分析

程序所要求的功能有以下几点:

  • 统计文件的字符数(不需要考虑汉字需要考虑空格制表符换行符)。

  • 统计文件的单词总数,单词:至少以4个英文字母开头,跟上字母数字符号,单词以分隔符分割,不区分大小写。
    • 英文字母: A-Z,a-z
    • 字母数字符号:A-Z, a-z,0-9
    • 分割符:空格,非字母数字符号
    • 例:file123是一个单词, 123file不是一个单词。file,File和FILE是同一个单词
  • 统计文件的有效行数:任何包含非空白字符的行,都需要统计。
  • 统计文件中各单词的出现次数,最终只输出频率最高的10个。频率相同的单词,优先输出字典序靠前的单词。
  • 按照字典序输出到文件result.txt:例如,windows95,windows98和windows2000同时出现时,则先输出windows2000
    • 输出的单词统一为小写格式
  • 输出的格式为
characters: number
words: number
lines: number
<word1>: number
<word2>: number
...

思路

第二次作业-个人项目

看到题目后第一想到的就是怎么在程序中读取文件。因为没学过,就去网上找了资料。使用fstream读取txt文件。然后使用getline()函数来读取文件中的每一行。并在函数中对每一行的字符进行操作。然后使用lower()函数把全部字母都变小写。首先先得到每一行的字数,使用temp.size()+1来表示每行的字数.加一是因为行末还有一个回车字符。行数即为每次使用getline时对linenum加1.对行中每一个字符进行遍历。当遇到非单词中的字符时continue。当遇到英文字母或者数字时即为发现新单词。进入对新单词的判断,当所遇到的字符不是空格、句号、逗号等符号时,将字符储存起来,当遇到空格、句号、逗号等符号时,停止储存,并将最后一个字符的后一个字符设为‘\0’.如a[k++]=‘\0’。将单词分割出来后,使用judge()函数判断是否为符合要求的单词。如是拷贝进word2[]中。在储存完所有单词后,检测各个单词的频率。最后进行排序。
  • lower()函数
void lower(string& str) {//大写转化成小写
    for (int j = 0; j < str.size(); j++)
    {
        if (str[j] <= 'Z'&&str[j] >= 'A') {
            str[j] = str[j] + 32;
        }

    }
}
  • 将单词按要求分开
for (int y = 0; y < temp.size(); ) {
            if (p[y] == ' ' || p[y] == '.' || p[y] == '?' || p[y] == '!' || p[y] == ',' || p[y] == '"')
            {
                y++;
                continue;
            }
            else {//发现一个单词
                char *danci = (char*)malloc(sizeof(char)*10);
                memset(danci, 0, sizeof(char) * 10);
                int k = 0;
                while ((p[y] >= 'a'&&p[y] <= 'z') || (p[y] >= '0'&&p[y] <= '9')) {
                    danci[k] = p[y];
                    k++; y++;
                }
                danci[k] = '\0';//终止符号 很重要
                //cout << danci << "*"<<endl;
                if (Judge(danci)) {
                    word2[m].s = danci;
                    word2[m].num = 0;
                    /*if (word2[m].s) {
                        cout << word2[m].s << endl;
                    }*/
                    m++;
                }
            }

输入输出

输入:

aaaa SSSSSS AAAA,SHENZHEN.
KKKKK KK AAAA aaaa?SHENZHEN.
XXXX XXXX XXXX XXXX XXXX!SHENZHEN,SHENZHEN.
"sdsdas" gaomima

输出:

characters:117
words:17
lines:4
word1:xxxx times:5
word2:aaaa times:4
word3:shenzhen times:4
word4:ssssss times:1
word5:kkkkk times:1
word6:sdsdas times:1
word7:gaomima times:1

计算模块接口的设计与实现过程

一共有四个函数分别是大写转化成小写的函数lower(),判断单词是否符合标准的函数judge(),将string转化成char的函数change(),冒泡排序的函数bubble_sort()。
这其中两个函数需要说明。
一是judge()函数。首先判断单词长度是否大于四,而后判断是否是至少四个英文字母开头。
而是转换函数change(),在进行转换后一定要将最后一个字符的后一个字符设定问‘\0’。否则会出现后面计算无法识别单词的情况。
程序的关键是对单词的分割。
当遇到字母或数字是才确定为是一个单词(后面会再用judge()函数判断是否符合标准)。然后继续往后遍历,遇到规定的分隔字符后停止,并将所得到的单词存入word2中,进行后续操作。这样做比较具有可靠性。

计算模块接口部分的性能

第二次作业-个人项目

计算模块部分单元测试展示

第二次作业-个人项目

第二次作业-个人项目

第二次作业-个人项目

第二次作业-个人项目
异常处理
===========

   if (argv[1] == NULL) {
        cout << "No input";
    }
    fstream file(argv[1]);
    if (!file) {
        printf("Unable to open");
    }

总结与感想

处理字符是我平常比较不熟悉的部分,所以这次完成程序花了比较多的时间。比如忘记在字符后加上‘\0’终止符。这花了我非常多时间去找错误。但是也是有了这些错误,才让我对字符方面的编码更加熟悉。收获无疑是很大的。解决错误会给自己带来很多收获。
这次除了学习读取文件的功能有去查找资料外,其他都是自己一点点试出来,感觉比一不懂就去找资料充实得多。