4

问题如何正确使用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_typechar值转换为int_type. 现在,std::cin.peek() == '\n'真的意味着下一个字符是\n


以下是我的分析。让我们从[char.traits.require][char.traits.specializations.char]收集碎片:

  1. 对于每个inteto_char_type(e)返回

    • c, 如果​eq_­int_­type(e, ​to_­int_­type(c))对于一些c;

    • 其他一些未指定的值。

  2. 对于每对intefeq_­int_­type(e, f)返回

    • eq(c, d), 如果e == to_int_type(c)f == to_int_type(d)对于一些cd;

    • true, 如果e == eof()f == eof();

    • false, 如果e == eof()f == eof()或;

    • 否则未指定。

  3. eof()返回一个值e,使得!eq_int_type(e, to_int_type(c))所有c.

  4. 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)从charto的转换unsigned char是双射的。

现在让我们验证要求:

  1. 对于每一个inte,如果​eq_­int_­type(e, ​to_­int_­type(c))对于一些c,那么e == int(c) + 1。因此,to_char_type(e) == char(int(c)) == c

  2. 对于每对inteand f,如果e == to_int_type(c)f == to_int_type(d)对于一些cand d,则当且eq_int_type(e, f)当当int(c) + 1 == int(d) + 1c == d(通过属性 1)。EOF 案例也很容易验证。

  3. 对于每个charc, int(c) >= -128, 所以int(c) + 1 != EOF。因此,!eq_int_type(eof(), to_int_type(c))

  4. 对于每对charcdeq(c, d)当且仅当(unsigned char) c == (unsigned char d)(通过属性 2)。

这是否意味着这个实现符合要求,因此std::cin.peek() == '\n'没有做它应该做的事情?我在分析中遗漏了什么吗?

4

1 回答 1

1

这是否意味着此实现符合要求,因此 std::cin.peek() == '\n' 没有做它应该做的事情?

我同意你的分析。这不能保证。

看来您必须使用eq_­int_­type(std::cin.peek(), ​to_­int_­type('\n'))才能保证正确的结果。


PS​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,但您已经排除了那些具有假设大小的系统。

于 2021-02-16T03:21:10.680 回答