您在格式字符串中键入的字符不是ASCII脱字符符号,它是以UTF-8编码为2字节[CB 84]的Unicode舍音符˄
U+02C4.因此,格式字符串是%[\xCB\x84\n]
,因此scanf()
只接受这3个字节的任意组合的序列.
如果用户输入其他字符作为第一个字符,则在用户按Enter键后,scanf()
将返回0
.相反,如果用户按Enter键,则接受\n
并继续输入,直到输入不同于3个字节的字符,但只有当用户再次按Enter键时才能使用.
观察到的行为是,只要只键入Enter键,输入就会继续,然后输出多个换行符,其中str
行后面跟着最后一个换行符.
您可能在键盘上键入了抑扬符(可能是法语AZERTY或类似布局),后跟一个空格,而不是AltGr9组合键.
%[^\n]
格式还有其他问题:
scanf()
无法找到目标数组的长度,任何足够长的输入都会导致缓冲区溢出.你应该写%99[^\n]
.
- 如果用户通过Enter键输入空行,
scanf()
将返回0
,缓冲区str
保持不变,因此未初始化.
- 如果输入流为空,
scanf()
将返回EOF
,也不修改缓冲区str
.
- 用户输入的换行符在输入流中处于挂起状态,这可能会导致使用
scanf()
或fgets()
的后续输入产生混淆行为.
因此,您应该始终测试返回值scanf()
以检测和报告无效或丢失的输入,而不是调用未定义的行为,并且使用fgets()
从用户读取字符串不那么容易混淆.
以下是修改后的版本:
#include <stdio.h>
int main(void) {
char str[100];
printf("Enter a string: ");
if (scanf("%99[^\n]", str) == 1) {
printf("%s\n", str);
} else {
printf("invalid or missing input\n");
}
return 0;
}
以下是使用fgets()
从用户输入字符串的推荐方法:
#include <stdio.h>
#include <string.h>
int main(void) {
char str[101];
printf("Enter a string: ");
if (fgets(str, sizeof str, stdin)) {
str[strcspn(str, "\n")] = '\0'; // strip the trailing newline if any
printf("%s\n", str);
} else {
printf("cannot read from input\n");
}
return 0;
}