C ++可以使用本机类型char保存文件结尾字符吗?

时间:2009-12-05 07:54:28

标签: c++ char eof

标题非常自我解释。

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

我刚才意识到也许原生类型的char不能保持EOF。

感谢, NMR

2 个答案:

答案 0 :(得分:8)

简短回答:否。使用 int 代替 char

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

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

C和C ++有三种字符类型(“宽”类型除外): char signed char unsigned char 。普通的 char 可以是签名的或未签名的,这在编译器之间会有所不同。

EOF 是一个负整数,通常为-1,因此显然您无法将其存储在 unsigned char 或纯 char < / strong>那是未签名的。假设您的系统使用8位字符(几乎全部都是这样), EOF 将转换为(十进制)255,并且您的程序将无效。

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

答案 1 :(得分:4)

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

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

通常情况下,这一切的实现方式与fgetc将字符转换为unsigned char然后再转换为int的方式完全相同,以便您可以区分所有有效字符来自EOF的字符值。

如果将std::cin.peek()的返回值存储在char中,那么可以读取具有正值的字符(比如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') ...其中chint,如上所述,您可能无法获得正确的结果。您需要在std::char_traits<char>::to_char_type上使用ch或在字符常量上使用std::char_traits<char>::to_int_type来获得一致的结果。 (不过,对于基本字符集的成员来说,你通常是安全的。)