C编程中scanf("%s")
,scanf(”%[^\n]s")
和gets(a)
之间有什么区别?
scanf("%[^\n]s", a)
scanf("%s", a)
gets(a)
采用字符数组输入的三种方式之间的主要区别是什么?
答案 0 :(得分:4)
scanf("%s",a);
将跳过输入中的前导空格字符,并匹配字符,直到遇到空白字符(或直到达到文件结尾),并将它们存储在参数指示的数组中。请注意,这容易受到缓冲区溢出的影响,因此最好包含一个宽度指定器,它提供从输入中读取的最大字符数。例如,如果a
是100 char
s的数组,则应使用%99s
;这为由\0
自动添加的scanf()
终结符留出了空间。
scanf("%s[^\n]",a);
和scanf("%[^\n]s", a);
都不是我的意思,而应该是:scanf("%[^\n]",a);
。 %[]
是 scanset 指令。没有必要使用%[]
跟随s
指令,这只会在scanf()
完成后告诉s
与输入中的文字%[]
匹配。 scanset指令匹配括号中描述的字符,并将它们分配给相应的参数。当匹配失败时,该字符将放回输入流中。这里,^\n
表示应该匹配换行符的除之外的所有字符,因此该指令将匹配字符,直到遇到换行符,并且换行符将保留在输入流中。关于指定最大宽度的相同建议也适用于:%99[^\n]
以避免缓冲区溢出,如果a
是100 char
s的数组。请注意,%[^\n]
指令将匹配任何不是\n
的字符,包括其他空白字符。这意味着它将不跳过前导空格字符(但输入中的前导\n
将导致指令立即失败,而不进行赋值),与{{1 },并将读取包含空格的输入的行。
%s
不读取输入,但是是输出函数。请注意,此函数在打印其参数后打印换行符。也许您打算在此方法列表中包含puts(a);
来收集输入。
gets(a);
is an unsafe function在C99中已弃用,并已完全从C11中的语言中删除。您不应该出于任何原因使用此功能。此函数获取一行输入,读取字符直到遇到换行符,或者直到达到文件结尾。换行符被丢弃;它不存储在gets()
指示的数组中,并且不会返回到输入流。因此,在过去使用a
时,它与gets()
配合得很好,puts()
会在打印参数后自动打印换行符。
最后,有关更多信息,请fgets()
。此函数获取一行输入,但采用size参数,以避免缓冲区溢出。鉴于我之前的char a[100];
示例,fgets()
将被称为:
fgets(a, 100, stdin);
或有时:
fgets(a, sizeof a, stdin);
在这里,fgets()
最多只能读取一个字符而不是size参数指定的数字,从而允许\0
的空间,它总是被添加。如果读取\n
,则会将其存储在a
中。由于换行不被丢弃,puts()
在这里不起作用;通常在使用fgets()
输入后需要删除换行符。
答案 1 :(得分:2)
首先,他们所有人都有未定义的行为出于同样的原因:他们会读取许多字符你事先无法知道,但通过你的指针,您提供存储此数据的存储位置,并且此存储具有一些固定大小。因此,始终输入可能会溢出您的缓冲区。您不应该在代码中使用任何这些行。
那说:
gets()
读取输入的行并将其存储到缓冲区。它还会读取换行符,但不会存储。 此功能因设计错误,因为无法安全使用。不要使用它。它已被C11中的C标准删除,因此您无论如何都只能使用旧标准。正确的替换是char a[100]; fgets(a, sizeof a, stdin);
。但将将换行符存储在缓冲区中。
scanf("%[^\n]s", ...)
还会读取输入的行。 []
转化说明符会列出已接受的列表,或者前面带有^
的拒绝字符列表。因此,使用此语法,它将接受任何字符除换行符。因此,不会以这种方式读取换行符 。 {<1}}将在输入字面上搜索,这不是你的意思。 s
和s
是不同的转换说明符。要正确使用此字段,您必须使用如下字段:[]
。请注意,您必须指定少一个而不是缓冲区大小,因为char a[100]; scanf("%99[^\n]", a);
不计算附加为字符串结束标记的scanf()
字符。
'\0'
读取“单词”,即它停在第一个空白字符处。要正确使用此功能,请使用scanf("%s", ...)
。