scanf(“% s”,a)vs得到(a)
我被告知当用户输入字符串时不应使用scanf。 相反,大多数专家和StackOverflow上的用户都可以使用gets()。 我从来没有在StackOverflow上问过为什么不应该使用scanf over gets for strings。 这不是实际问题,但非常感谢回答这个问题。
现在来到实际的问题。 我遇到过这种类型的代码 –
scanf("%[^\n]s",a);
这将读取一个字符串,直到用户输入一个新的行字符,同时将空格也视为字符串。
如果我使用有任何问题
scanf("%[^\n]s",a);
而不是得到?
得到比scanf函数更优化,听起来,gets纯粹专门处理字符串。 请让我知道这件事。
更新
这个链接帮助我更好地理解它。
gets(3)
是危险的,应该不惜一切代价避免。 我无法想象gets(3)
不是安全漏洞的用途。
scanf(3)
的%s
也很危险 – 您必须使用“字段宽度”说明符来指示已分配的缓冲区的大小。 没有字段宽度,这个例程和gets(3)
一样危险:
char name[64]; scanf("%63s", name);
GNU C库为%s
提供了a
修饰符 ,为您分配缓冲区。 这种非便携式扩展可能不太正确使用:
The GNU C library supports a nonstandard extension that causes the library to dynamically allocate a string of sufficient size for input strings for the %s and %a[range] conversion specifiers. To make use of this feature, specify a as a length modifier (thus %as or %a[range]). The caller must free(3) the returned string, as in the following example: char *p; int n; errno = 0; n = scanf("%a[az]", &p); if (n == 1) { printf("read: %s\n", p); free(p); } else if (errno != 0) { perror("scanf"); } else { fprintf(stderr, "No matching characters\n"): } As shown in the above example, it is only necessary to call free(3) if the scanf() call successfully read a string.
首先,目前尚不清楚s
在你的格式字符串中做了什么。 %[^\n]
部分是一个自给自足的格式说明符。 它似乎不是%s
格式的修饰符,因为您似乎相信。 这意味着"%[^\n]s"
格式字符串将被scanf
解释为两个独立的格式说明符: %[^\n]
后跟一个单独的s
。 这将指示scanf
读取所有内容,直到遇到\n
(保留\n
未读),然后要求下一个输入字符为s
。 这没有任何意义。 没有输入符合这种自相矛盾的格式。
其次,显然意味着scanf("%[^\n]", a)
。 这有点接近[不再可用] gets
(或fgets
),但它不一样。 scanf
要求每个格式说明符至少匹配一个输入字符。 如果无法匹配请求的格式说明符的任何输入字符,则scanf
将失败并中止。 这意味着scanf("%[^\n]",a)
无法读取空输入行,即立即包含\n
字符的行。 如果您将这样的一行输入上面的scanf
,它将返回0
表示失败并保持不变。 这与典型的基于行的输入function的工作方式有很大不同。
(这是一个相当令人惊讶且看似不合逻辑的%[]
格式。就个人而言,我更喜欢%[]
能够匹配空序列并产生空字符串,但这不是标准scanf
工作方式。)
如果您想以逐行方式阅读输入, fgets
是您的最佳选择。