【问题标题】:Problem with istream::tellg()?istream::tellg() 有问题吗?
【发布时间】:2010-09-10 03:52:27
【问题描述】:

我正在阅读 data.txt:

//////////////////////////////////////////////////

data.txt:

//////////////////////////////////////////////////

MissionImpossible3
3
TomCruise
MaggieQ
JeffChase

代码如下:

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

int main() {
 ifstream fin("data.txt");
 string FilmName, ActorName;
 getline(fin,FilmName,'\n');
 cout << FilmName << endl;
//    cout << fin.tellg() << endl; //if I add this line to
// get current reading position of data.txt, the program just
// can't work as if tellg() triggered some error. So I removed
// all tellg(). What's the reason for this and what shall I do
// if I want to get current reading position?
 int a;
 fin >> a;
 cout << a << endl;
// cout << fin.tellg() << endl;
 getline(fin,ActorName,'\n');
// cout << fin.tellg() << endl;
    for(int i=0;i<a;i++)
    {
     getline(fin,ActorName,'\n');
     cout << ActorName << endl;
//     cout << fin.tellg() << endl;
    }

 getchar();
}

意外的输出是:


碟中谍3
24
0
-1
-1

我正在使用 Dev-c++ 和 Windows XP。如果你们试一试并粘贴您的结果和环境,我将不胜感激。可能是我的系统或编译器有问题。

另一个版本的输入/输出:

数据.txt:

MissionImpossible3
3
TomCruise
MaggieQ
JeffChase

WarOfTheWorlds
2
TomCruise
DakotaFanning

SharkTale
3
JackBlack
RobertDeNiro
WillSmith

HideAndSeek
2
DakotaFanning
RobertDeNiro

TheAdventureOfPlutoNash
2
WillSmith
EddieMurphy

ShowTime
2
RobertDeNiro
EddieMurphy

输出:

MissionImpossible3
49
0
-1
-1

【问题讨论】:

    标签: c++


    【解决方案1】:

    它说它在第一行之后消耗了 24 个字符,然后没有得到一个数字。但是,MissionImpossible3 只有 18 个字符。

    我怀疑您的线路编码不兼容。您的文件以\n 结尾保存,而Windows iostreams 需要\r\n。输入中的3 被丢弃,因为系统需要\n。然后下一个输入是非数字的,它进入错误状态。

    尝试将输入数据复制粘贴到记事本中的新文件中。

    【讨论】:

    • 但是我之前没有看到这个编码问题发生,我使用记事本很好地查看了 txt 文件。我创建了一个新文件并复制粘贴。问题依然存在。
    • @L.Lawliet: ios::binary 阻止行编码转换。您是否尝试在十六进制编辑器中查看它,或者从该网页复制粘贴以消除冲突的可能性?
    • 是的,我试过了。只看第一条评论。我从这个页面粘贴了它。 “阻止行编码翻译”是什么意思?
    • @L.Lawliet:Unix 和 Windows 使用不同的字符序列来表示行尾。 C stdio 和 C++ iostream 使所有文件,无论您在什么平台上运行,都看起来像 Unix。这是一件好事,因为 Windows 使用两个字符 \r\n 来表示行尾。这听起来很熟悉吗?
    • 但是我用十六进制检查了我的文件,文件以 \r\n 结尾,或者每行末尾的 0xOD 0x0A 保存。
    【解决方案2】:

    尝试以二进制模式打开文件:

    ifstream fin("data.txt", ios::binary);
    

    【讨论】:

    • 是的,它有效!但正如我所想,是否读写二进制文件取决于您使用的函数(fread 或 >> , fwrite 或
    • @L.Lawliet: ios::binary 防止行尾编码转换。因此,虽然它可能适用于该文件,但它往往会生成 Unix 样式文件、曲解 Windows 文件以及损坏您已有的 Windows 文件。不要对文本使用二进制。
    • 那我该怎么办,我也不认为让文本文件像二进制文件一样工作是个好主意。
    • 我相信文本流中的 seek/tell 定义不明确,而二进制流定义明确(在很大程度上)。可能这可能是您面临此问题的原因(尽管我不确定)。参考:dinkumware.com/manuals/…
    • 这可能是因为从 Windows 文本文件中读取一个字节会消耗两个字节的文件偏移量。只要您不期望返回的字节数与文件位置匹配,就可以了。
    【解决方案3】:

    使用 std::ios::binary 创建 ifstream 修复了tellg,因此它在我的代码中也返回了文件中的正确位置(Win 7 64 位)。 正如 L.Lawliets 所问 - 为什么??!

    【讨论】:

      【解决方案4】:

      我在重新启用tellg 行的情况下编译并运行了您的代码,它似乎工作正常。我得到的输出是:

      碟中谍3
      20
      3
      21
      23
      汤姆克鲁斯
      34
      MaggieQ
      43
      杰夫蔡斯
      52

      当您尝试运行它时,您会得到什么确切结果? [是的,这实际上更像是一个评论而不是一个答案,但它不适合评论。]

      【讨论】:

      • 我得到了:
        MissionImpossible3
        24
        0
        -1
        -1
      • @L.Lawliet:很遗憾,您不能在评论中输入换行符。至于值,看起来它在读取时遇到了错误;你可能想看看errno(一种可能性)是否告诉你任何事情。
      • @L.Lawliet:这几乎让 Potatoswatter 的解释成为最好的初步猜测。我会对文本文件进行十六进制转储,看看它真正标记了行尾的内容——一些 Windows 代码处理 Unix 和/或 MacOS 文本文件,但有些不处理,以及你所看到的可能是由于记事本和标准库对行尾的处理存在差异。
      • 因为您的输入未正确编码为您正在使用的平台的文本文件。当以二进制文件打开时它“工作”的事实大多是偶然的。
      猜你喜欢
      • 2013-12-28
      • 2011-06-19
      • 1970-01-01
      • 2011-07-07
      • 2015-07-25
      • 2023-03-15
      • 2012-09-14
      • 2012-08-16
      • 2011-10-09
      相关资源
      最近更新 更多