【问题标题】:Strange behaviour of tellg() function c++tellg() 函数 c++ 的奇怪行为
【发布时间】:2013-05-18 16:26:51
【问题描述】:

我遇到了 std::fstream 类中的 tellg() 函数的问题。通常它应该返回当前字符在输入流中的位置。但是,它对我来说很奇怪。下面是一些简短的示例代码:

#include <iostream>
#include <fstream>

using namespace std;

int main(void) {
char c;
ifstream czytaj;
czytaj.open("test_file.txt");

cout << czytaj.tellg() << endl;     //is 0 should be 0
czytaj.peek();                      //is 0 should be 0
cout << czytaj.tellg() << endl;     //is 2 should be 0    !!
czytaj.get(c);                      //is 3 should be 3
czytaj.get(c);                      //is 4 should be 4
cout << czytaj.tellg() << endl;     //is 6 should be 4    !!

int r; cin >> r;
return 0;
}

而 txt 文件如下所示:

abcdefghij
kturjbkfvd

编译后我得到如下输出:

0
2
6

tellg() 的第一次使用正常,它返回位置 0 作为文件的开头。不幸的是,每次下一次使用都会使位置增加+2。结果,我得到了从流中提取的字母“c”和“d”。 tellg() 和 peek() 都应该不改变位置,所以我应该得到字母 'a' 和 'b',而正确的结果应该是:

0
0
2

如果我在 txt 文件中使用编码 ANSI,就会发生这种情况。当我将其更改为 Unicode 时,它​​可以正常工作。此外,如果我使用 ANSI 和二进制模式 ios::binary,它也可以正常工作。奇怪的事实是,在我的另一台计算机上,即使使用 ANSI 而没有 ios::binary,它也能正常工作。为什么会这样?

编辑:忘记提及非常重要的事实。如果我从此示例代码中删除所有包含 tellg() 的行,则提取是正确的 - 我得到字母 'a' 和 'b'。

【问题讨论】:

  • 对我有用 g++4.7.2 libstdc++4.7.2。您使用的是什么编译器/库?
  • 它可能是一个 UTF-X 编码的文件,前面有一个 BOM 标记。使用十六进制编辑器转储文件并向我们展示内容。在 Linux 上尝试:od -t x1 -t c test_file.txt
  • 您的输入文件是否包含除abcdefgh 之外的任何其他符号?也许换行符或其他什么?难道是文件是Unicode(UTF-16)?
  • @Inspired - 是的,它还包含换行符,现在只是在没有换行符的情况下对其进行了测试,即使在 ANSI 和没有二进制模式下也可以正常工作。编辑了我的问题,现在的问题是,为什么换行符会破坏函数tellg()?第一个换行符在第 11 位,即使在第 2 位,它也开始工作错误
  • 文本流没有有意义的当前位置。它受 CRT 的影响必须向前看才能正确处理文本编码和字符替换。你离 Unix 和 ASCII 越远,它就越离谱。

标签: c++


【解决方案1】:

tellg() 告诉您文件中的下一个“获取”位置在哪里。由于例如 Windows 中使用 CR+LF ('\r','\n') 作为换行符的文件有两个字符作为换行符,其中 C++(和 C)标准要求换行符是 LF '\n' 作为单个字符,当您的程序读取一个 CR+LF 序列,C 运行时将其计为一个字符,但您从中获取下一个字符的文件位置向前两步。

【讨论】:

  • 你是对的,但我不明白的是,为什么第二次使用 tellg() 突然返回 2 而不是 0,而流根本没有移动,只是同时偷看。在这两种tellg() 使用之间没有提取任何字符。
  • 不确定。我会说这可能是一个错误。
  • 它更复杂,伙计。因为像 peek() + tellg() 这样的每个组合都会“增加” 2 的位置,这真的很荒谬。
  • 我仍然认为这不是它的预期工作方式——也就是说,它是一个错误。
【解决方案2】:

有同样的问题。尝试读取文件流二进制文件:

    czytaj.open("test_file.txt",ios::binary);

对我有帮助

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-09
    • 2018-06-02
    相关资源
    最近更新 更多