Обратите внимание, что возвращаемое значение std::cin.peek()
на самом деле имеет тип std::basic_ios<char>::int_type
, который совпадает с std::char_traits<char>::int_type
, который является int
, а не char
.
Более того, значение, возвращаемое в этом int
, не обязательно является простым приведением от char
до int
, но является результатом вызова 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') ...
, где ch
- это int
, как указано выше, вы можете не получить правильные результаты. Вам нужно использовать std::char_traits<char>::to_char_type
на ch
или std::char_traits<char>::to_int_type
на символьной константе, чтобы получить согласованный результат. (Тем не менее, вы обычно в безопасности с членами основного набора символов.)