第四次作业——结对编程

GitHub地址 克隆地址
结对伙伴 郭忠杰
伙伴学号 201831061121
伙伴博客地址 胖狙
作业链接 https://edu.cnblogs.com/campus/xnsy/Autumn2019SoftwareEngineeringFoundation/homework/8708
作业要求 https://www.cnblogs.com/harry240/p/11524113.html

                                              软件工程第四次作业——结对编程

一.psp表格

 

 

二.解题思路

这次作业是我和我的室友郭忠杰一起完成的。在刚刚学习了一点点c++后,选择了用这个语言实现这次程序。

首先本次程序的功能要求

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

我们先定义了一个用于计算单词的结构体和一个单词分析的的类。

#pragma once
#include <fstream>
#include <iostream>
#include <unordered_map>
#include <algorithm>
#include <string>
using namespace std;
struct WordInf
{
    string word;
    int count;
    WordInf() {
        word = "";
        count = 0;
    }


};
class TextAnalysisUtil
{
public:

    TextAnalysisUtil();
    ~TextAnalysisUtil();
    int asciiCount(char * fileName);
    bool isAsascii(char ch);
    int countLines(char * filename);
    int wordAnalysis(char * fileName, WordInf * tempArr);



};

然后对类进行具体的实现

//#include "stdafx.h"
#include"pch.h"
#include "TextAnalysisUtil.h"


TextAnalysisUtil::TextAnalysisUtil()
{
}


TextAnalysisUtil::~TextAnalysisUtil()
{
}

bool isWordGreater(string str1, int n1, string str2, int n2)
{
    bool flag;
    if (n1 > n2)
    {
        flag = true;
    }
    else if (n1 < n2)
    {
        flag = false;
    }
    else
    {
        flag = strcmp(str1.c_str(), str2.c_str()) < 0 ? true : false;
    }
    return flag;
}

int TextAnalysisUtil::asciiCount(char * fileName)
{
    //调试用
    ifstream fin(fileName);
    if (!fin)
    {
        cout << "文件打开失败";
        return -1;
    }
    char ch;
    int count = 0;
    while (fin.get(ch))
    {
        if (isAsascii(ch))
            count++;
    }
    fin.close();
    return count;
}

bool TextAnalysisUtil::isAsascii(char c)
{
    return ((unsigned char)c & 0x80) == 0x80 ? false : true;
}

int TextAnalysisUtil::countLines(char * fileName)
{
    ifstream ReadFile;
    int n = 0;
    string tmp;
    int len;
    ReadFile.open(fileName, ios::in);
    while (getline(ReadFile, tmp, '\n'))
    {
        len = tmp.length();
        for (int i = 0; i < len; i++)
        {
            if ((tmp[i] >= 0 && tmp[i] <= 32) || tmp[i] == 127)
            {
                continue;
            }
            else
            {
                n++;
                break;
            }

        }




    }
    ReadFile.close();
    return n;
}

int TextAnalysisUtil::wordAnalysis(char * fileName, WordInf * tempArr)
{
    ifstream fin(fileName);
    if (!fin)
    {
        cout << "文件打开失败";
        return -1;
    }
    char ch;
    string str;
    int state = 0;
    int nflag;
    int wordCount = 0;
    unordered_map<string, int> map;
    while (fin.get(ch))
    {
        if (ch < -1 || ch>255)
        {
            return -1;
        }
        switch (state)
        {
        case 0:
            //查找单词首的状态
            if (isdigit(ch))
            {
                //转入找到数字开头的过滤状态
                state = 1;
            }
            else if (isalpha(ch))
            {
                //找到单词,转入爬取单词状态
                state = 2;
                str = ch;
                nflag = 1;//记录单词开头字母数
            }
            break;
        case 1:
            //转入找到数字开头或不符合单词开头有4个字母的过滤状态
            if (!(isdigit(ch) || isalpha(ch)))
            {
                state = 0;
            }
            break;
        case 2:
            //爬取单词状态
            if (isalpha(ch))
            {
                ++nflag;
                str += ch;
                if (nflag >= 4)
                    //进入爬取单词尾部状态
                    state = 3;
            }
            else
            {
                //不满足单词开头有4个字母
                state = 1;
            }
            break;
        case 3:
            //爬取单词尾部状态
            if (isdigit(ch) || isalpha(ch))
            {
                str += ch;
            }
            else
            {
                //处理和存入字符串
                transform(str.begin(), str.end(), str.begin(), ::tolower);
                state = 0;
                wordCount++;
                map[str]++;
            }
            break;
        default:
            break;
        }

    }
    if (state == 3)
        //处理最后跳出没来的及处理的字符串
    {
        transform(str.begin(), str.end(), str.begin(), ::tolower);
        wordCount++;
        map[str]++;
    }
    //遍历找出频率最高的top10单词
    for (auto iter = map.begin(); iter != map.end(); iter++)
    {
        if (isWordGreater(iter->first, iter->second, tempArr[9].word, tempArr[9].count))
        {
            tempArr[9].word = iter->first;
            tempArr[9].count = iter->second;
            for (int i = 9; i >= 1; i--)
            {
                if (isWordGreater(tempArr[i].word, tempArr[i].count, tempArr[i - 1].word, tempArr[i - 1].count))
                {
                    swap(tempArr[i], tempArr[i - 1]);
                }
            }
        }
    }
    fin.close();
    return wordCount;
}

 

在这个类的实现中有打开文本,记录单词出现的次数,计算文本的行数,遍历输出文本中出现频率最高的10个单词这几个函数。

 

最后是功能的实现

#include"pch.h"
#include <iostream>
#include <fstream>
#include "TextAnalysisUtil.h"
using namespace std;
int main(int argc, char *argv[])
{
    if (argc < 2)
    {
        cout << "未输入命令行参数" << endl;
        system("pause");
        return -1;
    }
    TextAnalysisUtil TA;
    ifstream infile;
    WordInf tempArr[10] = {

    };
    infile.open(argv[1], ifstream::binary | ifstream::in);
    if (!infile) {
        cout << "文件打开失败" << endl;
        system("pause");
        return 1;
    }
    infile.close();
    ofstream outFile;
    outFile.open("result.txt");
    if (!outFile) {
        cout << "文件打开失败" << endl;
        system("pause");
        return 1;
    }
    outFile << "characters: " << TA.asciiCount(argv[1]) << endl;

    outFile << "words: " << TA.wordAnalysis(argv[1], tempArr) << endl;
    outFile << "lines: " << TA.countLines(argv[1]) << endl;
    for (int d = 0; d < 10; d++)
    {
        if (tempArr[d].count > 0)
            outFile << "<" << tempArr[d].word << ">: " << tempArr[d].count << endl;
    }
    system("pause");
}

 

在程序中会生成一个文本文件记录单词的个数和高频词。

三.代码结果

目标初始文本

 

 

 

 

 

结果文本

 

 

四.代码性能分析

 

 五.代码复审

1.我们采用的模型是写了再改模型,遇到了一个典型的麻烦就是一个地方改动,其他的地方就要跟着变,不过还好不是很麻烦。

2.由于我们C++的功底不是很牢,最开始出现了很多的语法错误,纠正后自己的语法能力也得到了提升。

3.可读性的话个人认为还是比较好,因为经过两个人的审查我觉得已经可以比较容易阅读。

4.设计的缺陷我觉得还是比较大,毕竟开发的时间也不长,而且对C++也比较不熟悉。

六.结对编程

 

posted @ 2019-10-15 12:41  Mking-  阅读(165)  评论(1编辑  收藏  举报