B. C 語言的輸入輸出:scanf 與 printf
C 的輸入輸出函式 scanf 與 printf(住在 <cstdio>,用 bits/stdc++.h 的人已全包)在 C++ 裡完全可用。很多前輩的程式碼、部分舊題本與 APCS 考古題的參考程式都是 C 風格——看懂它們是這一節的目標;平常寫題,cin、cout 仍是本書的預設。
¶printf:格式字串+佔位符
printf 唸作 print formatted——按照格式輸出。第一個參數是格式字串,裡面的 % 開頭記號是佔位符,依序被後面的參數填入:
int n = 21;
printf("%d\n", n * 2); // %d 的位置填入 42
換行沒有 endl,直接在字串裡寫 '\n'。常用佔位符一張表:
| 型態 | scanf 讀入 | printf 輸出 |
|---|---|---|
int |
%d |
%d |
long long |
%lld |
%lld |
char |
%c |
%c |
C 字串(char 陣列) |
%s(不加 &) |
%s |
double |
%lf(l 不能少!) |
%f(%lf 也可以) |
小數位數控制是 printf 的招牌絕活:%.3f 就是「小數點後 3 位」——9.3 要兩個工具接力的事,它一格搞定:
printf("%.3f\n", x); // C 風格
cout << fixed << setprecision(3) << x; // 9.3 的等價寫法
¶scanf:那個 & 是 11.2 的取址
scanf 唸作 scan formatted——按照格式讀入。格式字串跟 printf 同一套,但變數前面要加 &:
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
long long big;
double x;
scanf("%d %lld %lf", &n, &big, &x); // 讀入:變數前面要加 &
printf("%d\n", n * 2);
printf("%lld\n", big + 1);
printf("%.3f\n", x);
return 0;
}
執行結果(輸入 21 1000000000000000000 2.71828):
42
1000000000000000001
2.718
為什麼要 &?因為 scanf 是 C 的函式,而 C 沒有參考(12.3 的參考是 C++ 才加進來的)——函式想把讀到的值放進外面的變數,唯一的辦法是 11.2 那招:把變數的記憶體位置交給它。&n 正是 11.2 的取址運算子——你給 scanf 的不是 n,是「值要放去哪」的門牌號碼。
這也解釋了表格裡的例外:讀 C 字串不用 &——8.6 說過,陣列名稱本身就代表開頭位置,門牌號碼已經是現成的:
char s[105];
scanf("%s", s); // s 本身就是位址,不加 &
printf("hi, %s!\n", s); // 輸入 anna,印出 hi, anna!
最後一個常見疑問:cin、cout 跟 scanf、printf 可以混用嗎?預設可以——C++ 為了讓兩家人和平共處,內建了同步機制,輸出順序保證正確。但「同步」兩個字是有代價的,那正是 12.10〈讓 cin、cout 變快〉的主題:關掉同步之後,兩家就不能再混用了。
動手試試看:把上冊最早期的某題(讀幾個整數、印一個結果那種)用 scanf/printf 重寫一遍提交。體驗過後你就有資格選邊站:cin 派還是 printf 派——只有小數位數輸出,記得 printf 派偶爾真的比較香。