• 第二次作业——词频统计2.0


    作业要求:

      参见博客:http://www.cnblogs.com/jiel/p/3311400.html

    设计思路:

      定义一个词典类,实现查找,插入,排序,输出等操作。

      对于扩展要求-e,通过整合合并词典操作即可。

    已经实现功能:

    1. 统计词频,按照出现次数由高到低输出到文件;
    2. 普通操作中,大小写不同算作同一个单词,按照ASCII序列统计输出;
    3. -e 操作中,尾缀(仅数字)不一样算作同一单词,按照ASCII序列统计输出。 

    代码:

      GitHub: https://github.com/chynphh/Word-frequency-program

    #include <iostream>
    #include <string>
    #include <stdio.h>
    #include <fstream>
    #include <algorithm>
    using namespace std;
    
    const int LIST_MAX = 10000;
    static int num = 0;
    
    //-e 功能中 提取前面部分
    string extract(string w)
    {
        string s;
        int l = w.size(), i;
        for(i = l - 1; i >= 0; i--)
        {
            if(w[i] > 57)break;
        }
        s = w.substr(0, i + 1);
        return s;
    }
    
    //词典类
    class Dictionary
    {
    public:
        int find(string w); //查找是否有这个单词
        void put(string w, int loc); //放入词典
        void sort(); //词典排序
        void out(); // 词典输出
        int merge(); //整合词典 -e功能
    
    private:
        string word[LIST_MAX];
        int freq[LIST_MAX] = {0};
    };
    
    int Dictionary::find(string w)
    {
        string w_lower, word_lower;
        w_lower = w;
        transform(w_lower.begin(), w_lower.end(), w_lower.begin(), ::tolower);
        for(int i = 0; i < num; i++)
        {
            word_lower = word[i];
            transform(word_lower.begin(), word_lower.end(), word_lower.begin(), ::tolower);
            if(w_lower.compare(word_lower) == 0)
            return i;
        }
        return -1;
    }
    
    void Dictionary::put(string w, int loc)
    {
        freq[loc]++;
        if(loc == num)
        {
            word[loc] = w;
            num++;
        }
        if(w.compare(word[loc]) < 0)
            word[loc].assign(w);
        return ;
    
    }
    
    
    void Dictionary::sort()
    {
        for(int j = 1; j < num; j++)//进行n-1次循环,n-i趟比较
            for(int i = 0; i < num - j;i++)//每趟进行n-i-j次比较
            {
                if(freq[i] < freq[i+1])//相邻两数进行比较
                {
                    int t = freq[i];
                    freq[i] = freq[i+1];
                    freq[i+1] = t;
                    string ts = word[i];
                    word[i] = word[i+1];
                    word[i+1] = ts;
                }
                else if(freq[i] == freq[i+1])
                {
                    if(word[i].compare("") == 0 || word[i].compare(word[i+1]) > 0)
                    {
                        int t = freq[i];
                        freq[i] = freq[i+1];
                        freq[i+1] = t;
                        string ts = word[i];
                        word[i] = word[i+1];
                        word[i+1] = ts;
                    }
                }
            }
        return ;
    }
    
    void Dictionary::out()
    {
        ofstream fout("output.txt");
        if(!fout.is_open())
        {
            cout << "file can not open" << endl;
        }
        else
        {
            for(int i = 0; i < num; i++)
                fout << word[i] << " : " << freq[i] << endl;
            fout.close();
        }
    
        return ;
    }
    
    int Dictionary::merge()
    {
        int sum = 0;
        string s1, s2;
        for(int i = 0; i < num - 1; i++)
        {
            s1 = extract(word[i]);
            transform(s1.begin(), s1.end(), s1.begin(), ::tolower);
            for(int j = i + 1; j < num; j++)
            {
                s2 = extract(word[j]);
                transform(s2.begin(), s2.end(), s2.begin(), ::tolower);
                if(s1.compare(s2) == 0)
                {
                    freq[j] = freq[j] + freq[i];
                    freq[i] = 0;
                    if(word[i].compare(word[j]) < 0)
                    {
                        word[j] = word[i];
                        word[i] = "";
                    }
                    sum++;
                    break;
                }
    
            }
        }
        return sum;
    }
    
    // 提取字符串中的第一个单词
    string check(string *s)
    {
        string b;
        int l = 0, start = -1, end = 0, flag = 1;
        l =(*s).size();
        if(l < 4) return "";
        for(int i = 0; (i < l) && flag; i++)
        {
            if( (*s)[i] < 48 || ((*s)[i] > 57 && (*s)[i] < 65) || ((*s)[i] > 90 && (*s)[i] < 97) || (*s)[i] > 122)
            {
                if( start > -1)
                {
                    end = i;
                    flag = 0;
                }
            }
            else if( start == -1 && (*s)[i] > 57)
            {
                start = i;
            }
    
        }
        if(end == 0 && start > -1)
        {
            end = l;
            flag = 0;
        }
        if(!flag)
        {
            b = (*s).substr(start, end - start);
            (*s).assign((*s).substr(end, end - l));
            if(b.size() < 4) b = check(s);
        }
        else
        {
            b = "";
            (*s).assign("");
        }
    
        return b;
    }
    
    int main(int argc, char const *argv[])
    {
        Dictionary dictionary;
        string path_in, s, w = "";
        int loc = 0;
        ifstream fin (argv[argc-1]);
        //ifstream fin ("test.txt");
        if(!fin.is_open())
        {
            cout << "file can not open" << endl;
        }
        else
        {
            while(! fin.eof() )
            {
                getline(fin, s);
                w = check(&s);
                while(w != "")
                {
                    loc = dictionary.find(w);
                    if(loc == -1) dictionary.put(w, num);
                    else dictionary.put(w, loc);
                    w = check(&s);
                }
            }
            int cut = 0;
            if(argc == 3)
            {
                cut = dictionary.merge();
            }
            dictionary.sort();
            num = num - cut;
            dictionary.out();
            fin.close();
        }
        return 0;
    }
    View Code

    数据:

      GitHub上有10组测试数据,input1-4是china daily中的新闻,input5和input6是普通英语作文,input7-10是为了测试功能自编数据(包括分隔符、大小写、尾缀等测试)。output-e*.txt是-e功能下的输出,output*.txt是普通输出,均与输入数据对应。

    使用说明:

      命令行输入:词频统计.exe -e filename.txt 或者 词频统计.exe  filename.txt

      结果将输出至:output.txt

    输出截图:

      

      

      

    用时:

      原计划全部用时3小时,实际用时5小时。

    分工:

      程昊:代码编写与博客编写

      陈金满:代码测试

     

  • 相关阅读:
    开源的 ASP.Net 错误记录发布模块 ELMAH (Error Logging Modules And Handlers)
    GridView 行单击与双击事件2
    iReaper
    ubuntu下android开发环境搭建(及错误异常处理)
    配置vim开发Android[神器终究是神器]
    Eclipse中文显示乱码问题
    预防鼠标手,从我做起
    ERROR:Android requires .class compatibility set to 5.0. Please fix project properties.
    Thinkpad在linux(ubuntu)下修改电池充电阈值,成功解决Thinkpad在Linux下的电池充电问题
    Eclipse启动时报错:A Java RunTime Environment (JRE) or Java Development Kit (JDK) must be available in order to run Eclipse. No java virtual machine was found after searching the following locations:…
  • 原文地址:https://www.cnblogs.com/Oranswj/p/5936389.html
Copyright © 2020-2023  润新知