語法書 / AA 競程語法書 下冊 / 附錄 / B. C 語言的輸入輸出:scanf 與 printf

B. C 語言的輸入輸出:scanf 與 printf

C 的輸入輸出函式 scanfprintf(住在 <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 %lfl 不能少!) %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 派偶爾真的比較香。