软件工程::个人作业

 

作业要求:

1.对于一个目录下(递归)的所有文本文件(文件扩展名:“TXT”,“CPP”,“H”,“CS”),计算出每个单词的频率,并把结果输出到一个文本文件中。编写代码C ++或C#,使用Net框架,运行环境是32位Win7或Win8。

2.单词前四个字符需为英文字母,再其次是可选的字母数字字符。词由分隔符分隔。如果字符串包含非字母数字字符,它不是一个字。 大小写不敏感。

3.以<word>: number形式输出文本至文件中。首先按照出现频率由高到低排序,其次依据字典序排序。

4.具有两种模式:简单模式与扩展模式。在扩展模式中,字母部分相同,结尾为不同数字的视为相同单词。

5.发布博客,总结作业。

 

  首先拿到这个作业,我面对的最大的问题就是编程工具的问题。我对C++与C#的认识非常浅薄,是不能用来编程的。但是C++与C#中的一些库函数使用起来十分便捷,是C语言不能代替的。因此,我决定用大概5天的时间来学习C++语言。

  这5天中,我每天用课余的时间用尽量快的速度浏览C++ Primer,希望能够尽早学会C++语言。幸好,C++语言与C语言的相似之处很多,这节约了我不少时间。我试着编了一些比较简单基础的程序,来熟练C++这门语言。

  然而,尽管对于C++具有了一定了解,我仍然没有什么思路。在苦思无果后,我请教了杜冰磊同学,并阅读了他的代码,从中得到了很大启发。

  分析该作业,主要有以下几个步骤:文件输入,读文件,提取单词,统计词频,对单词及词频进行排列,最后写文件输出。并且在此过程中还要处理两种模式。

  其中如何记录单词和处理模式是最困难的。从同学的思路中,我得知了一种很好的方法来解决这个问题。创建两个map,一个储存单词与词频,另一个储存统一格式的单词和其对应的各种单词,取ascII最小的保留。这样,既能够记录词频,又能够保证输出的代表词汇符合要求。最后只要将两个map整理到一个容器中排序输出即可。

  我计划的花费时间如下:

—文件输入输出 1h

—提取单词 0.5h

—统计词频 1h

—排序 2h

  但是,在实际变成中,我花费了比这多得多的时间。实际时间大概如下:

—文件输入输出 2h

—提取单词 0.5h

—统计词频 3h

—排序 3h

—Debug 3h

  这整整花费了我一个晚上和一个白天的时间。这说明我的编程能力还不到家,还需要进一步的思考与练习。

 

  其中,我最满意的一部分代码是扩展模式的代码:

string function_exended(string headword){
    if(headword.begin()==headword.end())
        return headword;
    while(1){
        if(isdigit(*(headword.end()-1))){
            headword.erase(headword.end()-1);
        }
        else
            break;
    }
        return headword;
}

  这段代码将数字结尾的单词提取出来并归类,实现了扩展功能的添加。

  而我最不满意的一部分是排序的部分:

map<string,string>::iterator hiter=head_map.begin();
    list<pair<string, int> >::iterator liter;
    for(;hiter!=head_map.end();hiter++){
        liter=out_list.begin();
        for(;out_list.empty()==0 && frequency[hiter->first] < liter->second 
            && liter!=out_list.end();liter++)
            ;
        for(;out_list.empty()==0
            && liter!=out_list.end()
            && (frequency[hiter->first] <= liter->second)
            && (hiter->second > liter->first);liter++)
            ;
        out_list.insert(liter,make_pair(hiter->second,frequency[hiter->first]));
    }

  这个排序虽然不长,但是复杂度很高,使程序限制在很小的文件统计上,规模稍大就会陷入长久的统计中。

  另外,文件的遍历过程还参考了一些资料:

C++遍历文件夹下的文件http://www.oschina.net/code/snippet_119226_6095

 

  在程序的最后调试阶段,出现了一些匪夷所思的bug。例如,排序中,我漏写了一个判断条件,导致在cmd运行时陷入死循环。然而,当我注释掉命令行读入的代码部分时,结果却正常输出。这让我们一度把眼光集中于命令行上,实际上并没有什么关系。这浪费我们很长的时间,可惜我们还是对原因不得而知,希望能够得到老师和助教的指导。还要感谢,在这个凌晨陪伴我debug的杜冰磊同学和刘昊言同学,谢谢你们!

  由于vs2012的一些环境问题,以及代码需要优化,故代码分析没有成功,将会在接下来时间继续优化。

  测试点如下:  

Test1: 空文件夹。

Test2: 文件夹下有20个文本文档。

Test3: 若干空文件。

Test4: 文本文档内有汉字。

Test5: 文件夹下有cs,cpp,h文件。

Test6: 测试拓展模式。

Test7: 词条含有“office”,”office98”,”office2000”,”offi100ce”,”Office”。

Test8: 文件夹下有空文件夹和文档。

Test9: 200M文件夹一个。

Test10: 将以上所有测试文件放入同一文件夹。

  经过本次作业,首先我的自学能力加强了,能够应付更艰难的任务;在学习中也找到了一些窍门。我会将收获应用到接下来的学习中。

posted on 2013-09-25 09:51  libcan  阅读(277)  评论(1编辑  收藏  举报