从流中以新方式排序数据
Posted
技术标签:
【中文标题】从流中以新方式排序数据【英文标题】:Ordering data in new way from stream 【发布时间】:2013-09-26 23:26:47 【问题描述】:如果我在文本文件中有如下所示的行:
1 4:48:08 Orvar Steingrimsson 1979 30 - 39 ara IS200
2 4:52:25 Gudni Pall Palsson 1987 18 - 29 ara IS870
我怎样才能将这些数据输出到一个新的文本文件中,但只列出三件事:年份 - 名称 - 时间......这样这两行看起来像这样:
1979 Orvar Steingrimsson 4:48:08
1987 Gudni Pall Palsson 4:52:25
我的猜测是这样的:
ifstream in("inputfile.txt");
ofstream out("outputfile.txt");
int score, year;
string name, time, group, team;
while (getline(in,str));
in >> score >> time >> name >> year >> group >> team;
//and then do something like this
out << year << name << time << '\n';
但是我有一种感觉,我无法在整个文本文件和所有 200 行中循环。任何提示表示赞赏!
【问题讨论】:
我会为此使用scanf
,但我偏向于 C 的文件操作功能。在“正确的”C++ 中,您可能会使用>>
。无论如何,对于您的确切问题,您使用了错误的substr
。你想要str.substr(54,4)
。您使用的是 C 风格,不适用于 std::string
s。
第二个问题:C/C++中'
是字符,"
是字符串。
【参考方案1】:
根据上面的问题,我认为您需要使用分隔符''或'\t'分割文件。 在 c++ 中,您可以使用 boost 库。 增强:
#include <iostream>
#include <string>
#include <vector>
#include <boost/algorithm/string/classification.hpp>
#include <boost/algorithm/string/split.hpp>
using namespace std;
int main( int argc, char** argv )
string s = "Hello, the beautiful world!";
vector<string> rs; // store the fields in your text.
boost::split( rs, s, boost::is_any_of( " ,!" ), boost::token_compress_on );
for( vector<string>::iterator it = rs.begin(); it != rs.end(); ++ it )
cout << *it << endl;
return 0;
或使用 strtok() 函数
#include <stdlib.h>
#include <iostream>
#include <string.h>
using namespace std;
int main( int argc, char** argv )
char str[] = "Hello, the beautiful world!";
char spliter[] = " ,!";
char * pch;
pch = strtok( str, spliter );
while( pch != NULL )
cout << pch << endl;
pch = strtok( NULL, spliter );
return 0;
您也可以使用find
或strchr
函数找到分隔符,然后将其拆分。您可以在第一个示例中的 vector<string> rs
或第二个示例中的 pch
中收到 year
。
【讨论】:
【参考方案2】:提取子字符串后,您可以调用strtol()
(或std::stoi()
,如果您有C++.11)将字符串转换为整数。一旦有了年份和数据行,就可以将它们存储到某个表中,可能是std::multimap<>
。
没有 C++.11:
void process (std::istream &in, std::ostream &out)
typedef std::multimap<int, std::string> table_type;
table_type data_by_year;
std::string str;
while (std::getline(in,str))
int year = strtol(str.substr(54, 4).c_str(), 0, 10);
data_by_year.insert(std::make_pair(year, str));
for (table_type::iterator i = data_by_year.begin();
i != data_by_year.end();
++i)
out << i->second << "\n";
在 C++.11 中:
void process (std::istream &in, std::ostream &out)
std::multimap<int, std::string> data_by_year;
std::string str;
while (std::getline(in,str))
int year = std::stoi(str.substr(54, 4));
data_by_year.insert(std::make_pair(year, str));
for (auto v : data_by_year)
out << v.second << "\n";
【讨论】:
注意:std::stoi
需要 C++11 支持
@LihO: 嗯...那么我也可以使用auto
和新的for
语法。但是问题没有标记 C++11... 好的,改成strtol()
,谢谢。
有人能解释一下我是如何使用这条线的吗? std::multimap#include <map>
。此外,我使用insert()
而不是[]
更新了答案,因为multimap<>
不支持[]
运算符(map<>
确实支持[]
,但切换到multimap<>
以便多个条目与相同的year
可以存储在表中)。以上是关于从流中以新方式排序数据的主要内容,如果未能解决你的问题,请参考以下文章