字符串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;
}