字符串IO、文件IO的应用

字符串IO的应用

1、统计一篇英文(The_Holy_Bible.txt)文章中出现的单词和词频。
输入:某篇文章的绝对路径
输出:词典(词典中的内容为每一行都是一个“单词 词频”)

词典的存储格式如下:

|   a 66          |
|   abandon 77    |
|   public 88     |
|    ......	      |
|_________________|

提示:因为我们需要统计圣经文件中单词以及该单词在文件中出现的次数,所以可以看去读圣经文件,然后将单词存到数据结构中,并记录单词的次数,如果单词第二次出现的时候,只需要修改单词的次数(也就是这里说的单词的频率),这样当统计完整个圣经文件后,数据都存在数据结构vector了。接着遍历vector数据结构就可以将单词以及单词次数(也就是频率)存储到另外一个文件。(当然如果不存到另外一个文件,就只能打印到终端了)

注意:在读圣经文件的时候,有可能字符串是不合法的,比如:abc123 abc?这样的字符串,处理方式两种:直接不统计这样的字符串或者将非法字母去掉即可。

思路:

  • 文件流对象关联到Bible.txt
  • 读取一行,
  • 用于构造字符串IO流对象,流入到到word中
  • 判断word的结构,并查看在字典中是否存在
  • 存在,对应词频+1
  • 不存在,将其添加到字典中
  • 持久化到另一个文件中
#include <iostream>
#include <ctime>
#include <string>
#include <vector>
#include <fstream>
#include <sstream>
#include <algorithm>

using std::cout;
using std::cerr;
using std::endl;
using std::string;
using std::vector;
using std::ifstream;
using std::ofstream;
using std::istringstream;
using std::sort;   //?

struct Record
{
    Record(const string& word, int frequency)
    :_word(word)
    ,_frequency(frequency)
    {
    }
    string _word;
    int _frequency;
};

bool operator < (const Record& lhs, const Record& rhs)
{
    return lhs._word < rhs._word;
}

class Dictionary
{
public:
    //构造时就设置字典的容量
    Dictionary(int capa)
    {
        _dict.reserve(capa);
    }
    
    //统计文件中的单词及其出现的频次
    void read(const string& filename)
    {
        ifstream ifs(filename);     //ifs.open()
        if(!ifs)
        {
            cerr << "ifs open file:" << filename << " failed!" << endl;
            return;
        }

        string line;
        while(getline(ifs,line))
        {
            istringstream iss(line);    //串IO
            string word;
            
            while(iss >> word)
            {
                string newWord = dealWord(word);

                insert(newWord);
            }
        }
        //排序
        sort(_dict.begin(),_dict.end());
        
        ifs.close();
    }
    
    //将单词与词频存储到文件中
    void store(const string& filename)
    {
        ofstream ofs(filename);
        if(!ofs)
        {
            cerr << "ofs open file:" << filename <<  " error!" << endl;
            return;
        }

        //基于范围的for循环
        for(Record& rec : _dict)
        {
            ofs << rec._word << " " << rec._frequency << endl;
        }

        ofs.close();
    }

    //对于不符合要求的单词进行处理
    string dealWord(const string& word)
    {
        string newWord;
        for(size_t idx = 0; idx != word.size(); ++idx)
        {
            if((word[idx] >= 'A' && word[idx] <= 'Z') 
               || (word[idx] >= 'a' && word[idx] <= 'z'))
            {
                newWord += word[idx];
            }
        }

        return newWord;
    }

    void insert(const string & word)
    {
        if(word == "")
        {
            return;
        }
        size_t idx = 0;
        for(; idx != _dict.size(); ++idx)
        {
            if(word == _dict[idx]._word) //单词出现过,故频次+1
            {
                ++_dict[idx]._frequency;
                break; //类似于剪枝
            }
        }

        //idx==dict.size() -->是新单词
        if(idx == _dict.size())
        {
            _dict.push_back(Record(word,1));
        }
    }
private:
    vector<Record> _dict;
};


int main(int argc, char** argv)
{
    Dictionary dict(13000);
    cout << "before reading..." << endl;
    time_t beg = time(NULL);
    dict.read(argv[1]);
    time_t end = time(NULL);

    cout << "time:" << end - beg <<  "s" << endl;
    cout << "after reading..." << endl;
    dict.store("dict.dat");
    return 0;
}

在这里插入图片描述

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值