程式競程入門:基本輸入與輸出

此篇文章是以 C/C++ 程式語言做為程式競程中,資料的輸入與輸出來示範的。

在程式競賽(APCS、ZeroJudge、UVa Online Judge)中,最重要的第一步就是學會如何讀取輸入資料(Input)以及輸出答案(Output)。


一、C++語言的輸入與輸出

C++ 主要使用 iostream 標頭檔中的 cin 與 cout。在競程中,為了提升 standard I/O 的效能,通常會在 main() 函式開頭加上「I/O 優化」程式碼。

輸出(Output)

C++使用 cout 與運算子 << 將資料顯示在螢幕上。

基本語法

  1. cout << "要輸出的文字內容";
  2. cout << variableName;

範例

  1. #include <iostream>
  2. using namespace std;
  3. int main()
  4. {
  5. int x = 33;
  6. cout << "變數x的數值為:" << x;
  7. return 0;
  8. }

執行結果:

變數x的數值為:33

輸出多個資料

  1. string name = "Tom";
  2. int age = 18;
  3. cout << "姓名:" << name << " 年齡:" << age;
輸出結果:
姓名:Tom 年齡:18

換行

  1. cout << "第一行" << endl;
  2. cout << "第二行" << endl;
  1. cout << "第一行\n";
  2. cout << "第二行\n";

輸入(Input)

C++使用 cin 與運算子 >> 從標準輸入讀取資料。

基本語法

  1. cin >> variableName;

範例

  1. #include <iostream>
  2. using namespace std;
  3. int main()
  4. {
  5. int x;
  6. cin >> x;
  7. cout << "你輸入的是:" << x;
  8. return 0;
  9. }
輸入:
50

輸出:

你輸入的是:50

同時輸入多個變數

  1. int a, b;
  2. cin >> a >> b;
  3. cout << a + b;

輸入:

10 20

輸出:

30

競程小撇步(I/O 優化):

C++ 的 cin/cout 預設會與 C 的 stdin/stdout 同步,這會導致速度變慢。寫競程題時,建議在 main 裡面加上:
  1. ios::sync_with_stdio(false);
  2. cin.tie(nullptr);


二、C語言的輸入與輸出

在某些需要嚴格控制輸出格式(如:保留小數點後幾位、補零)的題目中,使用 C 語言的 printfscanf 會更加直覺且有效率(需引入 <cstdio>)。

輸出:printf()

  • 語法: printf("格式化字串", 變數1, 變數2, ...);
  • 常見格式碼: %d (整數), %lld (長整數 long long), %f (浮點數), %c (字元)
範例:
  1. int x = 33;
  2. printf("變數x的數值為:%d\n", x);

輸入:scanf()

注意: 除了陣列與字串外,其餘基本型態變數前面必須加上 & 取位址符號
  1. int x;
  2. scanf("%d", &x);
範例
  1. #include <stdio.h>
  2. int main()
  3. {
  4. int x;
  5. scanf("%d", &x);
  6. printf("x = %d\n", x);
  7. return 0;
  8. }

三、競程常見輸入模式

競賽題目的輸入格式大致可以分成三種類型。


1. 讀入 N 筆資料

說明: 輸入的第一行會給予一個整數 $N$(或 $T$),代表接下來有 $N$ 筆獨立的測試資料。

常見題目:

輸入格式

5
10
20
30
40
50

第一行的數字 5 表示接下來有 5 筆資料。

C++寫法

  1. #include <iostream>
  2. using namespace std;
  3. int main() {
  4. int t;
  5. if (cin >> t) {
  6. while (t--) {
  7. int r;
  8. cin >> r; // 讀取該組資料的親戚人數
  9. int street[500];
  10. for (int i = 0; i < r; i++) {
  11. cin >> street[i];
  12. }
  13. // [解題邏輯:計算中位數與距離總和]
  14. }
  15. }
  16. return 0;
  17. }


競程觀念

當題目寫著:

  • There are N test cases.
  • The first line contains an integer N.

通常就是使用 for 迴圈讀取資料。


2. 讀至檔案結束(EOF)

說明: 題目沒有告知總共有幾組資料,要求程式必須一直讀取,直到測資檔結束(End of File)為止。

常見題目:

輸入格式

10 12
20 30
100 50

不知道總共有幾筆資料。

C++寫法

  1. // 【C++ 寫法】利用 cin 讀取成功與否作為判斷條件
  2. #include <iostream>
  3. #include <cmath>
  4. using namespace std;
  5. int main() {
  6. long long hashmat, enemy;
  7. while (cin >> hashmat >> enemy) {
  8. cout << abs(hashmat - enemy) << "\n";
  9. }
  10. return 0;
  11. }

為什麼可以這樣寫?

while (cin >> hashmat >> enemy)

表示:

  • 成功讀到資料 → 繼續執行
  • 已經沒有資料 → 迴圈結束

這種方式稱為:

EOF(End Of File)讀取法

是 UVa 題目最常見的輸入方式之一。

補充C寫法:

  1. // 【C 語言寫法】判斷 scanf 的回傳值是否不等於 EOF
  2. #include <stdio.h>
  3. #include <stdlib.h>
  4. int main() {
  5. long long hashmat, enemy;
  6. while (scanf("%lld %lld", &hashmat, &enemy) != EOF) {
  7. printf("%lld\n", llabs(hashmat - enemy));
  8. }
  9. return 0;
  10. }



3. 讀至數字 0 結束

說明: 程式會持續讀入資料,直到滿足特定條件(例如輸入為 0,或多個變數皆為 0)時,才主動結束程式。

常見題目:

輸入格式

123 456
555 555
123 594
0 0

當出現:

0 0

表示資料結束。

C++寫法

  1. // 【C++ 寫法】
  2. #include <iostream>
  3. using namespace std;
  4. int main() {
  5. int a, b;
  6. while(true)
  7. {
  8. cin >> a >> b;
  9. if(a == 0 && b == 0)
  10. break;
  11. cout << a + b << endl;
  12. }
  13. return 0;
  14. }

C++簡潔寫法

  1. // 【C++ 寫法】
  2. #include <iostream>
  3. using namespace std;
  4. int main() {
  5. unsigned int n1, n2;
  6. // 當讀入成功,且 n1 與 n2 不完全為 0 時繼續執行
  7. while (cin >> n1 >> n2 && (n1 != 0 || n2 != 0)) {
  8. // [解題邏輯:計算進位次數]
  9. }
  10. return 0;
  11. }


四、競賽常見輸入模板

單一資料

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

建議練習順序

  1. ZeroJudge a001:熟悉 cincout 的基本使用。
  2. UVa 1000:練習最基本的兩數輸入與輸出。
  3. UVa 10055:練習使用 while(cin >> a >> b) 讀取直到 EOF。
  4. UVa 10035:練習以特定條件(0 0)結束輸入。
  5. 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.

留言

這個網誌中的熱門文章