printf() 是一個能夠處理「字串」這種隱喻資料型態的函式。 只要依照「以零字元結束」這個要領,使用者也可以自行設計處理字串的函式。 在以下範例中,我們設計一個函式 getline(), 從標準輸入裝置 (stdin) 中讀取一列文字。
/* 從 stdin 讀取字元,到第一個 '\n' (含) 為止,放進 s[] 序列,
返回讀進 s[] 的字元個數。但 s[] 的維度是 N,故一列的長度上限是 N-1 個字元
(因為還要保留一個位置給 '\0')。
若超過此限,截斷。
*/
getline(char s[], int N) {
int c, i;
for (i=0; i<N-1 && (c=getchar()) != EOF && c != '\n'; ++i)
s[i] = c;
if (c == '\n') {
s[i] = c;
++i;
}
s[i] = '\0';
return i;
}
檢視 getline() 的設計邏輯。 函式中的 for 迴圈在三種情形停止:
注意,那三個用 && 合成的邏輯語句,它們的順序很重要。 因為,只要第一個是 FALSE,後面的 getchar() 就不會執行。 如果把 getchar() 寫在第一個,那麼可能會漏掉一個字元。
注意,根據以上的邏輯,當 getline() 讀到一個空行的時候, 返回的值是 1。因此即使空行也有一個 linefeed 字元。 由於 UNIX 純文字檔的 EOF 之前必定有一個 linefeed, 所以,當讀到 EOF 的時候,返回的值是 0。 因此,當原函式發現返回值是 0 的時候,就知道檔案結束了。
現在,我們寫一個簡單的 main() 來測試 getline() 函式。 我們設定一列不能超過 1024 個字元 (含 LF 但不含零字元)。 這個 main() 函式印出每列不含 LF 的字元數, 並印出那一列的字元。
#include <stdio.h>
#define BUFSIZE 1025
int getline(char[], int);
/* 輸出每一列的字元數 (不含 LF),以及那一列本身 (cline.c) */
main() {
char buf[BUFSIZE]; /* 新讀入字元的暫存佇列 (buffer) */
int n;
while ((n = getline(buf, BUFSIZE)) > 0)
printf("%6d: %s", n-1, buf);
return 0;
}
getline(char s[], int N) {
int c, i;
for (i=0; i<N-1 && (c=getchar()) != EOF && c != '\n'; ++i)
s[i] = c;
if (c == '\n') {
s[i] = c;
++i;
}
s[i] = '\0';
return i;
}
習題
main() {
char buf[BUFSIZE];
int n;
while ((n = getline(buf, BUFSIZE)) > 0)
printf("%s", buf);
return 0;
}
餵給它以下輸入檔案for (i=0; (c=getchar()) != EOF && i<N-1 && c != '\n'; ++i)
0123456789 01234567890123456789 012345678901234567890123456789
注意:此處所有文件均為原著,個別的版權宣告日後會一一公布, 整體版面設計亦尚未完成。但仍請勿抄襲文字與圖片,以免觸犯著作權法。
Created: Apr 4, 2000
Last Revised: Apr 20, 2000, June 10
© Copyright 2000 Wei-Chang Shann 單維彰