官术网_书友最值得收藏!

2.5.2 C99

嚴格符合C99的應用程序的兩個選項是用fgets()或getchar()取代gets()。

C標準fgets()函數和gets()擁有相似的行為。fgets()函數接受兩個額外的參數:期望讀入的字符數和輸入流。我們可以通過指定stdin作為輸入流來使fgets()模擬gets()的行為。

例2.9的程序片段中使用fgets()函數從stdin中讀取一行文本。

例2.9 使用fgets()從stdin中讀取


01  char buf[LINE_MAX];
02  int ch;
03  char *p;
04
05  if (fgets(buf, sizeof(buf), stdin)) {
06    /* fgets 
成功,
掃描查找換行符 */
07    p = strchr(buf, '\n');
08    if (p) {
09      *p = '\0';
10    }
11    else {
12      /* 
未找到換行符, 
刷新stdin
到行尾 */
13      while (((ch = getchar()) != '\n')
14            && !feof(stdin)
15            && !ferror(stdin)
16      );
17    }
18  }
19  else {
20    /* fgets 
失敗, 
處理錯誤 */
21  }

與gets()不同,fgets()函數保留換行符,這意味著不能將fgets()作為gets()的直接替代品。

當使用fgets()時,可能只讀取了一行的部分數據,然而,可以確定用戶的輸入是否被截斷了,因為那樣的話,輸入緩沖區內將不會包含一個換行符。

fgets()函數從流中最多讀入比指定數量少1個的字符到一個數組中。如果遇到換行符或者EOF標志,則不會繼續讀取。在最后一個字符讀入數組中后,一個空字符隨即被寫入緩沖區的結尾處。

使用fgets()可以安全地處理太長而不能在目標數組中存儲的輸入行,但出于性能方面的原因,不推薦使用它。如果指定的輸入字符數超過目標緩沖區的長度,fgets()函數也可能導致緩沖區溢出。

在嚴格符合C99標準的應用程序中更換gets()函數的第二個方法是使用getchar()函數。getchar()函數返回stdin指向的輸入流中的下一個字符。如果流在EOF處,則該流的EOF標記就會被設置,且getchar()返回EOF。如果發生讀取錯誤,則該流的錯誤標記就會被設置,且getchar()返回EOF。例2.10中的程序片段使用getchar()函數從stdin中讀取一行文本。

例2.10 使用getchar()從stdin中讀取


01  char buf[BUFSIZ];
02  int ch;
03  int index = 0;
04  int chars_read = 0;
05
06  while (((ch = getchar()) != '\n')
07          && !feof(stdin)
08          && !ferror(stdin))
09  {
10    if (index < BUFSIZ-1) {
11      buf[index++] = (unsigned char)ch;
12    }
13    chars_read++;
14  } /*  while
循環結束 */
15  buf[index] = '\0';  /* 
空終結符 */
16  if (feof(stdin)) {
17    /* 
處理 EOF */
18  }
19  if (ferror(stdin)) {
20    /* 
處理錯誤 */
21  }
22  if (chars_read > index) {
23    /* 
處理截斷 */
24  }

如果在循環結束時,,feof(stdin) ! = 0,則表示循環讀取到文件末尾,而沒有遇到一個換行符。如果在循環結束時,fferror(stdin) ! = 0,則表示循環在遇到一個換行符之前,發生了讀取錯誤。如果在循環結束時,chars_read > index,則表示輸入的字符串已被截斷?!禖安全編碼標準》[Seacord 2008],“FIO 34-C.使用int捕捉字符IO函數的返回值”,在此解決方案中也適用。

如果寫入到沒有設定正確的邊界的緩沖區中,那么使用getchar()函數讀取一行仍然可能導致緩沖區溢出。

一次讀取一個字符在控制行為方面提供了更多的靈活性,而無須額外的性能開銷。下面的測試對于while循環通常是足夠的:


while (( (ch = getchar()) ! = '\n') && ch ! = EOF ) 

參見《C安全編碼標準》[Seacord 2008],“FIO 35-C.在sizeof(int)==sizeof(char)的情況下,用feof()和ferror()檢測文件結束和文件錯誤”,這種情況下,必須用feof()和ferror()來代替上面的語句的寫法。

主站蜘蛛池模板: 蓬安县| 腾冲县| 宁乡县| 冕宁县| 剑川县| 南华县| 龙门县| 南通市| 六安市| 永靖县| 永登县| 尼玛县| 泸溪县| 阜宁县| 巧家县| 昌黎县| 固始县| 新丰县| 靖宇县| 大姚县| 宁城县| 汤阴县| 尼木县| 闻喜县| 拉萨市| 黑山县| 长沙县| 自贡市| 彝良县| 资阳市| 纳雍县| 新河县| 江华| 肇州县| 昆山市| 康平县| 永嘉县| 寿光市| 千阳县| 杂多县| 南投市|