1

标题非常不言自明。

char c = std::cin.peek(); // sets c equal to character in stream

我刚刚意识到也许本机类型 char 不能容纳 EOF。

谢谢,核磁共振

4

2 回答 2

9

简短的回答:不。使用int而不是char

稍微长一点的答案:不。如果您可以从函数中获取字符或值EOF,例如 C 的getchar和 C++ 的peek,显然普通的char变量不足以同时保存所有有效字符EOF

更长的答案:这取决于,但它永远不会像你希望的那样工作。

C 和 C++ 具有三种字符类型(“宽”类型除外):charsigned charunsigned char。普通字符可以是有符号或无符号的,这在编译器之间会有所不同。

EOF是一个负整数,通常为 -1,因此很明显,您不能将它存储在无符号字符或无符号普通字符中。假设您的系统使用 8 位字符(几乎所有字符都使用),EOF将转换为(十进制)255,您的程序将无法运行。

但是,如果您的char类型是有符号的,或者如果您使用有符号的 char类型,那么是的,您可以在其中存储 -1 ,所以是的,它可以保存EOF。但是,当您从文件中读取代码为 255 的字符时会发生什么?它将被解释为-1,即EOF(假设您的实现使用-1)。因此,您的代码不仅会在文件末尾停止读取,而且在找到 255 个字符时也会停止读取。

于 2009-12-05T08:42:14.090 回答
4

请注意,的返回值std::cin.peek()实际上是类型std::basic_ios<char>::int_type,与 相同std::char_traits<char>::int_type,它是 anint而不是 a char

更重要的是,返回的值int不一定是从charto的简单转换,int而是调用std::char_traits<char>::to_int_type流中的下一个字符或std::char_traits<char>::eof()(定义为EOF)如果没有字符的结果。

fgetc通常,这一切的实现方式与将字符转换为 anunsigned char然后转换为 an作为其返回值完全相同,int这样您就可以区分所有有效的字符值和EOF.

如果将 的返回值存储std::cin.peek()在 achar中,那么读取具有正值的字符(例如 iso-8859-1 编码文件中的 ÿ)将比较等于EOF.

迂腐的做法是。

typedef std::istream::traits_type traits_type;

traits_type::int_type ch;
traits_type::char_type c;

while (!traits_type::eq_int_type((ch = std::cin.peek()), traits_type::eof()))
{
    c = traits_type::to_char_type(ch);
    // ...
}

这可能更常见:

int ch;
char c;

while ((ch = std::cin.peek()) != EOF)
{
    c = std::iostream::traits_type::to_char_type(ch);
    // ...
}

请注意,正确转换字符值很重要。如果您执行这样的比较:if (ch == '\xff') ...where chis anint如上所述,您可能不会得到正确的结果。您需要使用std::char_traits<char>::to_char_typeonchstd::char_traits<char>::to_int_typeon 字符常量来获得一致的结果。(不过,对于基本字符集的成员,您通常是安全的。)

于 2009-12-05T11:35:51.063 回答