1. gets與fgets
gets函數原型:char*gets(char*buffer);//讀取字符到數組:gets(str);str為數組名。
gets函數功能:從鍵盤上輸入字符,直至接受到換行符或EOF時停止,並將讀取的結果存放在buffer指針所指向的字符數組中。
讀取的換行符被轉換為null值,做為字符數組的最后一個字符,來結束字符串。
注意:gets函數由於沒有指定輸入字符大小,所以會無限讀取,一旦輸入的字符大於數組長度,就會發生內存越界,
從而造成程序崩潰或其他數據的錯誤。
fgets函數原型:char *fgets(char *s, int n, FILE *stream);//我們平時可以這么使用:fgets(str, sizeof(str), stdin);
其中str為數組首地址,sizeof(str)為數組大小,stdin表示我們從鍵盤輸入數據。
fgets函數功能:從文件指針stream中讀取字符,存到以s為起始地址的空間里,知道讀完N-1個字符,或者讀完一行。
注意:調用fgets函數時,最多只能讀入n-1個字符。讀入結束后,系統將自動在最后加'\0',並以str作為函數值返回。
2. 細節介紹
1,上面說到gets函數無限讀取,沒有上限。但是有些資料介紹說它最多只能讀取1024個,所以我寫了下面代碼測試一下
(有興趣的朋友可以測試一下(●'◡'●))
1 //測試gets最多讀取字符是否超過1024 2 #include <stdio.h> 3 #include <string.h> 4 5 int main() 6 { 7 char str[2048]; //聽說gets最多可以讀取1024個字符,我們設定一個2048的數組 8 gets(str); //從鍵盤輸入大於1024個字符 9 int cnt; 10 printf("cnt = %d", strlen(str)); //cnt的值就是數組元素個數,是否大於1024呢??? 11 12 return 0; 13 }
經本人親自測試第一次cnt = 2003,第二次cnt = 2086,第二次程序最后崩潰了,但是不能說明gets的讀取上限為2086左右,
因為程序崩潰是由於內存越界
2,在來細說一下fgeis的用法,我們以char str[N];fgets(str, N, stdin);為例:
fgets只能讀取N-1個字符,包括最后的'\n',讀完結束后系統將自動在最后加'\0'(gets讀完結束后系統自動會將'\n'置換成'\0')。
說到這里就有倆種情況了:
一:當你從鍵盤上輸入<=N-1個字符(包括'\n')時,那么字符串str會以‘\n\0’結尾。這就造成了strlen(str)比你想象的大 1 ,
當然你可以通過下面代碼將'\n'去掉。
1 if(str[strlen(str) - 1] == '\n') { // 去掉換行符 2 str[strlen(str) - 1] = '\0'; 3 }
二:當你從鍵盤上輸入>N-1個字符(包括'\n')時,那么字符串str會以'\0'結尾。
3,在上面我們提到從鍵盤輸入字符大於N的情況,這時gets和fgets就又有一些區別了,我們通過以下代碼來測試一下:
1 #include <stdio.h> 2 #include <string.h> 3 #define N 5 4 5 int main() 6 { 7 char s1[N]; 8 char s2[N]; 9 fgets(s1, N, stdin); 10 // gets(s1); 11 if(s1[strlen(s1) - 1] == '\n') { // 去掉換行符 12 s1[strlen(s1) - 1] = '\0'; 13 } 14 15 // fflush(stdin); //清空緩沖區 16 fgets(s2, N, stdin); 17 // gets(s2); 18 if(s2[strlen(s2) - 1] == '\n') { // 去掉換行符 19 s2[strlen(s2) - 1] = '\0'; 20 } 21 22 printf("%s %s", s1, s2); 23 24 return 0; 25 }
當我們輸入12345按下回車,直接就出來1234 5這樣的結果。是不是與我們預想的不一樣呢?我們單看結果,s1是1234,
s2是5。這是為什么呢?
這就是fgets與gets的不同之處,我們第一個fgets只讀取了1234,將5'\n'放入緩沖區中,當程序運行到第二個fgets時,
它就會直接從緩沖區讀取,直到遇到'\n'結束所以就會有這樣的結果,此時s1是1234'\0',s2是5'\0'.我們應該怎么解決這種問題呢?
我們可以在第二個fgets前加一句fflush(stdin),它是清除緩沖區的作用,大家可以試試,我就不截圖了。
上面我們是用fgets輸入的,現在我們換成gets來輸入,看看結果吧:
說到這里就已經不是簡單的gets與fgets的問題了,這涉及到了我們從鍵盤讀入的數據在內存中是怎么顯示的了,所以我只簡單的說一下。
在內存中s1是這樣排序的
'\0' |
6 |
5 |
4 |
3 |
2 |
1 |
當s2輸入進來的時候會變成:
'\0' |
6 |
5 |
4 |
3 |
'\0' |
f |
e |
d |
c |
b |
a |
所以輸出的時候就會s1輸出f,后遇'\0'結束,s2輸出abcdef,后遇'\0'結束。