【问题标题】:getting weird symbol from file input从文件输入中获取奇怪的符号
【发布时间】:2014-02-12 08:39:46
【问题描述】:

我正在将一个文件 (input.txt) 输入到我的程序中 input.txt 包含以下文本:

Trojans, 0.80, 0.60
Bruins, 0.20, 0.30
Bears, 0.60, 0.50
Trees, 0.50, 0.40
Ducks, 0.40, 0.80
Beavers, 0.50, 0.10
Huskies, 0.80, 0.40
Cougars, 0.10, 0.90

但是终端输出的是

Trojans, 0.80, 0.60
Bruins, 0.20, 0.30
Bears, 0.60, 0.50
Trees, 0.50, 0.40
Ducks, 0.40, 0.80
Beavers, 0.50, 0.10
Huskies, 0.80, 0.40
Cougars, 0.10, 0.90�

我不确定奇怪的问号是从哪里来的。

我的代码目前是

知道为什么会这样吗?

【问题讨论】:

  • ifstream_obj.get() 一次获取一个字符,您将其存储在字符数组中。这个数组在 C++ 中看起来就像一个旧的 c 样式数组,因此应该以空值结尾。此外,您的输入缓冲区(团队)不够大;您正在运行超出数组的末尾,并调用未定义的行为。
  • 哦,这很有意义,所以如果我只包含一个 if 语句,告诉程序在到达 eof 时中断?
  • 这还不够。您正在创建一个 c 字符串,但不是以空值终止它。您在该字符串中读取的字符也比分配用于接收它们的数组的大小更多。
  • 以后当我从这个数组中获取数据时,这是否会成为一个问题,即使我告诉程序一旦达到 eof 就停止读取值。

标签: c++ arrays file io


【解决方案1】:

eof() 告诉您是否已尝试读取文件末尾,因此您的循环不正确。应该是:

for (;;)
{
    temp = myfile.get();
    if (myfile.eof()) break;
    team[il] = temp;
    il++;
}

【讨论】:

    【解决方案2】:

    最后一个字符是一些垃圾值。因为 il 即使在 EOF 时也会在 while 循环中递增。下面的更改应该可以解决问题。检查条件更改为 nee

      for (int nee = 0; nee < (il - 1); nee++) //check to see if what i outputted is correct
        {
            cout << team[nee];
        }
    

    检查下面修改后的 readfile 例程:

    void readfile()
        {   
            char temp;
            ifstream myfile ("input.txt");
            int il = 0;
            while (!myfile.eof())
            {   
                temp = myfile.get();
                team[il] = temp;
                il++;
            }   
            for (int nee = 0; nee < il - 1; nee++) //check to see if what i outputted is correct
            {   
                cout << team[nee];
            }   
            cout << endl ;
        }   
    

    【讨论】:

    • 谢谢你,但你知道我怎样才能摆脱存储到我的数组中的垃圾值吗?
    • 您可以将数组设置为具有 '\0' 字符。但是程序应该只打印它读取的字符
    • 是的,这就是它在这个随机问号中仍在阅读的大问题
    【解决方案3】:

    myfile.eof() 将在您的读取循环中第一次读取失败后返回 true

    temp = myfile.get();
    team[il] = temp;
    il++;
    

    您使用myfile.get() 读取了一个字节,这将在文件末尾失败,但您没有检查您是否成功地从文件中读取了一个字节。更正此问题的最简单方法是在之后 myfile.get() 但在您对结果执行任何操作之前插入一个检查。

    temp = myfile.get();
    if(!myfile) // use implicit conversion from stream to bool to test for success
        break;
    team[il] = temp;
    il++;
    

    虽然这不是一个特别优雅的循环结构,但我个人会使用这样的东西:

    for(char temp=myfile.get(); 
        myfile && il < sizeof(team)/sizeof(team[0]); 
        temp=myfile.get(), ++il)
    {
        team[il] = temp;
    }
    

    这会起作用,因为循环条件 (myfile) 将在每次 get 后检查,但在循环体 (team[il] = temp;) 执行之前,因此您不会有向 @ 写入无效字符的危险987654329@.

    请注意,如果 myfile 的长度超过 80 个字节,您的代码可能包含缓冲区溢出,我在上面的循环中添加了一个条件,以确保例程将在文件末尾或 80 个字节处停止读取 - 以两者为准首先发生。

    【讨论】:

    • 他的脚本也无法用 \0 终止 c 字符串“团队”,因此 cout 将继续打印,直到遇到一个。
    • 我同意,它应该是空终止的 - 但他实际上是一个接一个地输出字符,所以如果出于某种奇怪的原因,他可以不用空终止!
    猜你喜欢
    • 2018-03-05
    • 1970-01-01
    • 1970-01-01
    • 2020-07-20
    • 1970-01-01
    • 2017-07-18
    • 2014-10-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多