数据类型为 unsigned char 时 scanf 的行为问题
Posted
技术标签:
【中文标题】数据类型为 unsigned char 时 scanf 的行为问题【英文标题】:A problem with the behaviour of scanf when data type is unsigned char 【发布时间】:2020-08-07 16:01:45 【问题描述】:所以我不知道为什么会观察到这种行为:
#include <stdio.h>
int main()
unsigned char c;
char d;
scanf("%hhu", &d);
printf("%c\n", d);
return 0;
如果我没记错的话,%hhu
代表unsigned char
。如果我输入几乎任何字符,如a
或b
,答案是空的,d
得到值0
。但如果我输入97
,那么d
会打印出a
的值(因此ASCII 会转换为字符)。当数据类型为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;
如果我将第一个输入作为w
或a
之类的字符,那么它只会跳过第二个scanf
,但如果输入是一个数字,那么它可以正常工作。
【问题讨论】:
a
不是%hhu
的有效输入,因此scanf
返回错误。检查scanf
返回的值。
Re "这是两个不同的问题",不,只是提供错误数据的两个例子。
【参考方案1】:
%hhu
格式说明符需要 unsigned char*
参数是正确的。但是,格式的u
部分指示输入被解释为十进制整数。要将数据作为(未处理的)字符输入,您应该使用%c
格式说明符。
【讨论】:
【参考方案2】:格式说明符%u
用于读取十进制整数,%hhu
是添加了长度修饰符的%u
。
要将一个字符读入char
变量,请使用说明符%c
。
【讨论】:
【参考方案3】:如果我输入几乎任何字符,如“a”或“b”,答案是空的,d 得到值 0。但如果我输入 97,则 d 打印值 a。 (所以 ASCII 被转换为 char)当数据类型是 char 时显然不是这种情况。
scanf
所做的与类型无关,而是与您使用的格式说明符有关(反过来,它定义了参数中预期的类型)。
当您使用%hhu
时,输入被读取为有符号十进制整数,解析为strtoul
,并存储在unsigned char
中。这就是97
被正确读取的原因。
此外,在这两个示例中,您都应该考虑返回值以了解是否有任何失败。这样您就可以检测错误并执行任何需要的操作,例如再次询问用户。
【讨论】:
【参考方案4】: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;
【讨论】:
为了理解像你解释的那样谈论“句柄缓冲区”的scanf,我可以得到一些来源或指针吗? 只表示不吸收无效输入。未来的读取将从导致错误的字符开始,而不是之后的字符。从我系统上的手册页中不清楚是否会发生这种情况。【参考方案5】:如果我没记错的话,
%hhu
代表unsigned char
。如果我输入几乎任何字符,如“a”或“b”,答案是什么,d 的值为 0。
"%hhu"
期望输入文本是数字,如@987654324@。然后将 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()
的返回值。
如果我将第一个输入作为 'w' 或 'a' 之类的字符给出,那么它只会跳过第二个 scanf,但如果输入是一个数字,那么它会正常工作。
当scanf()
未能按照提供的说明符转换输入文本时,扫描停止并且有问题的文本保留在stdin
中。
一个常见的代码习惯是读取剩余的输入并将其折腾到'\n'
。
int ch;
while ((ch = getchar()) != '\n') && ch !- EOF)
;
【讨论】:
以上是关于数据类型为 unsigned char 时 scanf 的行为问题的主要内容,如果未能解决你的问题,请参考以下文章
在 c语言中int long unsigned 和 char这四种类型数据的转换规律是_____.