gets和fgets函數的區別


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'結束。

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM