从流中以新方式排序数据

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++ 中,您可能会使用&gt;&gt;。无论如何,对于您的确切问题,您使用了错误的substr。你想要str.substr(54,4)。您使用的是 C 风格,不适用于 std::strings。 第二个问题: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;

您也可以使用findstrchr 函数找到分隔符,然后将其拆分。您可以在第一个示例中的 vector&lt;string&gt; rs 或第二个示例中的 pch 中收到 year

【讨论】:

【参考方案2】:

提取子字符串后,您可以调用strtol()(或std::stoi(),如果您有C++.11)将字符串转换为整数。一旦有了年份和数据行,就可以将它们存储到某个表中,可能是std::multimap&lt;&gt;

没有 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 data_by_year; 当我尝试这种方法时,我不断收到“使用未声明的标识符 data_by_year”。所以我明白这意味着我需要识别它,但作为什么?整数、字符串、字符?我不知道,一切都会导致错误 您需要#include &lt;map&gt;。此外,我使用insert() 而不是[] 更新了答案,因为multimap&lt;&gt; 不支持[] 运算符(map&lt;&gt; 确实支持[],但切换到multimap&lt;&gt; 以便多个条目与相同的year 可以存储在表中)。

以上是关于从流中以新方式排序数据的主要内容,如果未能解决你的问题,请参考以下文章

从流中以 Xamarin 表单呈现 PDF

Jackson ObjectWriter 仅从流中写入第一个条目

连续从流中读取?

从流中读取失败 - MySqlException

iOS - 如何从流中读取音频并播放音频

从流中替换采样