内容简介:使用C++ STL库统计一散文中单词出现次数和行号
在开发过程中经常会遇到文件处理的情形,例如统计一篇文章单词的数量、行数、出现频率最高的几个单词等等。这篇文章主要通过C++来解析一篇文章,实现每个单词(不区分大小写)出现的总次数和出现的行号的统计。
1 演示程序
文件处理能比较好地考验对开发语言基础技能的掌握能力,因为这需要去考虑数据的读取、数据的存储方式、数据的处理等等,可能不同的处理方法会得到不同的效率和结果。
下面的代码主要是使用C++的STL库解析一篇英文散文(网上看到不错就wget下来了),涉及的编程基本点如下:
1、STL容器中的map和vector容器; 2、ifstream库文件流的操作; 3、string的分割查找find、获取子串substr、去除非法字符等待; 4、c++中的基本知识点:构造函数(包括常量的初始化)、引用、对象的构造和析构等等。
文章内容如上图所示,下面直接呈上代码:
/** * @FileName stl_apply_readfile_1.cpp * @Describe A simple example for using c++ STL to calculate words and line numbers in an article. * @Author vfhky 2017-04-16 16:44 https://typecodes.com/cseries/stlcalcarticlewordlines1.html * @Compile g++ stl_apply_readfile_1.cpp -o stl_apply_readfile_1 */ #include <iostream> #include <map> #include <vector> #include <fstream> #include <algorithm> #include <string> #include <assert.h> #include <string.h> using namespace std; class CFileHandle { public: CFileHandle( const string &s_file_name ) : s_m_file_name(s_file_name) { i_m_line_number = 0; } //读取每行的数据,然后进行处理 void ReadFile( const string &s_file_name ) { ifstream inFile; //以二进制可读的方式打开文件,也可以使用: inFile.open( s_file_name.data() ); inFile.open( s_file_name.c_str(), ios::in | ios::binary ); //Checks if the file stream has an associated file. assert( inFile.is_open() ); //每一行的数据 string s_line_buf; //读取一行内容 getline( inFile, s_line_buf ) while( getline( inFile, s_line_buf, inFile.widen('\n') ) ) { ++i_m_line_number; //统一转换成大写:也可以使用 transform( s_line_buf.begin(), s_line_buf.end(), s_line_buf.begin(), ::toupper ); transform( s_line_buf.begin(), s_line_buf.end(), s_line_buf.begin(), (int (*)(int))toupper ); //开始数据处理 HandleLine( s_line_buf ); } //关闭文件流 inFile.close(); } //对每行的数据进行解析 void HandleLine( const string &s_line_buf ) { string s_word_buf; int i_start=0, i_last=s_line_buf.size(); //std::size_t i_split_pos; int i_split_pos = 0; while( i_start < i_last ) { i_split_pos = s_line_buf.find( ' ', i_start ); string s_word; //if( i_split_pos == std::string::npos ) if( i_split_pos == -1 ) { s_word = s_line_buf.substr( i_start, i_last ); HandleUnkind( s_word ); HandleWord( s_word ); break; } /** 避免空格,也可以使用下面这两行来去掉行首和行尾的空格 s_line_buf.erase( 0, s_line_buf.find_first_not_of(" ") ); s_line_buf.erase( s_line_buf.find_last_not_of(" ") + 1 ); */ else if( i_start != i_split_pos ) { s_word = s_line_buf.substr( i_start, i_split_pos-i_start ); HandleUnkind( s_word ); HandleWord( s_word ); i_start = i_split_pos + 1; } //对于行首的空格不进行处理 else { i_start = i_split_pos + 1; } } } //去除每个单词可能包含的非字符(除0~9和A~Z外的数据) void HandleUnkind( string &s_word_buf ) { assert( s_word_buf.size() ); //char c_word_buf[s_word_buf.size()+1]; 在vs中会报错:error C2131: 表达式的计算结果不是常数 char *c_word_buf = new char[s_word_buf.size()+1](); unsigned int j = 0; for( unsigned int i=0; i<s_word_buf.size(); ++i ) { if( ( s_word_buf[i] >= 0x30 && s_word_buf[i] <= 0x39 ) || ( s_word_buf[i] >= 0x41 && s_word_buf[i] <= 0x5A ) ) { c_word_buf[j++] = s_word_buf[i]; } } s_word_buf = c_word_buf; delete c_word_buf; } //对每个单词的处理 void HandleWord( const string &s_word_buf ) { map<string, vector<int> >::iterator mapit = mapobj.find( s_word_buf ); //如果该单词不存在 if( mapit == mapobj.end() ) { vector<int> vect; vect.push_back( i_m_line_number ); mapobj.insert( make_pair( s_word_buf, vect ) ); } else { mapit->second.push_back( i_m_line_number ); } } //遍历map对象 void Traverse() { map< string, vector<int> >::iterator mapit = mapobj.begin(); cout << "Words\t\t\t\tCounts\t\t\t\tLines" << endl; cout << "---------------------------------------------------------------------" << endl; for( ; mapit != mapobj.end(); ++mapit ) { cout << mapit->first << "\t\t\t\t" << mapit->second.size() << "\t\t\t\t"; for( vector<int>::iterator vectorit = mapit->second.begin(); vectorit != mapit->second.end(); ++vectorit ) { cout << *vectorit << " "; } cout << endl; } } //获取文件总行数 const unsigned int GetTotalLines() const { return i_m_line_number; } private: map<string, vector<int> > mapobj; unsigned int i_m_line_number; const string s_m_file_name; }; int main( int argc, char **argv ) { //文件所在路径 const string s_file_name = "STL_APPLY_READFILE_1"; CFileHandle *pCFileHandle = new CFileHandle( s_file_name ); //开始处理文件 pCFileHandle->ReadFile( s_file_name ); //打印总行数 cout << "[" << __FILE__ << ":" << __LINE__ << "] Total Lines=[" << pCFileHandle->GetTotalLines() << "]." << endl; //遍历结果 pCFileHandle->Traverse(); delete pCFileHandle; return 0; } |
2 使用g++编译器进行编译并执行
使用g++或者之前写的这个Makefile文件进行编译,结果如下图所示。
接着执行程序 stl_apply_readfile_1
,效果如下图所示(图片大小的限制只显示了一部分结果)。另外,上面C++程序中的数据处理函数 HandleUnkind
相对比较 粗略
:只简单过滤了非数字和字母的字符。这样会出现类似把 YOU'R
这样的数据处理成 YOUR
的情况,大家可以进行代码改进做更精细化的处理。
以上所述就是小编给大家介绍的《使用C++ STL库统计一散文中单词出现次数和行号》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 算法 – 给出一个单词,打印其索引,可以相应地增加单词
- Pocketsphinx – 添加单词和提高准确性
- Spark入门(三)--Spark经典的单词统计
- 每日一道算法题--leetcode 290--单词规则--python
- go基础库之将字符串分解为单词
- python将每个单词按空格分开并保存到文件中
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
C程序设计的抽象思维
Eric S.Roberts / 闪四清 / 机械工业出版社 / 2012-5 / 99.00元
Eric S. Roberts所著的《C程序设计的抽象思维》是一本关于C语言的经典图书。本书共计17章,分为4部分,第一部分概述计算机导论课程中涉及的基本编程概念;第二部分讨论递归算法,其中结合大量示例,有助于读者轻松理解和掌握晦涩的概念;第三部分不仅介绍了用非递归算法实现的抽象数据类型,还提供了一些工具,有助于读者理解数据抽象的概念;第四部分重点介绍采用递归算法实现的抽象数据类型。本书重点突出,......一起来看看 《C程序设计的抽象思维》 这本书的介绍吧!