【问题标题】:Parsing and split from a text file从文本文件中解析和拆分
【发布时间】:2016-05-01 22:31:10
【问题描述】:

我想从具有以下格式的文本文件中读取行:a r3, r2, r1 并且我想将其拆分为单独的部分,因此我有一个单独保存 a、r3、r2 和 r1 的变量,所以我需要删除空格和逗号。我不知道该怎么做。我四处搜索,但只能找到带有预定义字符串的示例(如this)。

我知道如何从文件中读取文本并将其放入 char 数组中,但理想情况下我希望将一行的每个元素放入一个单独的变量中。

比如:

#include <iostream>
#include <string>
#include <fstream>
using namespace std;

void main()
{
  string var1, var2, var3, var4;
  ifstream inFile("myfile.txt");

  if (inFile.is_open()){
      while (!inFile.eof()){
         inFile >> var1 >> var2 >> var3 >> var4;
      }
   }
}

但它处理空格、逗号和换行符的地方。有关如何执行此操作的任何建议?

【问题讨论】:

标签: c++ parsing fstream delimiter


【解决方案1】:

您可以使用std::getline(&lt;stream&gt;, &lt;string&gt;) 读取一行。

std::string line;
while(std::getline(inFile, line))
{
    // You successfully read a line.
}

std::getline() 实际上还有第三个参数,用于指定行尾。默认情况下,这是 '\n',但你指定你的在线结束(这将是 ',')。

std::stringstream   lineStream(line);    // convert your line into a stream.

if (std::getline(lineStream, a, ',') &&
    std::getline(lineStream, r1, ',') &&
    std::getline(lineStream, r2, ',') &&
    std::getline(lineStream, r3, ',')
   )
{
    // Read all the values successfully
}

如果您的行被空格分隔,请使用operator&gt;&gt; 而不是std::getline()

std::stringstream   lineStream(line);    // convert your line into a stream.

if (lineStream >> a >> r1 >> r2 >> r3)
{
    // Read all the values successfully
}

【讨论】:

  • 我不确定我是否遵循您对在线端“,”的意思。如果我的行是(空格)ra, ra, rc,则除了要读取的 \n 之外,没有行结束
  • std::getline() 的第三个参数是它将停止读取的字符。默认情况下,它在'\n' 处停止,但您可以使用任何其他字符(如',')。如果您的单词 a 用空格分隔,请使用 operator&gt;&gt;
  • 我的行被空格和逗号分隔,如问题所示:a(space)r1,(space)r2,(space)r3\n
【解决方案2】:

以下所有方法都适用于您的情况:

您可以对每个字符串使用这样的例程。检查最后一个字符是否为逗号。如果是,将其替换为“empty-ness”:

if (var1[var1.size() - 1] == ',')
    var1.replace(var1.size() - 1, var1.size() - 1, ""); // (From index, to index, with)

如果是逗号,可以pop_back()最后一个字符:

if (var2[var2.size() - 1] == ',')
    var2.pop_back();

另外,如果逗号是最后一个字符,您可以删除它:

if (var3[var3.size() - 1] == ',')
    var3.erase(var3.size() - 1, var3.size() - 1); // (From index, to index)

【讨论】:

  • 这会处理空格吗?
  • @noobgineer inFile &gt;&gt; var1 默认忽略空格
  • 如果我有不同数量的变量怎么办,假设一行只有 3 个元素或另一行有 5 个元素,我是否只需声明我需要的最大变量数而不用担心 var5什么都没读?
  • 您可以这样做并对其进行测试,否则您将需要一个 vector 的字符串,每次阅读 while(inFile&gt;&gt;temp) 时将元素推送到它,或者创建一个新节点的链表对于每个输入。如果您是初学者,也许这太多了,但您应该学习。
  • 如果我想从变量中删除第一个字符,比如说 var2,我需要做什么?因此,对于任何数值,输入将是 r1、r2 等,并且最多可以是 3 位数字,因此 r127。但我也想去掉“r”并保留数字。
【解决方案3】:

这不是最优雅的解决方案,但可以使用以下方法:

void parse_input(const std::string& _buffer, std::string& _s1, std::string& _s2,
 std::string& _s3, std::string& _s4);

int main(void) {   
    std::ifstream inFile("foo.txt");

    std::string var1, var2, var3, var4;
    std::string buffer = "";
    while(std::getline(inFile, buffer)) {
        parse_input(buffer, var1, var2, var3, var4);
    }
}

void parse_input(const std::string& _buffer, std::string& _s1, std::string& _s2,
 std::string& _s3, std::string& _s4) {
    size_t count = 0;
    // increment count until first space char
    while (buffer.at(count) != ' ') {
        ++count;
    }
    // set _s1 to substring of _buffer from start to first space
    _s1 = _buffer.substr(0, count);
    size_t prev_count = count;
    // repeat above for comma char instead...
    while (buffer.at(count) != ',') {
        ++count;
    }
    _s2 = _buffer.substr(prev_count, count);
    prev_count = count;
    while (buffer.at(count) != ',') {
        ++count;
    }
    _s3 = _buffer.substr(prev_count, count);
    prev_count = count;
    while (buffer.at(count) != ',') {
        ++count;
    }
    _s4 = _buffer.substr(prev_count, count);
}

请注意,这并不能防止parse_input_buffer 参数中出现索引越界错误 - 您需要在while 循环中添加额外的检查,例如&amp;&amp; count &lt; _buffer.size()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-05-15
    • 1970-01-01
    • 2020-08-13
    • 1970-01-01
    • 2018-08-31
    • 1970-01-01
    相关资源
    最近更新 更多