1. 前言
在學習C語言的過程中,處理使用者輸入的「標準輸入」是不可避免的重要功能。正確理解並安全地使用標準輸入,可以大幅提升程式的通用性與可靠性。
本文將從基礎到進階,系統性地解說C語言中的標準輸入。為了讓初學者也能輕鬆理解,內容會搭配範例程式碼,請務必將其應用到您自己的程式開發中。
標準輸入的重要性
標準輸入是程式從外部接收資料的基本機制。例如,常見的使用場景包括:
- 使用者輸入數字進行計算的應用程式
- 透過字串進行搜尋的功能
- 根據命令列指令動態執行的程式
在這些情況下,正確處理標準輸入能夠建立高效又安全的程式。
本文將學到的內容
本文將涵蓋以下主題:
- 標準輸入的基本原理與在C語言中的實作方法
scanf
與fgets
等函式的使用方式- 安全且可靠的標準輸入實作方式
- 進階的資料處理技巧
- 常見問題與解決方法
適合的讀者
- 第一次學習C語言的初學者
- 對標準輸入用法沒有信心的程式設計師
- 想實現安全且高效輸入處理的人
2. 什麼是標準輸入
在C語言中,標準輸入是程式接收外部資料的基本機制。它屬於「標準輸入輸出」的一部分,通常透過終端機或命令列由使用者提供資料。本節將解釋標準輸入的基本概念與角色。
標準輸入的定義
標準輸入(Standard Input,stdin
)指的是程式用來接收外部資料的資料流。在C語言中,可以透過 stdio.h
標頭檔輕鬆操作標準輸入。
- 資料通常由鍵盤輸入。
- 輸入的資料會在程式中處理,並輸出到標準輸出。
標準輸入輸出的機制
C語言內建以下三種標準資料流:
- 標準輸入(stdin):用來接收外部資料。
- 標準輸出(stdout):用來輸出程式結果。
- 標準錯誤輸出(stderr):用來輸出錯誤訊息。
實際範例
以下範例示範如何使用標準輸入讀取數字,並將結果輸出到標準輸出。
#include <stdio.h>
int main() {
int number;
printf("請輸入一個數字: ");
scanf("%d", &number); // 從標準輸入讀取整數
printf("您輸入的數字是: %d\n", number); // 輸出到標準輸出
return 0;
}
3. C語言中的標準輸入基礎
在C語言中,為了從使用者取得輸入,有多種函式可用。其中最基本的是 scanf
和 fgets
。本節將透過具體範例,說明這些函式的使用方式與特性。
scanf
函式的使用方法
scanf
是透過格式指定子解析輸入資料並存入變數的函式。
基本語法
int scanf(const char *format, ...);
format
:用來指定資料格式的字串。...
:儲存輸入資料的變數位址。
常用的格式指定子
指定子 | 說明 | 範例 |
---|---|---|
%d | 整數 | 42 |
%f | 浮點數 | 3.14 |
%c | 單一字元 | A |
%s | 字串 | Hello |
使用範例
#include <stdio.h>
int main() {
int age;
printf("請輸入年齡: ");
scanf("%d", &age); // 讀取整數
printf("您輸入的年齡是: %d\n", age);
return 0;
}
注意事項
- 若輸入格式不正確,可能會導致錯誤。
- 為避免緩衝區溢位,務必限制輸入大小(例如使用
%s
時)。
fgets
函式的使用方法
fgets
用於逐行讀取字串,相較於 scanf
更安全。
基本語法
char *fgets(char *str, int n, FILE *stream);
str
:用來存放輸入的字元陣列。n
:最多可讀取的字元數(陣列大小)。stream
:輸入來源(通常為stdin
)。
使用範例
#include <stdio.h>
int main() {
char name[50];
printf("請輸入姓名: ");
fgets(name, 50, stdin); // 最多讀取49個字元
printf("您輸入的姓名是: %s", name);
return 0;
}
注意事項
- 若輸入超過緩衝區大小,超出的資料會被截斷。
- 若包含換行符號,需手動刪除。
刪除換行字元的方法
name[strcspn(name, "\n")] = '\0';
scanf
與 fgets
的比較
特性 | scanf | fgets |
---|---|---|
用途 | 依格式讀取數字或字串 | 逐行讀取字串 |
安全性 | 可能有緩衝區溢位風險 | 可限制讀取大小 |
靈活性 | 可使用格式指定 | 可完整取得輸入字串 |
該使用哪一個?
- 使用
scanf
的情況:需要直接讀取數字或特定格式資料。 - 使用
fgets
的情況:重視安全性,或需要處理長字串、複雜輸入。
4. 安全的標準輸入實作
在C語言中處理標準輸入時,確保安全性非常重要。不當的輸入處理可能導致緩衝區溢位或未定義行為,進而降低程式的可靠性。本節將透過實例,解說如何安全地實作標準輸入。
防止緩衝區溢位
scanf
雖然方便,但若未限制輸入大小,可能發生緩衝區溢位。解決方法是使用格式指定子限制輸入長度。
限制輸入大小的範例
#include <stdio.h>
int main() {
char input[10];
printf("請輸入最多9個字元: ");
scanf("%9s", input); // 最多讀取9個字元
printf("您輸入的字串是: %s\n", input);
return 0;
}
重點
- 使用
%9s
等方式限制輸入大小,避免超過陣列空間。
使用 fgets
來提升安全性
fgets
可指定讀取字數,因此能降低緩衝區溢位風險,特別適合處理長字串或逐行輸入。
fgets
實作範例
#include <stdio.h>
#include <string.h>
int main() {
char buffer[20];
printf("請輸入字串: ");
fgets(buffer, sizeof(buffer), stdin); // 最多讀取19個字元
buffer[strcspn(buffer, "\n")] = '\0'; // 移除換行
printf("您輸入的字串是: %s\n", buffer);
return 0;
}
重點
- 使用
sizeof(buffer)
自動設定緩衝區大小。 - 透過
strcspn
移除換行字元。
驗證輸入資料
為確保安全,必須驗證使用者輸入。例如,當需要整數時,先以字串接收再轉換,並檢查是否正確。
數字輸入驗證範例
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main() {
char buffer[20];
long number;
char *endptr;
printf("請輸入整數: ");
fgets(buffer, sizeof(buffer), stdin);
errno = 0; // 重設錯誤狀態
number = strtol(buffer, &endptr, 10); // 轉換成整數
if (errno != 0 || endptr == buffer || *endptr != '\0') {
printf("請輸入有效的整數。\n");
} else {
printf("您輸入的整數是: %ld\n", number);
}
return 0;
}
重點
strtol
可檢測轉換時的錯誤。- 搭配
errno
和endptr
驗證輸入是否正確。
錯誤處理的最佳實踐
在標準輸入中實作錯誤處理,能有效提升程式可靠性。
錯誤檢查範例
#include <stdio.h>
int main() {
int value;
printf("請輸入整數: ");
if (scanf("%d", &value) != 1) { // 若輸入失敗
printf("輸入無效。\n");
return 1; // 錯誤結束
}
printf("您輸入的整數是: %d\n", value);
return 0;
}
重點
- 檢查
scanf
的回傳值,若輸入格式錯誤,執行錯誤處理。
安全輸入處理總結
- 使用
scanf
時,必須限制輸入大小。 - 處理長字串或逐行輸入時,建議使用
fgets
。 - 不要完全信任使用者輸入,務必進行驗證與錯誤處理。
5. 標準輸入的進階處理
在掌握標準輸入的基本用法後,進一步學習進階處理方法,可以讓程式應對更複雜的輸入資料與情境。本章將解說如何高效處理多筆輸入、換行與空白字元,以及動態資料。
一次輸入多筆資料
標準輸入常需要一次讀取多筆資料,以下將介紹以空白或逗號分隔資料的處理方式。
處理以空白分隔的輸入範例
#include <stdio.h>
int main() {
int numbers[5];
printf("請輸入5個整數(以空白分隔): ");
for (int i = 0; i < 5; i++) {
scanf("%d", &numbers[i]); // 以空白分隔輸入
}
printf("您輸入的整數為: ");
for (int i = 0; i < 5; i++) {
printf("%d ", numbers[i]);
}
printf("\n");
return 0;
}
處理以逗號分隔的輸入範例
#include <stdio.h>
int main() {
int numbers[3];
printf("請輸入3個整數(以逗號分隔): ");
scanf("%d,%d,%d", &numbers[0], &numbers[1], &numbers[2]); // 以逗號分隔輸入
printf("您輸入的整數為: %d, %d, %d\n", numbers[0], numbers[1], numbers[2]);
return 0;
}
處理包含換行與空白的輸入
標準輸入有時會混雜換行符與空白符,以下示範正確處理方式。
處理換行字元範例
可利用 fgets
讀取,再移除換行字元。
#include <stdio.h>
#include <string.h>
int main() {
char input[100];
printf("請輸入一段文字: ");
fgets(input, sizeof(input), stdin);
input[strcspn(input, "\n")] = '\0'; // 移除換行
printf("您輸入的文字為: %s\n", input);
return 0;
}
處理多行輸入
多行輸入在文字分析或資料處理中十分常見。
逐行處理輸入範例
#include <stdio.h>
int main() {
char line[100];
printf("請輸入多行文字(結束請按 Ctrl+D):\n");
while (fgets(line, sizeof(line), stdin) != NULL) {
printf("讀取到的行: %s", line);
}
return 0;
}
處理動態輸入資料
若輸入筆數不固定,需要彈性處理。以下範例示範計算多筆整數的總和。
動態資料處理範例
#include <stdio.h>
int main() {
int number, sum = 0;
printf("請輸入整數(結束請按 Ctrl+D):\n");
while (scanf("%d", &number) == 1) {
sum += number;
}
printf("輸入整數的總和為: %d\n", sum);
return 0;
}
小結
透過進階的標準輸入技巧,可以更靈活地處理多筆資料、換行與動態輸入。熟悉這些技巧後,能設計出更強大的程式。
6. 常見問題與解決方法
在C語言中處理標準輸入時,初學者經常會遇到一些問題。本章整理了常見的錯誤與解決方法,幫助您建立更可靠的程式。
scanf
的問題與解決方法
問題1: 輸入跳過問題
使用 scanf
讀取字串或整數時,換行或空白字元可能會影響下一次輸入。
範例
#include <stdio.h>
int main() {
int number;
char letter;
printf("請輸入整數: ");
scanf("%d", &number);
printf("請輸入字元: ");
scanf("%c", &letter); // 會讀取到殘留的換行字元
printf("輸入的整數: %d, 字元: %c\n", number, letter);
return 0;
}
解決方法
在 scanf
格式前加入空白字元,忽略多餘的換行。
scanf(" %c", &letter); // 空白可忽略多餘換行
問題2: 緩衝區溢位
當使用 scanf
讀取字串時,若輸入超過陣列大小,可能造成程式崩潰。
範例
char input[10];
scanf("%s", input); // 若輸入超過10字元,會溢位
解決方法
在格式指定子中限制輸入大小。
scanf("%9s", input); // 最多讀取9字元
或改用更安全的 fgets
。
fgets
的問題與解決方法
問題1: 含有換行字元
fgets
會保留輸入最後的換行符,可能導致字串比較失敗。
範例
char input[20];
fgets(input, sizeof(input), stdin);
if (strcmp(input, "yes") == 0) {
printf("輸入為 yes。\n");
}
此時 input
內容實際為 "yes\n"
,比較會失敗。
解決方法
移除換行字元。
input[strcspn(input, "\n")] = '\0';
處理輸入錯誤的方法
問題1: 無效輸入
當程式期望數字,但使用者輸入字串時,程式可能異常。
範例
int number;
scanf("%d", &number); // 若輸入文字會導致錯誤
解決方法
檢查輸入是否合法。
if (scanf("%d", &number) != 1) {
printf("輸入無效。\n");
while (getchar() != '\n'); // 清除輸入緩衝區
}
多行輸入的問題
問題: scanf
與 fgets
混用
在同一程式中混用 scanf
與 fgets
,常會出現意料之外的行為。
原因
scanf
不會移除換行符,因此下一個 fgets
會直接讀取換行。
解決方法
在 scanf
之後清空緩衝區。
while (getchar() != '\n');
小結
標準輸入在C語言中容易出現各種問題,但只要理解原因並妥善處理,就能建立更安全與高效的程式。特別是要理解 scanf
與 fgets
的差異,並依需求選擇合適的方法。

