软工实践第二次作业 - 个人项目

  • GitHub地址

    https://github.com/huabei-li/personal-project
  • PSP表格

    PSP2.1Personal Software Process Stages预估耗时(分钟)实际耗时(分钟)
    Planning计划1520
    · Estimate· 估计这个任务需要多少时间400720
    Development开发200300
    · Analysis· 需求分析 (包括学习新技术)150200
    · Design Spec· 生成设计文档3020
    · Design Review· 设计复审3030
    · Coding Standard· 代码规范 (为目前的开发制定合适的规范)2010
    · Design· 具体设计5060
    · Coding· 具体编码300400
    · Code Review· 代码复审3030
    · Test· 测试(自我测试,修改代码,提交修改)30120
    Reporting报告6090
    · Test Repor· 测试报告3030
    · Size Measurement· 计算工作量1010
    · Postmortem & Process Improvement Plan· 事后总结, 并提出过程改进计划3030
    合计13852070
  • 功能要求参见作业要求博客

  • 解题思路

    作业要求实现对文本文件中的单词词频做出统计,拿到题的时候先想到了以前做过的对句子单词统计,对文件单词统计的差异在于文件存在多个行。但是也可以想作对文件中的多个行进行统计。在代码中体现为countWord1()将文件的每一行送入countWord2(),countWord2进行单词的判断和数量的统计,同时将单词信息存入unordered_map里,便于topten()函数的字数统计。topten()函数利用了百度的对value值排序的方法,并输出了出现频率前十的单词。countChar_Line()用于统计字符和行数。这是大致的思路。

  • 实现过程

    逻辑结构如图所示

    1092183-20180910104346660-1042301313.jpg

    关于接口。如果按照以前的习惯,基本上都是讲所有的功能都写在一起,显得代码很乱。将主要功能都独立成函数,把操作对象相似的函数都放在一个类里,条理和逻辑都比较直观。没有把统计输出的语句集成函数,是受到C++老师的影响(如果函数有输出会带来调试的负担,特别在合作开发时)。

创建了class file,将对文件统计的一些信息,功能都集合在一起,便于理清结构。

  • 关键代码

    部分主要函数代码

    countWord1() 对文件读行操作

void countWord1()
    {
        string File, temp;
        fstream file(fname);
        while (getline(file, File))
        {
            File.append(temp);
            temp.clear();
            for (int i = 0; i < File.length(); i++)
            {
                if (File[i] == '\n')
                    File[i] = ' ';
                if (ispunct(File[i]))
                    File[i] = ' ';
            }
            stringstream ss(File);
            countWord2(ss);
        }
    }

countWord2() 判断单词,统计数量,存入unordered_map

void countWord2(stringstream &ss)
    {
        string stemp;
        while (ss >> stemp)
        {
            for (int i = 0; i < stemp.length(); i++)
            {
                if ('A' < stemp[i] && stemp[i] < 'Z')
                    stemp[i] += 32;
            }

            if (stemp.length() < 4)
            {
                continue;
            }
            if ((stemp[0]>'z' || stemp[0]<'a' || stemp[1]>'z' || stemp[1]<'a' || stemp[2]>'z' || stemp[2]<'a' || stemp[3]>'z' || stemp[3]<'a'))
            {
                continue;
            }
            numWords++;
            unordered_map<string, int>::iterator it = My.find(stemp);
            if (it == My.end())
            {
                My.insert(unordered_map<string, int>::value_type(stemp, 1));
            }
            else
                My[stemp]++;
        }
    }

topTen() 按照value排序输出前十单词(啪啪打脸,函数有输出是觉得功能比较统一)

(更新)最近的更新把输出给挪出去了

void topTen()
{
    vector<pair<string, int>> VM;
    for (auto it = My.begin(); it != My.end(); it++)
    {
        VM.push_back(make_pair(it->first, it->second));
    }
    sort(VM.begin(), VM.end(), [](const pair<string, int> &x, const pair<string, int>&y)->int {return x.second > y.second; });
    int c = 0;
    for (auto it = VM.begin(); c < 10; it++, c++)
    {
        cout << it->first << ":" << it->second << endl;
    }
}

关于注释,习惯上是对于比较难搞混的变量进行解释,对于比较直观的函数等没有做出太多的说明。个人认为过多的注释会使代码看起来太乱,而且这一次的代码量也不需要太多的注释。因为这一次的代码都是给自己看的,所以看懂就好了,如果是合作完成的话,还是尽量把功能都注释清楚比较好。

  • 测试结果

    如图

    1092183-20180910105946146-1370187279.jpg
    1092183-20180910105952025-1010028696.jpg

    关于测试数据的设计,除了应尽可能地照顾所有的情况,还要考虑对于大文件的测试时间消耗。从网上找了一部原著资源,跑了一下感觉还是比较快的,得益于数据结构方面的选择还是比较合适的,没有走太多弯路。

  • 性能分析及改进

    利用visual studio 2017 的性能测试工具

    1092183-20180910110139752-1816940900.jpg
    1092183-20180910110147180-1381342307.jpg

    相关信息都在图上了

  • 一些问题

    关于单元测试:尝试了一下但是没有实现,对这个还是不太清楚还需要进一步的尝试。如果按照我自己的理解,每完成一个特定的功能是要事先测试一下是否能正确完成,每一部件都能正常工作再组合在一起。

    关于异常处理:当程序运行时发生了特殊情况,异常处理能够提供转移程序控制权的方式,从网上看了很多资料,尝(xia)试(xie)了一些类似的代码,写了一个最简单的:当文件读取失败时报出异常(我真机智),当文件打开失败时,throw出一个错误提示。

    (更新)最大的一个问题!:关于文件的读取真的是犯了一个贼大的错误。按照要求是需要控制台输入文件。当时望文生义是控制台给出路径……也没有百度具体含义,之前也没接触主函数参数,所以就用的是文件路径打开文件,而且全程都用了这个路径……导致现在要想修改正确要大改……真的是无法原谅的错误,导致在最后测试的时候可能写的程序都不能正常运行。尝试是否能在规定时间内修改正确,但是真的来不及,函数的功能结构都要改掉。

  • 心得收获

    第一次作业如果只是实现功能的话不是很难,花大概两天多的时间查找资料,学习新知识就能写个差不多。但是做起来还是感觉比较匆忙,后续的git,性能分析,测试,单元测试,异常处理之前都没有接触过,要学习的东西很多。这一次作业也就这样七七八八的写成这个样子了,有很多缺陷和不完善的地方,希望能考虑到各种功能和尽可能多的情况。花了很多时间,学到了很多东西,再一次受到打击。很多东西不是浅显易懂的,通过实践能够加深理解,但是也就增加了开始操作的难度。以前对于编码的工作的重点都集中在功能实现上,这一次则还要考虑各个部件的性能,异常处理,测试等等。花的时间不少(每一步都有挺费时间的),但是学习的效果不明显,希望通过积累能有慢慢的改善吧。

posted on 2018-09-11 17:47 huabei_li 阅读( ...) 评论( ...) 编辑 收藏

转载于:https://www.cnblogs.com/031602418matt/p/9617902.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值