標(biāo)準(zhǔn)I/O庫(kù)函數(shù):fgets與gets比較分析
掃描二維碼
隨時(shí)隨地手機(jī)看文章
函數(shù)名:fgets
功能:從流中讀取一個(gè)字符串
用法:char *fgets(char *string,int n,FILE *stream);
形參注釋:
*string:結(jié)果數(shù)據(jù)的首地址;n-1:一次讀入數(shù)據(jù)塊的長(zhǎng)度,其默認(rèn)值為1k,即1024;stream文件指針,指向一個(gè)文件
函數(shù)說(shuō)明:
fgets()用來(lái)從參數(shù)stream所指的文件內(nèi)讀入字符并存到參數(shù)s所指的內(nèi)存空間,直到出現(xiàn)換行字符、讀到文件尾或是已讀了size-1個(gè)字符為止,最后會(huì)加上NULL作為字符串結(jié)束。
如果在未讀滿n-1個(gè)字符之時(shí),已讀到一個(gè)換行符或一個(gè)EOF(文件結(jié)束標(biāo)志),則結(jié)束本次讀操作,讀入的字符串中最后包含讀到的換行符。
示例:
#include <string.h>
#include <stdio.h>
int main(void)
{
FILE *stream; //FILE 是一種數(shù)據(jù)類型,是管理文件流的一種結(jié)構(gòu)
char string[] = "This is a test";
char msg[20];
/* open a file for update */
stream = fopen("DUMMY.FIL", "w+");
/* write a string into the file */
fwrite(string, strlen(string), 1, stream);
/* seek to the start of the file */
fseek(stream, 0, SEEK_SET);
/* read a string from the file */
fgets(msg, strlen(string)+1, stream);
/* display the string */
printf("%s", msg);
fclose(stream);
return 0;
}
代碼分析:
操作成功時(shí)返回的是msg的值,如果碰到文件結(jié)束或錯(cuò)誤的時(shí)候,fgets返回NULL;因?yàn)檩斎氲倪^(guò)程中一般只會(huì)按下回車(chē),很少會(huì)是EOF的,所以不會(huì)是碰到文件結(jié)束,而錯(cuò)誤是當(dāng)你傳入msg是NULL的時(shí)候才會(huì)遇到,所以基本上是不可能返回NULL的。而且輸入超過(guò)了長(zhǎng)度n的時(shí)候,fgets會(huì)自動(dòng)截?cái)嗟?屬于操作成功。
函數(shù)名:gets
功能:從stdin流中讀取字符串,直至接受到換行符或EOF時(shí)停止,并將讀取的結(jié)果存放在str指針?biāo)赶虻淖址麛?shù)組中。換行符不作為讀取串的內(nèi)容,讀取的換行符被轉(zhuǎn)換為null值,并由此來(lái)結(jié)束字符串。
示例:
#include"stdio.h"
void main()
{
char str1[5];
gets(str1);
printf("%sn",str1);
}
注意:本函數(shù)可以無(wú)限讀取,不會(huì)判斷上限,所以程序員應(yīng)該確保str的空間足夠大,以便在執(zhí)行讀操作時(shí)不發(fā)生溢出。
代碼分析:
用gets函數(shù)時(shí),編譯器會(huì)有報(bào)警提示,因?yàn)間ets函數(shù)不安全,沒(méi)有限制輸入緩沖區(qū)的大小,容易造成溢出。這就好像養(yǎng)金魚(yú),你投多少魚(yú)食它就吃多少,自己不知道控制,但它的胃容量是有上限的(默認(rèn)值),喂的太多金魚(yú)就會(huì)撐死(溢出)。
總結(jié):
1 盡量不使用gets
2 內(nèi)存越界是有問(wèn)題隱患,但并不是一定會(huì)體現(xiàn)出問(wèn)題,要看具體情況。
來(lái)源:miaomi2次