我被告知用户输入字符串时不应使用scanf。相反,大多数专家和StackOverflow上的用户都可以使用gets()。我从未在StackOverflow上问过为什么不应该使用scanf over gets for strings。这不是实际问题,但非常感谢对这个问题的回答。
现在回答实际问题。我遇到过这种类型的代码 -
scanf("%[^\n]s",a);
这会读取一个字符串,直到用户输入一个新的行字符,同时将空格也视为字符串。
如果我使用
,是否有任何问题scanf("%[^\n]s",a);
而不是获取?
听起来比scanf函数更优化,gets纯粹专门用于处理字符串。请让我知道这件事。
更新
This链接帮助我更好地理解它。
答案 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
是您的最佳选择。