程式競程入門:基本輸入與輸出
此篇文章是以 C/C++ 程式語言做為程式競程中,資料的輸入與輸出來示範的。
在程式競賽(APCS、ZeroJudge、UVa Online Judge)中,最重要的第一步就是學會如何讀取輸入資料(Input)以及輸出答案(Output)。
一、C++語言的輸入與輸出
C++ 主要使用 iostream 標頭檔中的 cin 與 cout。在競程中,為了提升 standard I/O 的效能,通常會在 main() 函式開頭加上「I/O 優化」程式碼。輸出(Output)
C++使用 cout 與運算子 << 將資料顯示在螢幕上。
基本語法
- cout << "要輸出的文字內容";
- cout << variableName;
範例
- #include <iostream>
- using namespace std;
- int main()
- {
- int x = 33;
- cout << "變數x的數值為:" << x;
- return 0;
- }
執行結果:
變數x的數值為:33
輸出多個資料
- string name = "Tom";
- int age = 18;
- cout << "姓名:" << name << " 年齡:" << age;
輸出結果:
姓名:Tom 年齡:18
換行
- cout << "第一行" << endl;
- cout << "第二行" << endl;
或
- cout << "第一行\n";
- cout << "第二行\n";
輸入(Input)
C++使用 cin 與運算子 >> 從標準輸入讀取資料。
基本語法
- cin >> variableName;
範例
- #include <iostream>
- using namespace std;
- int main()
- {
- int x;
- cin >> x;
- cout << "你輸入的是:" << x;
- return 0;
- }
輸入:
50
輸出:
你輸入的是:50
同時輸入多個變數
- int a, b;
- cin >> a >> b;
- cout << a + b;
輸入:
10 20
輸出:
30競程小撇步(I/O 優化):
C++ 的cin/cout預設會與 C 的stdin/stdout同步,這會導致速度變慢。寫競程題時,建議在main裡面加上:
- ios::sync_with_stdio(false);
- cin.tie(nullptr);
二、C語言的輸入與輸出
在某些需要嚴格控制輸出格式(如:保留小數點後幾位、補零)的題目中,使用 C 語言的 printf 與 scanf 會更加直覺且有效率(需引入 <cstdio>)。
輸出:printf()
- 語法: printf("格式化字串", 變數1, 變數2, ...);
- 常見格式碼: %d (整數), %lld (長整數 long long), %f (浮點數), %c (字元)
- int x = 33;
- printf("變數x的數值為:%d\n", x);
輸入:scanf()
& 取位址符號。
- int x;
- scanf("%d", &x);
範例
- #include <stdio.h>
- int main()
- {
- int x;
- scanf("%d", &x);
- printf("x = %d\n", x);
- return 0;
- }
三、競程常見輸入模式
競賽題目的輸入格式大致可以分成三種類型。
1. 讀入 N 筆資料
說明: 輸入的第一行會給予一個整數 $N$(或 $T$),代表接下來有 $N$ 筆獨立的測試資料。
常見題目:
- Vito's Family (UVA 10041) (https://zerojudge.tw/ShowProblem?problemid=a737)
輸入格式
5
10
20
30
40
50
第一行的數字 5 表示接下來有 5 筆資料。
C++寫法
- #include <iostream>
- using namespace std;
- int main() {
- int t;
- if (cin >> t) {
- while (t--) {
- int r;
- cin >> r; // 讀取該組資料的親戚人數
- int street[500];
- for (int i = 0; i < r; i++) {
- cin >> street[i];
- }
- // [解題邏輯:計算中位數與距離總和]
- }
- }
- return 0;
- }
競程觀念
當題目寫著:
- There are N test cases.
- The first line contains an integer N.
通常就是使用 for 迴圈讀取資料。
2. 讀至檔案結束(EOF)
說明: 題目沒有告知總共有幾組資料,要求程式必須一直讀取,直到測資檔結束(End of File)為止。
常見題目:
- Hashmat the brave warrior (UVA 10055) https://zerojudge.tw/ShowProblem?problemid=a012
輸入格式
10 12
20 30
100 50
不知道總共有幾筆資料。
C++寫法
- // 【C++ 寫法】利用 cin 讀取成功與否作為判斷條件
- #include <iostream>
- #include <cmath>
- using namespace std;
- int main() {
- long long hashmat, enemy;
- while (cin >> hashmat >> enemy) {
- cout << abs(hashmat - enemy) << "\n";
- }
- return 0;
- }
為什麼可以這樣寫?
while (cin >> hashmat >> enemy)
表示:
- 成功讀到資料 → 繼續執行
- 已經沒有資料 → 迴圈結束
這種方式稱為:
EOF(End Of File)讀取法
是 UVa 題目最常見的輸入方式之一。
補充C寫法:
- // 【C 語言寫法】判斷 scanf 的回傳值是否不等於 EOF
- #include <stdio.h>
- #include <stdlib.h>
- int main() {
- long long hashmat, enemy;
- while (scanf("%lld %lld", &hashmat, &enemy) != EOF) {
- printf("%lld\n", llabs(hashmat - enemy));
- }
- return 0;
- }
3. 讀至數字 0 結束
說明: 程式會持續讀入資料,直到滿足特定條件(例如輸入為 0,或多個變數皆為 0)時,才主動結束程式。
常見題目:
- Primary Arithmetic (UVA 10035) https://zerojudge.tw/ShowProblem?problemid=c014
輸入格式
123 456
555 555
123 594
0 0
當出現:
0 0
表示資料結束。
C++寫法
- // 【C++ 寫法】
- #include <iostream>
- using namespace std;
- int main() {
- int a, b;
- while(true)
- {
- cin >> a >> b;
- if(a == 0 && b == 0)
- break;
- cout << a + b << endl;
- }
- return 0;
- }
C++簡潔寫法
- // 【C++ 寫法】
- #include <iostream>
- using namespace std;
- int main() {
- unsigned int n1, n2;
- // 當讀入成功,且 n1 與 n2 不完全為 0 時繼續執行
- while (cin >> n1 >> n2 && (n1 != 0 || n2 != 0)) {
- // [解題邏輯:計算進位次數]
- }
- return 0;
- }
四、競賽常見輸入模板
單一資料
int x;
cin >> x;
多個資料
int a, b;
cin >> a >> b;
N筆資料
int n;
cin >> n;
for(int i = 0; i < n; i++)
{
// 處理資料
}
EOF
while(cin >> x)
{
// 處理資料
}
EOF(多個變數)
while(cin >> a >> b)
{
// 處理資料
}
特殊終止條件
while(true)
{
cin >> x;
if(x == 0)
break;
}
五、競程新手必學重點
| 題目類型 | 寫法 |
|---|---|
| 單筆輸入 | cin >> x; |
| 多筆輸入 | cin >> a >> b; |
| N筆資料 | for(int i=0;i<n;i++) |
| 不知道幾筆資料 | while(cin >> x) |
| EOF輸入 | while(cin >> x) |
| 讀到0結束 | while(true) + break |
| 多組測資 | while(T--) |
六、競程入門練習題
| 題目名稱 | 超連結 |
|---|---|
| 【A. Two Sum】 | ZeroJudge a001:兩數相加 (A + B Problem) |
| 【A+B Problem】 | UVa 1000:A + B Problem |
| 【Hashmat the Brave Warrior】 | UVa 10055:Hashmat the Brave Warrior |
| 【Primary Arithmetic】 | UVa 10035:Primary Arithmetic |
| 【Vito's Family】 | UVa 10041:Vito's Family |
建議練習順序
-
ZeroJudge a001:熟悉
cin與cout的基本使用。 - UVa 1000:練習最基本的兩數輸入與輸出。
-
UVa 10055:練習使用
while(cin >> a >> b)讀取直到 EOF。 -
UVa 10035:練習以特定條件(
0 0)結束輸入。 - UVa 10041:練習先讀入測試資料筆數(N),再使用迴圈處理多組測資。
這五題涵蓋了競程最常見的四種輸入模式:
- 單筆輸入
- 多個變數輸入
- EOF(End of File)輸入
- N 筆測資輸入與特殊終止條件輸入
完成這五題後,即可建立 APCS、ZeroJudge 與 UVa 入門題所需的基本輸入輸出能力。掌握 cin、cout、for、while、EOF 之後,便已具備解決大部分競程入門題目的基礎能力。
若您覺得文章寫得不錯,請點選文章上的廣告,來支持小編,謝謝。
If you like this post, please click the ads on the blog or buy me a coffee. Thank you very much.
留言