内容简介:使用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将每个单词按空格分开并保存到文件中
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Python神经网络编程
[英]塔里克·拉希德(Tariq Rashid) / 林赐 / 人民邮电出版社 / 2018-4 / 69.00元
神经网络是一种模拟人脑的神经网络,以期能够实现类人工智能的机器学习 技术。 本书揭示神经网络背后的概念,并介绍如何通过Python实现神经网络。全书 分为3章和两个附录。第1章介绍了神经网络中所用到的数学思想。第2章介绍使 用Python实现神经网络,识别手写数字,并测试神经网络的性能。第3章带领读 者进一步了解简单的神经网络,观察已受训练的神经网络内部,尝试进一步改......一起来看看 《Python神经网络编程》 这本书的介绍吧!