scanf(“%[^ \ n] s”,a)vs得到(a)

时间:2011-11-18 04:23:44

标签: c scanf gets

我被告知用户输入字符串时不应使用scanf。相反,大多数专家和StackOverflow上的用户都可以使用gets()。我从未在StackOverflow上问过为什么不应该使用scanf over gets for strings。这不是实际问题,但非常感谢对这个问题的回答。

现在回答实际问题。我遇到过这种类型的代码 -

scanf("%[^\n]s",a); 

这会读取一个字符串,直到用户输入一个新的行字符,同时将空格也视为字符串。

如果我使用

,是否有任何问题
scanf("%[^\n]s",a);

而不是获取?

听起来比scanf函数更优化,gets纯粹专门用于处理字符串。请让我知道这件事。

更新

This链接帮助我更好地理解它。

2 个答案:

答案 0 :(得分:7)

gets(3)是危险的,应该不惜一切代价避免。我无法想象gets(3) 安全漏洞的用途。

scanf(3)的{​​{1}}也很危险 - 您必须使用“字段宽度”说明符来指示已分配的缓冲区的大小。如果没有字段宽度,此例程与%s

一样危险
gets(3)

GNU C库为char name[64]; scanf("%63s", name); 提供a 修饰符,为您分配缓冲区。这种非便携式扩展可能不太容易正确使用:

%s

答案 1 :(得分:4)

首先,不清楚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以指示失败并保持a不变。这与典型的基于行的输入功能的工作方式有很大不同。

(对于%[]格式,这是一个相当令人惊讶且看似不合逻辑的。个人而言,我更希望%[]能够匹配空序列并产生空字符串,但这不是标准{ {1}}有效。)

如果您想逐行阅读输入,scanf是您的最佳选择。