C语⾔中的gets()函数
在c语⾔中读取字符串有多种⽅法,⽐如scanf() 配合%s使⽤,但是这种⽅法只能获取⼀个单词,即遇到空格等空字符就会返回。如果要读取⼀⾏字符串,
⽐如:I love MIT
这种情况,scanf()就⽆能为⼒了。这时我们最先想到的是⽤gets()读取.
C标准库中的 gets() 函数。
c语言定义一个字符串这个函数的定义如下:
char * gets ( char * str );
gets() 函数的形参只有⼀个指针。它会从标准输⼊流中读字符到⼀块连续的内存地址空间中。这块地址空间的开始位置就是指针 str 指向的位置。当在输⼊流中遇到⽂件结束符( EOF )或者换⾏符(\n)时,读取操作结束。当读⼊换⾏符(\n)时,该字符不会被放⼊那块连续的地址空间中。在读取结束时, gets() 会⾃动在内存空间的末尾追加⼀个 NULL 字符。经过上述这些操作,对于程序员来说,这个函数得到的就是从标准输⼊进来的,以 NULL 字符结尾的C字符串。如果读⼊的字符流是⼀整⾏的话,⾏尾的换⾏符将会被舍去。
gets()函数从标准输⼊(键盘)读⼊⼀⾏数据,所谓读取⼀⾏,就是遇到换⾏符就返回。
gets()函数并不读取换⾏符'\n',它会把换⾏符替换成空字符'\0',作为c语⾔字符串结束的标志。
gets()函数经常和puts()函数配对使⽤,puts()函数⽤于显⽰字符串,并⾃动在字符串后⾯添加⼀个换⾏标志'\n'
gets()函数存在⼀个严重的缺陷,这个缺陷就是:它不会检查数组是否能够装的下输⼊⾏:
⽐如:
我们定义了⼀个数组char src[5],这时候我们调⽤gets(src),来从标准输⼊读取字符串,我们看到gets()函数的参数为数组名,我们都知道,数组名就相当于⼀个指针,也就是数组的⾸地址。这时如果我们的输⼊⼤于5个字符,⽐如 I love MIT, gets()函数会从src所指地址开始,依次填⼊每个字符,但是src只分配了5个字节的空间,填满这五个空间后,gets()函数就会访问未被分配的内存空间,如果这⽚空间已经存有数据,这时程序就会发⽣错误,⽽中断。
虽然 gets() 函数早就被公认为不安全的,但是它仍然存在于 C89 和 C99 标准,并最终在 C2011 标准中移除了。但这仅仅是在语⾔标准中的移除,当我检查⾃⼰的⼀些代码时,发现仍有地⽅⽤到了它。
除了gets(),那我们还可以⽤什么来代替它的功能呢?
C11标准新增了gets_s()函数可以代替gets()函数,但是,该函数是stdio.h输⼊输出函数系类中的可选扩展,因此,即使编译器⽀持C11标准,也有可能不⽀持gets_s()函数。
其实我们可以⽤c语⾔中的fgets()函数来代替gets()
我们先看⼀下函数原型声明:
char *fgets(char *buf, int bufsize, FILE *stream);
注意⼀下第⼆个参数bufsize,这个参数就限制了读取的字符的个数,这就可以解决gets()函数的缺陷。
我们知道fgets() 函数主要⽤于读取⽂件,如果要读取键盘,则stream参数应该为stdin,
需要注意的是,如果bufsize设置为n,那么fgets()函数最多读取n-1个字符,之所以⽤“最多”这个词是因为,如果在之前遇到了换⾏符,fgets 函数也会返回。
还有⼀点就是,fgets()函数会读取换⾏符(这⼀点和gets函数不同),当读取结束后,fgets函数会为buf在末尾添加⼀个空字符作为字符串的结束。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。