首页 > 解决方案 > getline 在读取文本文件时有一个奇怪的行为

问题描述

我写的一段代码有一个奇怪的行为。有代码:

#include "pugixml.hpp"

#include <cassert>
#include <string>
#include <iostream>
#include <fstream>
#include <optional>

namespace xml = pugi;

void read_ascii_file(const std::string& filename)
{
  std::ifstream file(filename, std::ios::in);

  if(!file) {
    std::cerr << "[ERREUR - read_ascii_file] Impossible d'ouvrir le fichier " << filename << "! Vérifier son existence." << std::endl;
    abort();
  }

  std::string tmp;
  while(std::getline(file, tmp))
    {
      //Do nothing here
    }
  file.close();
}

class Foo{

public:
  Foo(const xml::xml_document& doc)
  {
    _base_node = doc.child("test");

    std::string id = _base_node.child("data1").child_value("id");
    std::cout << "id from constructor " << id <<std::endl;
  }

  void bar()
  {
    std::string id = _base_node.child("data2").child_value("id");
    std::cout << "id from bar " << id <<std::endl;
  }

private:
  xml::xml_node _base_node;

};

std::optional<Foo> make(const std::string& filename)
{
  xml::xml_document doc;
  xml::xml_parse_result result = doc.load_file(filename.c_str());

  if(result.status != xml::xml_parse_status::status_ok)
    return {};
  else
    return Foo(doc);
}

int main()
{
  std::string filename = "xml_test.dat";
  std::optional<Foo> f = make(filename);

  if(!f)
    std::abort();
  else
    {
      std::string filename = "lbl-maj_for_test.dat";
      //read_ascii_file(filename);
      f->bar();
    }

  return 0;
}

文件 xml_test.dat 是:

<test>
  <data1>
    <id>1</id>
  </data1>
  <data2>
    <id>2</id>
  </data2>
</test>

此代码给出输出:

来自构造函数 1 的 id

来自酒吧 2 的 ID

但是当我取消注释该行时//read_ascii_file(filename);,输出变为:

来自构造函数 1 的 id

分割错误

gdb 给我错误:

#0  0x00007ffff7f84b20 in pugi::xml_node::child(char const*) const () from /lib/x86_64-linux-gnu/libpugixml.so.1
#1  0x00005555555578ba in Foo::bar (this=0x7fffffffdf40) at /home/guillaume/dev/C++/projects/moteur_de_calcul/test/test_xml_node.cpp:42
#2  0x00005555555575ec in main () at /home/guillaume/dev/C++/projects/moteur_de_calcul/test/test_xml_node.cpp:73

文件 lbl-maj_for_test.dat 是一个 132 行的 txt 文件,似乎没有一个长度超过 50 个字符。我认为是一个编码问题,但我不知道如何解决这个问题......

标签: c++encodinggetline

解决方案


这与getline. 当您的程序具有未定义的行为时取消注释/注释事物可能会导致诸如此类的红鲱鱼。

问题是你的节点都是悬空的,因为你不坚持doc。到你打电话的时候bar()_base_node已经死了/无效/孤立了。

文档中

xml_document 是整个文档结构的所有者;销毁文档会破坏整棵树。

假设图书馆支持它,我 doc进入Foo并按值将其存储为成员。


推荐阅读