【问题标题】:How to read and process text from a file in this specific way?如何以这种特定方式读取和处理文件中的文本?
【发布时间】:2016-01-06 19:13:00
【问题描述】:

我有一个关于处理我正在阅读的文件中的某些名称或数字的代码的问题。所以文件中的文本如下所示:

Imp;1;down;67
Comp;3;up;4
Imp;42;right;87

如您所见,有 3 行单词和数字由字符 ';' 分隔.我想一次读取每一行,并将一行中的整个字符串拆分为 words 和 numbers ,然后处理信息(将用于使用数据创建一个新对象)。然后继续下一行,以此类推,直到 EOF。

所以,我想读取第一行文本,将其拆分为由该行中的单词和数字组成的字符串数组,然后从中创建一个类的对象。例如,对于第一行,创建一个 Imp 类的对象,如 Imp objImp(Imp, 1, down, 67)

在 Java 中,我使用 information = line.split(";")'(其中 line 是一行文本)做了同样的事情,然后使用 information[0]information[1] 访问字符串数组的成员并创建对象。我正在尝试在这里做同样的事情

【问题讨论】:

  • 看起来您的代码读取了一行,打印出来,然后重复,直到没有内容可读取。这符合你对我认为的事情的描述......所以有什么问题? 它不会在第一行之后停止,所以我可以插入我需要的代码——嗯,嗯?您根本没有很好地描述您的问题,并且您似乎没有添加任何代码来处理该行(output)而不是打印它。
  • 您正在使用 getline 中的常量 256 引发崩溃。你应该在这里使用sizeof(output)
  • @mah 我没有解释我想要做什么,让我再试一次。因此,我想读取第一行文本,将其拆分为由该行中的单词和数字组成的字符串数组,然后从中创建一个类的对象。例如,对于第一行,创建一个 Imp 类的对象,如 Imp objImp(Imp, 1, down, 67)。在 Java 中,我使用 'information = line.split(";")' (其中 line 是一行文本)做了同样的事情,然后使用 'information[0]', 'information[1]' 来访问字符串数组并创建对象。我正在尝试在这里做同样的事情
  • @Logicrat - 这只是为了测试,但感谢您的提醒

标签: c++ file input getline


【解决方案1】:

不要使用char 数组作为缓冲区,也不要使用don't use std::istream::eof。说了这么多,我们继续解决问题。

std::getlinestd::istream::getline 类似,只是它使用std::string 而不是char 数组。

在两者中,参数delim 表示分隔字符,但在某种程度上,它是字符,当遇到该字符时,std::getline 会停止读取(不保存并丢弃它)。这并不意味着分隔符会神奇地为您在整行的每个; 之间拆分输入。

因此,您必须这样做:

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

...

std::ifstream myFile("D:\\stuff.txt"); // one statement

if (myFile.is_open()) {
    std::string line;

    while (std::getline(myFile, line)) { // line by line reading
        std::istringstream line_stream(line);
        std::string output;

        while (std::getline(line_stream, output, ';')) // line parsing
            std::cout << output << std::endl;
    }
}

我们从line 构造一个std::istringstream,所以我们可以用std::getline 再次解析它。

【讨论】:

  • Live Demo 你的代码在行动中。
  • 谢谢,代码运行良好,但我第一次提出的问题不正确。同时我编辑了最初的问题,如果你有任何想法,请参阅最后一部分关于我在现在编辑的初始问题中想要实现的目标
  • @Alex 不是打印output,而是将其推送到std::vector&lt;std::string&gt; 中,并在外部循环的每次迭代中重新创建,然后使用these functions 检查其大小,如果需要转换std::string 为整数。
  • @Alex 它可以以一种截然不同的方式完成,将operator&gt;&gt; 重载为Imp
  • @LogicStuff 谢谢。我应该能够完成矢量部分,找到它的文档 (cplusplus.com/reference/vector/vector),所以我应该很好。至于重载,我还没有在 C++ 中尝试过,需要进一步调查。已将您的答案标记为正确,非常感谢您的帮助。
【解决方案2】:

另一种(略有不同)的选择:

/*
 * Sample output:
 *   line:Imp;1;down;67
 *     "Imp", "1", "down", "67"
 *   line:Comp;3;up;4
 *     "Comp", "3", "up", "4"
 *   line:Imp;42;right;87
 *     "Imp", "42", "right", "87"
 *   line:Imp;42;right;87
 *     "Imp", "42", "right", "87"
 */
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>

using namespace std;

void split(const std::string &s, char delim, std::vector<string> &fields)
{
    fields.clear();
    std::stringstream ss(s);
    std::string item;
    while (std::getline(ss, item, delim)) {
        fields.push_back(item);
    }
}

void print (std::vector<string> &fields)
{
  cout << "  ";
  for (size_t i = 0; i < fields.size() - 1; i++)
    cout << "\"" << fields[i] << "\", ";
  cout << "\"" << fields[fields.size()-1] << "\"" << endl;
}

int main ()
{
  std::ifstream fp("tmp.txt");
  std::string line;
  while (!fp.eof()) {
    fp >> line;
    cout << "line:" << line << endl;
    std::vector<std::string> fields;
    split(line, ';', fields);
    print(fields);
  }
  fp.close();
  return 0;
}

【讨论】:

    猜你喜欢
    • 2014-09-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-29
    • 1970-01-01
    • 2013-10-30
    相关资源
    最近更新 更多