软件工程第二次实践

实现一个能够对文本文件中的单词的词频进行统计的控制台程序

1.Github项目地址: xinz
2.PSP表格
1476398-20180909134029680-508291419.png
3.解题思路描述:拿到题目之后,先总的浏览了两遍,大致上明白了题意和需要用的知识。首先得先通过学习学会如何使用c++读取和写入文本文件,这需要花费一段时间。读到文本和通过读取字符,一个字符一个字符判断,分别根据不同的字符来进行判断是否为单词。如果是单词则与结构体中存在的单词判断,如果单词存在,单词个数+1,不存在则放入结构体中。然后因为需要统计词频,所以还需要对字符串操作的相关知识,并且需要设计一个算法来排序单词出现的次数,通过查阅书本和上网浏览资料完成。
4.设计实现过程:

  • 代码中会有一个结构体来储存出现的单词和其对应出现的频率
  • 一个类来对文本进行操作,具体函数如下
    • 一个统计字符的函数
    • 一个统计行数的函数
    • 一个统计单词和其频率的函数
    • 一个将结果输出的文本的函数
    • 一个得到字符数的函数,用于单元测试
    • 一个得到单词数的函数,用于单元测试
    • 一个得到行数的函数,用于单元测试
  • 一个判断是否为字母的函数
  • 一个判断是否为数字的函数
  • 一个用来将结构体排序的函数
  • 单元测试的设计
    • 测试当输入文件为空时,统计字符结果为0
      • 测试样例是一个空的文件夹
    • 测试判断行数是否正确
      • 测试数据是一个三行的文本
        1476398-20180910113053082-811586729.png
    • 测试判断单词统计是否正确
      • 测试数据是同一个单词 但是大小写形式不同
        1476398-20180910113329911-193976012.png
    • 测试结果截图
      1476398-20180910122429316-1646181341.png

    • 三个测试的代码如下

namespace countchartest                         //第一测试
{       
    TEST_CLASS(UnitTest1)
    {
    public:
        
        TEST_METHOD(TestMethod1)
        {
            // TODO: 在此输入测试代码
            char file[100] = "input.txt";
            FILE *f;
            fopen_s(&f, file, "r");
            myfile ff;
            ff.countchar(f);
            Assert::AreEqual(ff.getchars(),0);
        }

    };
}
namespace countlinetest                         //第二测试
{
    TEST_CLASS(UnitTest1)
    {
    public:

        TEST_METHOD(TestMethod1)
        {
            // TODO: 在此输入测试代码
            char file[100] = "input.txt";
            FILE *f;
            fopen_s(&f, file, "r");
            myfile ff;
            ff.countline(f);
            Assert::AreEqual(ff.getlines(), 3);
        }

    };
}
namespace countwordtest                         //第三测试
{
    TEST_CLASS(UnitTest1)
    {
    public:

        TEST_METHOD(TestMethod1)
        {
            // TODO: 在此输入测试代码
            char file[100] = "input.txt";
            FILE *f;
            fopen_s(&f, file, "r");
            myfile ff;
            ff.countword(f);
            Assert::AreEqual(ff.getwords(), 1);
        }

    };
}

5.改进思路:一开始是想用冒泡排序来排序结构体,后来选择了相对速度更快的快排来代替。
6.代码说明:

  • 判断是否为单词并且统计单词个数
void myfile::countword(FILE  *f)
{
    char ch;
    int flag = 1;
    int x;
    int i, j;
    while (!feof(f))                                            //读单词写入结构体,并统计单词个数
    {
        ch = getc(f);
        if (ch == ' ' || ch == 10)                              //出现空格或换行的情况跳过
        {
            flag = 1;
            continue;
        }
        if (isnum(ch))                                          //flag用于出现“7english”情况的错误判断
        {
            flag = 0;
            continue;
        }
        if ((ischar(ch)) && flag == 1)
        {                                                       //当出现一个字母,并且前一个相邻的不是数字时进入
            int k = 0;
            x = 0;
            s.count = 1;
            while ((ischar(ch)) || (isnum(ch)))
            {
                if (x <= 3 && (isnum(ch)))                      //没有符合至少以四个英文单词开头
                {
                    k = k - x;
                    flag = 0;
                    break;
                }
                s.word[k++] = tolower(ch);                      //将大写转换为小写
                ch = getc(f);
                x++;
            }
            if (flag == 0) continue;
            if (x <= 3)                                         //如果出现字符数小于4个的情况,不算单词
            {
                k = k - x;
                continue;
            }
            s.word[k++] = '\0';
            j = words;
            for (i = 0; i < j; i++)                             //与结构体中比较,如果存在,则改单词次数+1
            {
                if (strcmp(s.word, str[i].word) == 0)
                {
                    str[i].count++;
                    break;
                }
            }
            if (words == 0 || i == j)                           //不存在将单词写入结构体中
            {
                str[words++] = s;
            }
        }
    }
}

7.心路历程与收获:通过本次任务,看到了自身的不足,对于c++的学习还没有到位,临时去学习的文件输入输出流,所以前期准备就花费了很多时间。而且自己完成的算法也不算是有效的,所以今后会利用空闲时间补缺补漏,弥补自己不足的地方,多加强学习。在接触github之后,通过几次都commit,理解了为什么每次代码有进展之后都要commit,这样可以让自己的思路清晰,时刻知道自己的进度和自己的编程经历。通过这次任务也第一次接触了单元测试的理念,感觉这是一个很好测试程序的办法,没有做好的是,单元测试应该在写代码之前就构思好,在写完一个功能就进行测试,但是本次任务是完成所有功能之后才进行的单元测试,以后会改正。通过本次任务,收获了很多知识,虽然花费的挺多的时间,但是过程和结果都感觉很充实,很享受专注做一件事情的感觉,希望以后还能再接再厉。虽然本次任务完成了,但是相关的学习还会继续,并且会学习其他方面的内容,为之后的任务做准备。

转载于:https://www.cnblogs.com/wzh7/p/9610968.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值