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 單維彰