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是您的最佳选择。