7. 使用標準輸入的應用程式範例
本章將介紹一些使用標準輸入的實際程式範例,從基礎到進階,幫助您透過實際代碼理解如何應用。
範例1: 計算數字總和與平均值
此程式會從標準輸入讀取多個整數,並計算總和與平均。
#include <stdio.h>
int main() {
int numbers[100];
int count = 0, sum = 0;
float average;
printf("請輸入多個整數(以空白分隔,結束請按 Ctrl+D):\n");
while (scanf("%d", &numbers[count]) == 1) {
sum += numbers[count];
count++;
}
if (count > 0) {
average = (float)sum / count;
printf("總和: %d, 平均: %.2f\n", sum, average);
} else {
printf("未輸入任何數字。\n");
}
return 0;
}
範例2: 回文判斷程式
判斷輸入的字串是否為回文(正反讀都一樣)。
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
bool isPalindrome(char str[]) {
int start = 0;
int end = strlen(str) - 1;
while (start < end) {
if (str[start] != str[end]) {
return false;
}
start++;
end--;
}
return true;
}
int main() {
char input[100];
printf("請輸入字串: ");
fgets(input, sizeof(input), stdin);
// 移除換行字元
input[strcspn(input, "\n")] = '\0';
if (isPalindrome(input)) {
printf("輸入的字串是回文。\n");
} else {
printf("輸入的字串不是回文。\n");
}
return 0;
}
範例3: 處理CSV格式資料
此程式會讀取CSV(逗號分隔值)資料,並逐一處理各欄位。
#include <stdio.h>
#include <string.h>
int main() {
char input[200];
char *token;
printf("請輸入CSV格式資料: ");
fgets(input, sizeof(input), stdin);
// 移除換行字元
input[strcspn(input, "\n")] = '\0';
// 以逗號分割
token = strtok(input, ",");
while (token != NULL) {
printf("值: %s\n", token);
token = strtok(NULL, ",");
}
return 0;
}
範例4: 互動式輸入程式
此程式會多次接收使用者輸入,並依內容進行處理。
#include <stdio.h>
#include <string.h>
int main() {
char input[50];
printf("輸入 'exit' 可結束程式。\n");
while (1) {
printf("請輸入指令: ");
fgets(input, sizeof(input), stdin);
// 移除換行字元
input[strcspn(input, "\n")] = '\0';
if (strcmp(input, "exit") == 0) {
printf("程式結束。\n");
break;
} else {
printf("輸入的指令: %s\n", input);
}
}
return 0;
}
小結
透過這些應用程式範例,您可以更好地理解標準輸入的用法。請嘗試將其應用到您的專案中,設計出符合需求的互動式程式。
8. 總結
本文從基礎到進階,全面解說了C語言中標準輸入的使用方式。希望透過這些內容,您能理解標準輸入的運作機制、安全處理方法,以及實際應用範例。以下簡單回顧重點。
再次確認標準輸入的重要性
- 標準輸入是程式從外部接收資料並進行動態操作的基本功能。
- 在C語言中,可以使用
scanf
或fgets
讀取數字或字串。
安全且高效輸入處理的要點
- 防止緩衝區溢位
- 在
scanf
中限制輸入大小(例如%9s
)。 - 處理長字串或逐行輸入時,優先使用
fgets
。
- 驗證輸入資料
- 使用
strtol
或strtod
等函式,檢查輸入是否合法。 - 若有不正確輸入,需進行適當的錯誤處理。
- 進階處理
- 處理多筆輸入或換行字元時,需特別注意正確性與安全性。
下一步建議
在熟悉標準輸入後,建議進一步學習以下內容,以提升程式設計能力:
- 標準輸出與錯誤輸出:掌握如何輸出錯誤訊息與記錄日誌。
- 檔案操作:結合標準輸入與檔案讀寫,製作更進階的程式。
- 實作練習:嘗試修改本文範例,設計適合自己專案的輸入處理。
給讀者的話
標準輸入是C語言程式設計的基礎,但同時也蘊含許多細節與進階技巧。希望本文能幫助您在實作中養成「安全且高效處理輸入」的習慣。無論疑問多小,都應一步步解決,這將成為您程式學習旅程中的重要基石。