Appearance
前幾篇介紹了很多基本的運算,其中輸出都是使用 printf 來顯示運算的結果,來確認這段程式的特性,本篇會深入介紹輸入輸出的使用。
在開始介紹前,推薦使用 c reference 或 c plus plus 來查詢內建函數的功能與參數。
輸出
在 C 中,輸出通常是使用 stdio.h 的 printf 來輸出,但偶爾會使用 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)」,字串本身代表的就是地址,所以讀取字串時不需要加 &。