【问题标题】:how to extract out data from a txt file which is seperated by |如何从由 | 分隔的 txt 文件中提取数据
【发布时间】:2013-11-30 08:43:41
【问题描述】:

我正在寻找一种从 txt 文件中提取数据的方法,该文件中的数据按行分隔,每列数据由 | 分隔

这是一个例子

12|john bravo|123 kings street
15|marry jane|321 kings street

以前我是用这样的空格分隔的

12 john kingstreet
15 marry kingstreet

但是当我在名称中添加姓氏/添加带有空格的地址时会出现问题,例如:john bravo 所以我决定使用 |

分隔列数据

这就是我提取数据的方式

struct PERSON{
   int id;
   string name;
   string address;
};

//extract
int main(){
   PERSON data[2];

   ifstream uFile("people.txt");
   int i = 0;
   while(uFile >> data[i].id >> data[i].name >> data[i].address){
    i++;
   }
   return 0;
}

那么,如果列由 | 分隔,我该如何提取? ??

【问题讨论】:

  • 我也用 | 保存通过程序,txt 文件帮助我保存数据。

标签: c++


【解决方案1】:

使用 getline() 两次: 首先,让每一行使用默认分隔符(新行);其次,对于第一步的每个段,使用“|”作为分隔符。 "stringstream" 类可用于传输数据。


@edward 下面的代码是根据你的修改而来的,我觉得@P0W58 的回答更好。

#include <iostream>
#include <fstream>
#include <sstream>

using namespace std;

const int length = 2;

struct PERSON
{
    int id;
    string name;
    string address;
};

//extract
int main()
{
    PERSON data[length];

    ifstream fin("people.txt");

    int i = 0;
    while(true)
    {
        string segment;
        if (!getline(fin, segment))
            break;

        stringstream transporter;
        transporter << segment;

        string idString;
        getline(transporter, idString, '|');
        getline(transporter, data[i].name, '|');
        getline(transporter, data[i].address, '|');

        stringstream idStream;
        idStream << idString;

        idStream >> data[i].id;

        i++;
    }

    for (i=0; i<length; i++)
        cout << data[i].id << '+' << data[i].name << '+'\
            << data[i].address << endl;

    return 0;
}

【讨论】:

  • 这个或类似的东西是正确的答案,与问题中发布的方法相比,它根本没有将换行符视为特殊,如果输入包含会导致一整类错误“字段数错误。”
  • istream& getline ( istream &is , 字符串 &str , char delim );如果使用默认分隔符,则忽略第三个参数。这可能会有所帮助:stackoverflow.com/questions/14777775/…
  • 我仍然没有完全了解 getline 的全貌,因为它与我通常使用的方法不同。你能给我一个代码示例吗?感谢您的帮助。
【解决方案2】:

要读入struct,我会重载&lt;&lt;,然后按照答案之一中的说明解析文本。

类似这样的:

#include<sstream>
//...

struct PERSON{
   int id;
   std::string name;
   std::string address;

   friend std::istream& operator >>(std::istream& is, PERSON& p)
   {
     std::string s;
     std::getline(is, s); //Read Line, use '\r' if your file is saved on linux
     std::stringstream ss(s);
     std::getline(ss, s, '|');  //id
     p.id = std::atoi(s.c_str()); 
     std::getline(ss, p.name, '|'); // name
     std::getline(ss, p.address, '|'); //address

    return is ;
   }
};

然后你可能会这样做,

std::ifstream fin("input.txt");
PERSON p1;
while (fin >> p1)
   //std::cout << p1.id << p1.name << std::endl ; 

你也可以重载&lt;&lt;

【讨论】:

  • 当我向结构 PERSON 添加一个新元素时,例如,我添加了 float cash 并且对于 getline,我添加了 std::getline(ss, p.cash, '|'); ,我得到一个错误:没有重载函数 std 的实例: :getline
  • @Ah,对于float,使用std::stof,如图所示std::stoi 用于int。还要先查看错误消息并研究参考/文档。 std::getline 仅适用于 std::basic_string
  • 所以如果我添加 float 作为最后一个元素,我应该在获取地址后添加:std::getline(ss, s, '|'); p.cash = stof(s.c_str());
【解决方案3】:

使用 boost::tokenizer 或 find first of like :

// code example
string s = "12|john bravo|123 kings street";
string delimiters = "|";
size_t current;
size_t next = -1;
do
{
  current = next + 1;
  next = s.find_first_of( delimiters, current );
  cout << s.substr( current, next - current ) << endl;
}
while (next != string::npos);

【讨论】:

  • next != string::npos 是什么意思?
  • 这意味着 find_first_of 返回的位置不等于不匹配
猜你喜欢
  • 2021-09-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-05
  • 1970-01-01
  • 2013-05-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多