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

use*_*699 3 c scanf

我已经搜索并读取了^修饰符状态以忽略你放在[]中的任何内容scanf.例如:

int val;   
scanf("%[^abc] %d, &val);  
printf("val is %d", val);  
Run Code Online (Sandbox Code Playgroud)

现在,如果我输入abc42,我认为abc将被忽略,42将被存储到val中.但是,这不会发生.

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

scanf("%*[^abc] %d, &val);
Run Code Online (Sandbox Code Playgroud)

但这也行不通.所以我对^实际上做了什么很困惑.

god*_*el9 6

当你说你想scanf忽略某些字符时,我认为你的意思是你想要scanf阅读这些字符然后忽略它们.为此,您使用%*[]格式说明符:

scanf("%*[abc] %d", &val);
Run Code Online (Sandbox Code Playgroud)

[abc]告诉scanf读取任何数目的括号中的字符(即,b或c).该*告诉scanf忽略这些字符,然后%d读取值成val.

^说明符告诉scanf读取任意数目的字符其他比在括号,这是你想要做什么,相反之间,我想.


Bas*_*tch 5

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

scanf("%[^abc] %d", &val);  
Run Code Online (Sandbox Code Playgroud)

在读取两个项目,第一个是字符的集合{以外的字符串a,b,c}(以及第二是整数去"无处").

所以,你的程序未定义行为(UB),因为你打电话scanf与比它应该少一个参数,因为第一个参数应该是一个足够宽的位置的char缓冲.UB可能非常糟糕,所以你需要始终避免它.

你可以试试:

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 
}
Run Code Online (Sandbox Code Playgroud)