【发布时间】:2021-05-18 21:54:47
【问题描述】:
How to use correctly the return value from std::cin.get() and std::cin.peek()?的问题让我想知道是否可以保证
std::char_traits<char>::to_int_type(c) == static_cast<int>(c)
对于所有有效的char 值c。
这出现在很多地方。例如istream::peek 调用streambuf::sgetc,它使用to_int_type 将char 值转换为int_type。现在,std::cin.peek() == '\n'真的意味着下一个字符是\n吗?
这是我的分析。快来收集[char.traits.require]和[char.traits.specializations.char]的碎片吧:
-
对于每个
int值e,to_char_type(e)返回-
c,如果eq_int_type(e, to_int_type(c))为一些c; -
其他一些未指定的值。
-
-
对于每对
int值e和f,eq_int_type(e, f)返回-
eq(c, d),如果e == to_int_type(c)和f == to_int_type(d)用于某些c和d; -
true, 如果e == eof()和f == eof(); -
false, 如果e == eof()xorf == eof(); -
否则未指定。
-
-
eof()返回一个值e使得!eq_int_type(e, to_int_type(c))对应所有c。 -
eq(c, d)iff(unsigned char) c == (unsigned char) d.
现在,考虑这个假设的实现:(语法简化)
// char: [-128, 127]
// unsigned char: [0, 255]
// int: [-2^31, 2^31-1]
#define EOF INT_MIN
char to_char_type(int e) {
return char(e - 1);
}
int to_int_type(char c) {
return int(c) + 1;
}
bool eq(char c, char d) {
return c == d;
}
bool eq_int_type(int c, int d) {
return c == d;
}
int eof() {
return EOF;
}
注意
-
(属性1)从
unsigned char到int的转换是保值的; -
(属性 2)从
char到unsigned char的转换是双射的。
现在让我们验证要求:
-
对于每个
int值e,如果eq_int_type(e, to_int_type(c))对于某些c,则e == int(c) + 1。因此,to_char_type(e) == char(int(c)) == c。 -
对于每对
int值e和f,如果e == to_int_type(c)和f == to_int_type(d)对于某些c和d,那么eq_int_type(e, f)iffint(c) + 1 == int(d) + 1iff @98765 (按属性 1)。 EOF 案例也很容易验证。 -
对于每个
char值c,int(c) >= -128,所以int(c) + 1 != EOF。因此,!eq_int_type(eof(), to_int_type(c))。 -
对于每对
char值c和d,eq(c, d)iff(unsigned char) c == (unsigned char d)(按属性 2)。
这是否意味着这个实现符合要求,因此std::cin.peek() == '\n' 没有做它应该做的事情?我在分析中遗漏了什么吗?
【问题讨论】:
-
不保证,实际上这两个是often different 的典型实现。
-
不管怎样,我的阅读和你的一样;
to_int_type被允许执行任何可逆转换,没有任何东西说std::char_traits<char>::to_int_type(c) == static_cast<int>(c)必须保持c的任何值。 -
@IgorTandetnik 至少适合
unsigned char的char值似乎与常见的实现没有偏差——现在我必须计算我写的peek() == '\n'的数量! (耸耸肩)
标签: c++ io language-lawyer istream char-traits