相比C语言,C++学习起来比较烦,但是功能更强一些。
尤其是C++的STL标准模板库,可以说是很好很强大。
还是继续介绍不使用太多面向对象class, 只使用STL标准模板库的C++案例。
笔者在前面的文章中举了一个采用C++ STL标准模板库的例子,
实现了类似awk的功能,就是从文件中抓出来某一列。
那么能不能再多走一步,把文本文件的每一行按照某一列内容的字母大小进行排序,然后再写出来呢?
这就可以采用STL sort的自定义排序规则来实现。
用自定义的排序规则,对任何类型 T 的数组排序:
sort( 数组名 +n1 ,数组名 + n2, 排序规则结构名() )
排序规则结构的定义方式:
struct 结构名
{
bool operator() (const T & a1,const T & a2) const {
// 若 a1 应该 在 a2 前面,则返回 true 。
// 否则返回 false 。
}
};
我们首先构建一个结构体
struct Tag_line {
string line; // 存储从文件中抓出来的每一行
string tag; // 存储这一行中用于排序的那一列的字符串
} ;
然后定义排序规则的结构
struct column_sort_rule { // 按某一列字符串的字母顺序从小到大排序
bool operator() (const Tag_line & line1, const Tag_line & line2) const {
if( line1.tag < line2.tag )
return true;
return false;
}
};
从文件中抓出来的每一行里,再抓出来用于比较的那一列的内容,构成Tag_line类型的数据。
然后把Tag之后的每一行数据放在一个vector中存储,
vector<Tag_line> vec_tag_line_all;
然后对这个vector进行自定义规则sort, 就是
sort(vec_tag_line_all.begin(), vec_tag_line_all.end(), column_sort_rule());
注意:struct结构体的定义要放在main函数的外边
其他的细节请查看源代码,我在重点的地方都加了注释
程序源代码:
#include <iostream>
#include <fstream>
#include <sstream>
#include <cstdio>
#include <string>
#include <vector>
#include <cstdlib>
#include <algorithm>
using namespace std;
struct Tag_line {
string line; // each line
string tag; // the column to compare
} ;
struct column_sort_rule { // sort by the string of required column
bool operator() (const Tag_line & line1, const Tag_line & line2) const {
if( line1.tag < line2.tag ) // the smaller string in front
return true;
return false;
}
};
int main (int argc, char* argv[])
{
//usage:
//cmd input_file_name column_num
if (argc < 3) {
cout << "Wrong input option number:" << argc -1 << endl;
cout << "Please inputi: file_name column_num" << endl;
return 0 ;
}
ifstream input_f(argv[1]) ; // input argv 1
if ( !input_f ) { // check if input file can be opened
cout << "Error: the input file can not be opened" <<endl ;
return 0 ;
}
int column_num = atoi(argv[2]) ; // input argv 2
if ( column_num <= 0 ) { // check if input column number is correct
cout << "Error: wrong column number" << endl;
return 0;
}
vector<Tag_line> vec_tag_line_all; // all line after tag
Tag_line tag_line_tmp; // each line after tag
string i_line ; // each line from file
//int line_num = 0 ;
int line_length ; // total column number of each line
vector<string> vec_line ; // store all element (sub string) of each line
stringstream ss; // string stream
string tmp_s; // each element and will be put into vec_line
while ( getline(input_f, i_line) ) { // get each line
tag_line_tmp.line = i_line ; // put each line in struct .line
ss.clear(); // init string stream
ss << i_line ; // put each line to string stream
vec_line.clear(); // each line need init vec_line
while (ss >> tmp_s) { // each element (sub string) in each line
vec_line.push_back(tmp_s); // put into vec_line
}
line_length = vec_line.size() ; // get total colume number of each line
if ( column_num > 0 && column_num <= line_length) {
tag_line_tmp.tag = vec_line[column_num - 1] ;
} else {
cout << "" << endl ; // if the line is empty or the required column > total column
tag_line_tmp.tag = "" ;
}
vec_tag_line_all.push_back(tag_line_tmp); // put tag line in vector
}
sort(vec_tag_line_all.begin(), vec_tag_line_all.end(), column_sort_rule()); // sort vector
int line_num = vec_tag_line_all.size() ;
for (int i = 0 ; i < line_num; ++i) { // output sorted lines
cout << vec_tag_line_all[i].line << endl ;
}
input_f.close() ;
return 0 ;
}
测试文件test.txt:
12 24 45 9 48 5
12 24 45 9 48 5
12 24 65 c 48 5
12 24 45 b 48 5
12 24 45 a 48 5
12 24 75 f 48 5
12 24 45 d 48 5
12 24 95 9 48 5
12 24 45 9 48 5
12 24 35 9 48 5
12 24 25 9 48 5
测试结果:
./a.out test.txt 3
12 24 25 9 48 5
12 24 35 9 48 5
12 24 45 9 48 5
12 24 45 9 48 5
12 24 45 b 48 5
12 24 45 a 48 5
12 24 45 d 48 5
12 24 45 9 48 5
12 24 65 c 48 5
12 24 75 f 48 5
12 24 95 9 48 5
./a.out test.txt 4
12 24 45 9 48 5
12 24 45 9 48 5
12 24 95 9 48 5
12 24 45 9 48 5
12 24 35 9 48 5
12 24 25 9 48 5
12 24 45 a 48 5
12 24 45 b 48 5
12 24 65 c 48 5
12 24 45 d 48 5
12 24 75 f 48 5
本文暂时没有评论,来添加一个吧(●'◡'●)