数据类型为 unsigned char 时 scanf 行为的问题

A problem with the behaviour of scanf when data type is unsigned char

所以我不知道为什么会出现这种行为:

#include <stdio.h>

int main()
{
    unsigned char c;
    char d;
    scanf("%hhu", &d);
    printf("%c\n", d);

    return 0;
}

如果我没记错的话 %hhu 是给 unsigned char 的。如果我输入几乎任何字符,如 ab,答案都是空的,d 得到值 0。但是如果我输入 97 然后 d 打印值 a (因此 ASCII 被转换为 char)。当数据类型为 char 时,情况显然不是这样。我直接输入字符就可以存储了

也在对这段代码稍加修改

#include <stdio.h>

int main()
{
    unsigned char c;
    char d;
    int g;
    scanf("%hhu", &d);
    printf("%c\n", d);
    scanf("%d", &g);
    printf("%d is g\n", g);

    return 0;
}

如果我将第一个输入作为 wa 之类的字符,那么它只会跳过第二个 scanf,但如果输入是数字,则它会正常工作。

格式说明符 %u 用于读取十进制整数,%hhu%u 添加了长度修饰符。

要将一个字符读取到 char 变量,请使用说明符 %c

你是正确的,%hhu 格式说明符需要一个 unsigned char* 参数。但是,格式的 u 部分规定输入被解释为 十进制整数 。要将数据作为(未处理的)字符输入,您应该使用 %c 格式说明符。

If I input almost any character like 'a', or 'b' the answer is nothing and d gets the value 0. But if I input 97 then d prints the value a. (so ASCII is converted to char) This clearly not the case when the data type is char.

scanf 所做的与类型无关,而是与您使用的格式说明符相关(它又定义了参数中预期的类型)。

当您使用 %hhu 时,输入被读取为带符号的十进制 整数 ,按 strtoul 解析,并存储在 unsigned char.这就是 97 被正确读取的原因。

此外,在这两个示例中,您应该考虑 return 值以了解是否有任何失败。这样你就可以检测错误并做任何需要的事情,比如再次询问用户。

If I remember correctly %hhu is for unsigned char. If I input almost any character like 'a', or 'b' the answer is nothing and d gets the value 0.

"%hhu" 期望输入文本是数字,如 "123"。然后将123的值保存在d中。 d 没有 得到 值 0。d 没有被 scanf("%hhu", &d); 更改,因为输入无效。

如果你想将一个字符读入 unsigned char

unsigned char d;
if (scanf("%c", &d) == 1) Success();

如果您想将数字文本读入 unsigned char

unsigned char d;
if (scanf("%hhu", &d) == 1) Success();

在所有情况下,测试 scanf() 的 return 值。


If I give first input as a character like 'w' or 'a' then it just skips the second scanf, but if the input is a number then it works normally.

scanf() 无法根据提供的说明符转换输入文本时,扫描将停止并且有问题的文本 仍然stdin.

一个常见的代码习惯用法是读取剩余的输入并将其扔到 '\n'

int ch;
while ((ch = getchar()) != '\n') && ch !- EOF) {
  ;
}

a 不是 %hhu 的有效输入。期望一个整数(在数学意义上)。如果我们添加错误检查(下面的代码),我们得到:

$ gcc -Wall -Wextra -pedantic a.c -o a && ./a
a
Number of assigned variables: 0
Can't read: Invalid input
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    unsigned char c;

    int rv = scanf("%hhu", &c);
    if (rv == EOF) {
       if (ferror(stdin)) {
          perror("Can't read");
       } else {
          fprintf(stderr, "Can't read: Premature EOF\n");
       }

       exit(1);
    }

    printf("Number of assigned variables: %d\n", rv);

    if (rv < 1) {
       fprintf(stderr, "Can't read: Invalid input\n");
       exit(1);
    }

    printf("%hhu\n", c);

    return 0;
}

无效输入保留在句柄的缓冲区中,以供将来读取。因此,早期 scanf 中的错误可能导致后来 scanf 失败。

如果您希望在出错后继续,您可以简单地阅读直到获得 LF 以清除缓冲区中的任何“垃圾”。

void read_stdin_to_eol(void) {
   while (1) {
      int ch = getchar();
      if (ch == '\n' || ch == EOF)
         return ch;
   }
}