Skip to content

前幾篇介紹了很多基本的運算,其中輸出都是使用 printf 來顯示運算的結果,來確認這段程式的特性,本篇會深入介紹輸入輸出的使用。

在開始介紹前,推薦使用 c referencec plus plus 來查詢內建函數的功能與參數。

輸出

在 C 中,輸出通常是使用 stdio.hprintf 來輸出,但偶爾會使用 putchar

在開始說明輸出之前,要先了解基本的 ASCII 表示,其中 \n 是換行、 \t 是 tab。

這邊先舉一個簡單的例子

c
printf("hello world %s\n", name);
printf("3+4=%d\n", 7);

他的功能就是印出 hello world 和名字,前面 "hello world %s\n" 稱作 format string(打印形式),後方則是 Arguments(變數部分)。

Format String

必須用""包住(一個字串),這部分會指定印出來的字串會是什麼樣子,其中最關鍵的部分就是 %,有很多的參數可以調整印出來的樣式,請參見 printf

變數型別Specifier
int%d
long%ld
long long%lld
float%f or %g
double%lf
long double%Lf
string%s
char%c

因為 % 符號通常用來識別要傳遞的參數,因此如果要顯示 % 的話需要用 %%

進階

這部分包含了一些比較進階的使用,

  • 打印長度: %10d 印出十格,靠右對齊
    • 靠左: %-10d
    • 長度不定: printf("%*d", len, num); 印出 len 格
  • 正負號對齊
    • 補正號: %+d 優先套用
    • 補空格: % d

輸入

輸入則是使用 scanf,他會從 緩衝區 拿到資料並放到變數中,構成與 printf 類似,都是由 format string 與 Arguments 組成,主要的不同是在 Arguements 部分。

緩衝區的概念

初學者常以為按下鍵盤,程式就立刻讀取。但實際上,你的輸入會先被丟到一個「緩衝區(Buffer)」,像一條傳送帶。scanf 就像一個坐在傳送帶末端的食客,依照你給的格式(如 %d)來拿取食物。

自然斷點:空格、換行與 Tab

scanf 在讀取數字或字串時,會自動跳過空白 (Space)、換行 (\n) 或 Tab。這些對它來說就像是食物之間的「隔板」。

EOF: End of File

當程式處理大量資料(例如從檔案讀取)時,它需要知道什麼時候「沒東西可讀了」。這就是 EOF (End Of File)。

  • 在 Windows 控制台,按下 Ctrl + Z 代表 EOF。

  • 在 Linux/macOS,按下 Ctrl + D 代表 EOF。

scanf 其實是有回傳值的。它會告訴你它成功讀取了幾個變數。如果讀到盡頭,它會回傳 EOF(通常數值是 -1),常用於做題。

c
int num;
while (scanf("%d", &num) != EOF) {
    printf("%d\n", num);
}

Format String

輸入部分與輸出部分不太一樣,幾乎整個字串都是由 %d%s 之類組成,參數對應可以參考上面那張表。

新增部分: string 可以使用 %[] 讀取

Arguments

在 scanf 的參數部分,與 printf 有一個核心的不同:你必須傳遞變數的「地址」。

在 C 語言中,我們使用 & (取位址運算子) 來取得變數在記憶體中的位置。

c
int age;
scanf("%d", &age); // 正確:告訴 scanf 把數字放進 age 的地址裡
scanf("%d", age);  // 錯誤:這會導致程式崩潰,因為把 age 的「數值」當成了「地址」
為什麼要加 &?

這是 C 語言中 「傳值 (Pass by Value)」 的特性決定的。 當你呼叫一個函數時,C 預設會把數值「影印」一份丟進去。如果你不給 &age(地址),scanf 拿到的只是一份複製品,它改不動你原本的變數。給了地址,它才能直接去記憶體「當場修改」原件。

例外: 之後我們會學到「字串 (String)」,字串本身代表的就是地址,所以讀取字串時不需要加 &。