字符串输入


字符串输入
一、gets()函数
gets()是从标准输入设备读字符串函数
功能为:从stdin流中读取字符串,直至接受到换行符或EOF时停止,并将读取的结果存放在buffer指针所指向的字符数组中。换行符不作为读取串的内容,读取的换行符被转换为‘\0’空字符,并由此来结束字符串。
注意:不会判断上限,以回车结束读取,所以程序员应该确保buffer的空间足够大,以便在执行读操作时不发生溢出。使用时需要包含stdio.h头文件
二、gets()的替代品
1.fgets()函数(和fputs())
fgets()函数通过第2个参数限制读入的字符数来解决溢出的问题。该函
数专门设计用于处理文件输入,所以一般情况下可能不太好用。fgets()和
gets()的区别如下。
fgets()函数的第2个参数指明了读入字符的最大数量。如果该参数的值是n,那么fgets()将读入n-1个字符,或者读到遇到的第一个换行符为止。
如果fgets()读到一个换行符,会把它储存在字符串中。这点与gets()不同,gets()会丢弃换行符。
fgets()函数的第3个参数指明要读入的文件。如果读入从键盘输入的数
据,则以stdin(标准输入)作为参数,该标识符定义在stdio.h中。
因为fgets()函数把换行符放在字符串的末尾(假设输入行不溢出),通常要与fputs()函数(和puts()类似)配对使用,除非该函数不在字符串末尾添加换行符。fputs()函数的第2个参数指明它要写入的文件。如果要显示在计算机显示器上,应使用stdout(标准输出)作为该参数。
2.gets_s()函数
C11新增的gets_s()函数(可选)和fgets()类似,用一个参数限制读入的
字符数。假设把程序清单11.9中的fgets()换成gets_s(),其他内容不变,那么下面的代码将把一行输入中的前9个字符读入words数组中,假设末尾有换行符:
gets_s(words,STLEN);
gets_s()与fgets()的区别如下。
gets_s()只从标准输入中读取数据,所以不需要第3个参数。
如果gets_s()读到换行符,会丢弃它而不是储存它。
如果gets_s()读到最大字符数都没有读到换行符,会执行以下几步。首先把目标数组中的首字符设置为空字符,读取并丢弃随后的输入直至读到换行符或文件结尾,然后返回空指针。接着,调用依赖实现的“处理函数”(或你选择的其他函数),可能会中止或退出程序。
第2个特性说明,只要输入行未超过最大字符数,gets_s()和gets()几乎一样,完全可以用gets_s()替换gets()。第3个特性说明,要使用这个函数还需要进一步学习。
我们来比较一下gets()、fgets()和gets_s()的适用性。如果目标存储区装得下输入行,3个函数都没问题。但是fgets()会保留输入末尾的换行符作为字符串的一部分,要编写额外的代码将其替换成空字符。
如果输入行太长会怎样?使用gets()不安全,它会擦写现有数据,存在安全隐患。gets_s()函数很安全,但是,如果并不希望程序中止或退出,就要知道如何编写特殊的“处理函数”。另外,如果打算让程序继续运行,
gets_s()会丢弃该输入行的其余字符,无论你是否需要。由此可见,当输入太长,超过数组可容纳的字符数时,fgets()函数最容易使用,而且可以选择不同的处理方式。
所以,当输入与预期不符时,gets_s()完全没有fgets()函数方便、灵活。也许这也是gets_s()只作为C库的可选扩展的原因之一。鉴于此,fgets()通常是处理类似情况的最佳选择。
3.s_gets()函数
程序清单演示了fgets()函数的一种用法:读取整行输入并用空字符代替换行符,或者读取一部分输入,并丢弃其余部分。既然没有处理这种情况的标准函数,我们就创建一个,在后面的程序中会用得上。
11.10提供了一个这样的函数。
程序清单s_gets()函数
chars_gets(charst,intn)
{
char*ret_val;
inti=0;
ret_val=fgets(st,n,stdin);
if(ret_val)//即,ret_val!=NULL
{
while(st[i]!='\n'&&st[i]!='\0')
i++;
if(st[i]=='\n')
st[i]='\0';
else
while(getchar()!='\n')
continue;
}
returnret_val;
}
如果fgets()返回NULL,说明读到文件结尾或出现读取错误,s_gets()函数跳过了这个过程。它模仿程序清单11.9的处理方法,如果字符串中出现换行符,就用空字符替换它;如果字符串中出现空字符,就丢弃该输入行的其余字符,然后返回与fgets()相同的值。
为什么要丢弃过长输入行中的余下字符。这是因为,输入行中多出来的字符会被留在缓冲区中,成为下一次读取语句的输入。例如,如果下一条读取语句要读取的是double类型的值,就可能导致程序崩溃。丢弃输入行余下的字符保证了读取语句与键盘输入同步。我们设计的s_gets()函数并不完美,它最严重的缺陷是遇到不合适的输入时毫无反应。它丢弃多余的字符时,既不通知程序也不告知用户。但是,用来替换前面程序示例中的gets()足够了。
三、C语言三种字符串输入方式的区别
1.scanf("%s",s);
sacnf():当遇到从键盘输入空白字符(空格、换行符、制表符和空行)都标志输入结束,当要注意的是这些空白字符并没有被读入到字符串中也没有丢弃,而是等待下一个输入函数读取。当scanf函数gets()和fgets()混用的话,可能产生一些不一样的结果。
2.gets(s);
gets():可以接受一切字符,即你输入什么空格、换行符什么的都可以读到字符串中。当在键盘上敲回车则表示输入结束,与scanf函数不同的是,换行符也会被读入。但是在使用gets()函数时,要注意输入字符的个数,不能超过字符串的大小限制。
3.fgets(s,size,stdin);
fgets():是为了解决gets()函数容易导致缓冲器溢出的问题来代替gets()函数。
s:表示字符串
size::输入字符的个数限制(其中要留一个给‘\0’)
stdin:标准输入模式(即从键盘输入),fgets()函数还可以从文本中读入。
当遇到换行符表示输入结束,分为俩种情况:
1.如果输入的字符个数没有超过size-1,然后敲回车结束,fgets()会把换行符也输入到字符串中。
2.如果输入字符超过size-1,然后敲回车结束,fgets()会截取size-1个字符输入字符串中,剩下的等待下一个输入函数读取。
参考书籍:《C Primer Plus》第六版中文版
相关习题
1.设计并测试一个函数,从收入中获取n个字符(包括空白制表符换行符),把结果存储在一个数组里,作为一个参数传递数组的地址。


2.修改编程练习1的函数在n个字符后停止,或者再读到第一个空白、制表符或者换行符时停止。哪个先遇到哪个先停止,不能只使用scanf()函数。