如何解决是否保证 std::char_traits<char>::to_int_type(c) == static_cast<int>(c)?
问题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)
,ife == to_int_type(c)
andf == to_int_type(d)
for somec
andd
; -
true
,如果e == eof()
和f == eof()
; -
false
,ife == eof()
xorf == eof()
; -
未指定。
-
-
eof()
返回一个值e
,使得所有!eq_int_type(e,to_int_type(c))
的c
。 -
eq(c,d)
仅当(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
和{{ 1}},然后d
iffeq_int_type(e,f)
iffint(c) + 1 == int(d) + 1
(根据属性 1)。 EOF 案例也很容易验证。 -
对于每个
c == d
值char
,c
,所以int(c) >= -128
。因此,int(c) + 1 != EOF
。 -
对于每对
!eq_int_type(eof(),to_int_type(c))
值char
和c
,d
iffeq(c,d)
(根据属性 2)。
这是否意味着这个实现是一致的,因此 (unsigned char) c == (unsigned char d)
没有做它应该做的事情?我的分析中是否遗漏了什么?
解决方法
这是否意味着这个实现是一致的,因此 std::cin.peek() == '\n' 没有做它应该做的事情?
我同意你的分析。这不能保证。
看来您必须使用 eq_int_type(std::cin.peek(),to_int_type('\n'))
来保证正确的结果。
附言由于 to_char_type(EOF)
中的签名溢出,您的 INT_MIN - 1
具有未定义的行为。当然,在这种情况下未指定该值,但您仍然不能拥有 UB。这将是有效的:
char to_char_type(int e) {
return e == EOF
? 0 // doesn't matter
: char(e - 1);
}
to_int_type
将在 int 和 char 大小相同的系统上使用 UB,以防万一c == INT_MAX
,但您已经排除了那些具有假设大小的系统。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。