^ scanf修饰符实际上做了什么?

时间:2015-10-12 04:46:28

标签: c scanf

我已经搜索并读到^修饰符声明忽略你放在scanf中的[]内的任何内容。例如:

int val;   
scanf("%[^abc] %d, &val);  
printf("val is %d", val);  

现在,如果我输入abc42,我认为abc将被忽略,42将被存储到val中。但是,这并没有发生。

我还尝试通过制作scanf来抑制它:

scanf("%*[^abc] %d, &val);

但这也不起作用。所以我对^实际上做了什么很困惑。

3 个答案:

答案 0 :(得分:6)

如果您希望scanf忽略某些字符,我认为您的意思是希望scanf读取这些字符,然后忽略它们。为此,您使用%*[]格式说明符:

scanf("%*[abc] %d", &val);

[abc]告诉scanf读取括号之间的任意数量的字符(即a,b或c)。 *告诉scanf忽略这些字符,然后%d将值读入val

^说明符告诉scanf读取任意数量的字符其他而不是括号之间的字符,这与您想要做的相反,我认为

答案 1 :(得分:5)

您需要仔细阅读scanf(3) 的文档并在编译时启用所有警告(例如gcc -Wall -Wextra -g如果使用GCC ...);你可能会被这样的汇编警告过。您还应该使用scanf的结果并在调试器中运行您的程序(gdb

scanf("%[^abc] %d", &val);  

正在阅读两个项目,第一项是在{abc}之外的一系列字符(第二个是“无处”的整数)

所以你的程序有undefined behavior(UB)因为你用一个小于它应该的参数调用scanf,并且因为第一个参数应该是一个足够宽的char缓冲区的位置。 UB可以是bad,所以你需要始终避免它

您可以尝试:

int val= 0;
char buf[32]; // 30+1 could be enough....
memset (buf, 0, sizeof(buf));
if (scanf("%30[^abc] %d", buf, &val) == 2) {
  printf("got string %s and int %d\n", buf, val);
}
else { // handle scanf failure 
}

答案 2 :(得分:2)

在编译代码时,它会给出以下警告消息。

test.c:5:2:警告:格式'%[^ abc'需要类型为'char *'的参数,但参数2的类型为' int *'[-Wformat]
test.c:5:2:警告:格式'%d'需要匹配的'int *'参数[-Wformat]

使用它时,必须将字符数组传递给scanf函数。

因此,将scanf行修改为下面,并检查会发生什么。

char buf[100];
int val;
scanf("%[^[abc] %d",buf,&val);

%[^ abc]它读取字符串,如果括号中除^之外的任何字符出现,它将用读取字符填充字符数组的地址。 因此,仅在我们读取字符串输入时才使用它。