`fin.get(ch);` 读取最后一个字符两次而 `ch=fin.get();` 不在 `while(!fin.eof())` 循环中为什么?

`fin.get(ch);` reads last character twice while `ch=fin.get();` not inside `while(!fin.eof())` loop why?

vicky.txt 文件

I was born in Hupari.

代码-1

#include <iostream>
#include<fstream>
int main()
{
    char ch;
    std::ifstream fin;
    fin.open("vicky.txt", std::ios::in);

    while (!fin.eof())
    {
        fin.get(ch);
        std::cout<<ch;
    }
    fin.close();
    return 0;
}

输出

I was born in Hupari..

代码-2

#include <iostream>
#include<fstream>
int main()
{
    char ch;
    std::ifstream fin;
    fin.open("vicky.txt", std::ios::in);

    while (!fin.eof())
    {
        ch=fin.get();
        std::cout<<ch;
    }
    fin.close();
    return 0;
}

输出

I was born in Hupari. 

为什么在使用 fin.get(ch) 时它会读取最后一个字符两次。另一方面 ch=fin.get() 正确读取意味着只读取最后一个字符一次。

顺便说一下return类型的fin.get(ch)fin.get() 的 return 类型是 char 对吗?

两个版本都是错误的。有关如何正确编码阅读循环的更多详细信息,请参阅 Why is iostream::eof inside a loop condition (i.e. while (!stream.eof())) considered wrong?


现在,解释一下发生了什么。第一个版本使用 get() 的第二个重载。如果读取失败(例如,到达文件末尾)并设置标志,此方法将保持其参数不变。因此,您再次打印最后读取的字符。

第二个版本使用 get() 的第一个重载。因为这个版本必须 return 一个字符并且不能像其他版本一样保持不变,它 return 一个 int 能够 return 特殊值 EOF (不能代表任何有效字符)。 EOF 通常等于 -1(如 int)。然后,您将其隐式转换为 char,这将使其等于 255(或保持为 -1,但为 8 位)。然后你打印它。根据终端使用的代码页,它可能是 ÿ 字符,不间断 space 或其他。可能,您打印了那个不间断的 space 字符,或者其他一些不可见或不可打印的字符。