软件第四次作业

       作业要求

  • 基于作业3的结果,读取一个较小的文本文件A_Tale_of_Two_Cities.txt,统计该文件中的单词的频率,并将统计结果输出到当前目录下的 Result1.txt 文件。 (第一阶段初稿完成该要求)
  • 命令行格式: 提示符> Myapp.exe -f filename.txt > Result.txt (PS:C++ 程序,Java 程序输出方式类似) filename.txt 为前面下载的文件名。
  • 解释:
    • 选项 -f 表示后面跟文件名
    • 输出格式规定(参考作业3中的示例):
      • 首先按照频率由高到低排序
      • 频率一样的词, 按照字典顺序排序
  • 此外, 读取一个较大的文本文件Gone_with_the_wind.txt实验对比程序执行效率,做如下改进,比较改进前后程序执行时间。PS: 请看一位同学做的效能分析示例

     结对对象:钱佳晨 

      Github:https://github.com/TYshadow/TYshadow/blob/master/4.cpp

     作业共同讨论修改 大致55开

int main()
{
    int wCount = 1;
    Word * words;
    string content;
    string addition;
    const char *delim = " ,'  '“”.''-‘’!?";
    ifstream file("e://Gone_with_the_wind.txt");   //读取
    ofstream fout("e://Result1.txt");
    if (!file)
    {
        cout << "Unable to open ";
        exit(1);
    }
    while (!file.eof())
    {
        getline(file,addition);                                       
        content.append(addition);                                       //分段读取文本
    }
    file.close();
    
    unsigned int len = content.length();
    for (unsigned int i = 0; i < len; i++)
    {
         if (isalnum(content[i]) == 0)                                 //非字母数字
        {
            wCount++;
        }
    }
    cout << wCount;
    words = new Word[wCount];

    string::size_type offset = content.find_first_of(delim);          //单词分隔;size_type用以保存string对象的长度
    while (offset != string::npos)
    {
        string wStr = content.substr(0, offset);                      //string.substr()返回一个从指定位置返回指定长度的字符串
        if (wStr.length() < 4)                                        //除去长度小于4的单词
        {
            wCount--;
            content.erase(0, offset + 1);
            offset = content.find_first_of(delim);
            continue;
        }
        content.erase(0, offset + 1);                                 //string.erase()删除从指定位置开始的指定长度的字符
        transform(wStr.begin(), wStr.end(), wStr.begin(), ::tolower);
        CalcCount(words, wStr, wCount);                               
        offset = content.find_first_of(delim);
    }
    if (content.length() >= 4)
    {
        transform(content.begin(), content.end(), content.begin(), ::tolower);
        CalcCount(words, content, wCount);                           //计算最后一个单词 
    }
    else wCount--;

    for (int i = 0; i < wCount; i++)
    {
        if (words[i].Str == "")
        {
            wCount--;
        }
    }
    SortWord(words, wCount);
    SortWordDown(words, wCount);
    fout << "词频统计:" << endl;
    for (int i = 0; i < wCount - 1; i++)
    {
        fout << words[i].Str << "\t频率:" << words[i].Count << "次" << endl;
    }

    fout << "调用该程序所花费的时间为:" << clock() << "毫秒\n";
    delete[] words;
    return 0;
}

总结:首先用了find_first_of函数解决了上次分隔符的问题,无论哪一种语言,它们的类库都很重要,熟悉掌握这些能够节省很多时间。然后这次的文件读取中,一开始发现大文件无法读取,花了大把时间调试找问题,最后原因还是对函数功能的理解出现偏差,和大钱商讨后选择了分段读取的方式,多一个人可以更加坚定自己的想法,并且确实可以纠正一些思维上的死角。最后再效能分析上,用clock()函数计算了时间,大概是程序偏小,感觉差别并不很大。程序仍待改进。

posted @ 2016-03-22 21:58  刘天宇  阅读(136)  评论(1)    收藏  举报