1. 前言
在 C 語言中,當解析字串並提取特定資料時,有一個便利的函式 sscanf
。本文將從 sscanf
的基本用法到應用與注意事項,詳細說明。 學習 C 語言時,常會遇到「想處理使用者輸入的資料」或「想從字串中取出數值」等情況。了解 scanf
與 sscanf
的差異,並適當運用 sscanf
,即可編寫更安全且彈性的程式。 本文將說明以下重點。sscanf
函式的基本sscanf
的使用方法(附範例程式碼)sscanf
的應用技巧- 常見錯誤與其對策
sscanf
安全使用的注意事項
那麼,首先來看看 sscanf
的基本功能。
2. C語言 sscanf 函式是什麼?
2.1 sscanf 概述
sscanf
是 C 語言標準函式庫中提供的函式,用來解析字串並轉換成指定的資料型別。雖然與 scanf
類似,但 sscanf
的不同之處在於 不是從標準輸入,而是從字串取得資料。2.2 sscanf 的基本語法
sscanf
的基本格式如下。int sscanf(const char *str, const char *format, ...);
str
:要解析的字串format
:格式指定子(定義資料型別)...
:存放轉換後值的變數(指標)
作為返回值,會回傳成功轉換的輸入項目數量。失敗時則回傳 0
或 EOF
(-1
)。2.3 與 scanf 的差異
以下以表格整理 sscanf
與 scanf
的差異。項目 | sscanf | scanf |
---|
輸入來源 | 字串 | 標準輸入(鍵盤) |
用途 | 解析既有字串 | 接收使用者輸入 |
彈性 | 高(可指定格式) | 低(輸入受限) |
安全性 | 安全性較低(有緩衝區溢位風險) | 輸入控制較困難 |
錯誤處理 | 可利用返回值適當處理 | 因為是標準輸入,需要即時處理 |
如上所述,sscanf
適合解析既有字串,使用方式與標準輸入不同。3. sscanf 的基本使用方法(附範例程式碼)
sscanf
可用於從字串取得整數、浮點數、字串等值。此處說明基本用法,並搭配範例程式碼介紹。3.1 sscanf 的基本語法
使用 sscanf
時的基本語法如下。int sscanf(const char *str, const char *format, ...);
str
:要解析的字串format
:格式指定子(%d、%f、%s 等)...
:存放資料的變數指標
回傳值為成功轉換的輸入項目數量。若發生錯誤,會回傳 0
或 EOF
(-1
)。3.2 從字串取得整數
讓我們看看使用 sscanf
從字串中取得整數的方法。#include <stdio.h>
int main() {
char str[] = "123";
int num;
sscanf(str, "%d", &num);
printf("取得的數值: %dn", num);
return 0;
}
輸出結果取得的數值: 123
如同這樣,指定 "%d"
後,即可從字串 "123"
取得整數 123
。3.3 從字串取得多個值
使用 sscanf
可以從單一字串取得多個值。#include <stdio.h>
int main() {
char str[] = "100 200";
int a, b;
sscanf(str, "%d %d", &a, &b);
printf("a = %d, b = %dn", a, b);
return 0;
}
輸出結果a = 100, b = 200
在解析以空格分隔的資料時很有用。3.4 同時取得字串與數值
接下來介紹使用 sscanf
解析字串與數值兩者的方法。#include <stdio.h>
int main() {
char str[] = "name: John age: 30";
char name[50];
int age;
sscanf(str, "name: %s age: %d", name, &age);
printf("姓名: %s, 年齡: %dn", name, age);
return 0;
}
輸出結果姓名: John, 年齡: 30
如同這樣,結合 %s
與 %d
即可同時取得字串與數值。3.5 sscanf
回傳值的活用
檢查 sscanf
的回傳值即可判斷解析是否成功。#include <stdio.h>
int main() {
char str[] = "42";
int num;
int result = sscanf(str, "%d", &num);
if (result == 1) {
printf("取得成功: %dn", num);
} else {
printf("取得失敗n");
}
return 0;
}
輸出結果取得成功: 42
回傳值 1
表示成功取得 1 個值。失敗時會是 0
或 EOF
,因此可進行適當的錯誤處理。3.6 小結
sscanf
可從字串取得整數、浮點數、字串等。- 也能同時取得多筆資料。
- 確認
sscanf
的回傳值即可進行錯誤處理。
4. sscanf 的應用技巧
sscanf
除了取得基本的數值和字串外,還可用於更高階的資料解析。在此,我們將詳細說明其應用方式,包括 格式指定子的活用、特定資料的抽取、逗號分隔資料的解析、不同資料型別的處理、錯誤處理。4.1 靈活運用格式指定子
sscanf
的格式指定子若能善加利用,將能更彈性地解析資料。特別是,透過以下的 指定子的組合,即可處理不同的資料型別。指定子 | 說明 |
---|
%d | 取得整數 |
%f | 取得浮點數 |
%s | 取得字串(空白分隔) |
%c | 取得單一字元 |
%[A-Za-z] | 取得特定字元範圍的字串 |
範例:取得含空格的字串
一般的 %s
會以空格分隔取得字串,但使用 %[^ ]
則可 取得至換行符號的全部字元。#include <stdio.h>
int main() {
char str[] = "Hello World!";
char result[50];
sscanf(str, "%[^
]", result);
printf("取得的字串: %sn", result);
return 0;
}
輸出結果取得的字串: Hello World!
這樣使用 %[^ ]
,即可正確取得含空格的字串。4.2 抽取特定資料
sscanf
也適合從字串中 抽取特定資料。範例:日期解析
例如,從像 “2025-02-01” 這樣的日期資料中,可分別取得年、月、日。#include <stdio.h>
int main() {
char date[] = "2025-02-01";
int year, month, day;
sscanf(date, "%d-%d-%d", &year, &month, &day);
printf("年: %d, 月: %d, 日: %dn", year, month, day);
return 0;
}
輸出結果年: 2025, 月: 2, 日: 1
4.3 解析逗號分隔資料
在處理 CSV(Comma-Separated Values)資料時,使用 sscanf
會很方便。範例:CSV 資料解析
#include <stdio.h>
int main() {
char input[] = "Apple,120,2.5";
char product[20];
int quantity;
float price;
sscanf(input, "%[^,],%d,%f", product, &quantity, &price);
printf("商品名稱: %s, 數量: %d, 價格: %.2fn", product, quantity, price);
return 0;
}
輸出結果商品名稱: Apple, 數量: 120, 價格: 2.50
4.4 解析不同資料型別
介紹使用 sscanf
處理數值與字串混合資料的方法。範例:ID、名稱、分數的解析
#include <stdio.h>
int main() {
char input[] = "ID123 Name:Taro Score:95";
char id[10], name[20];
int score;
sscanf(input, "ID%s Name:%s Score:%d", id, name, &score);
printf("ID: %s, 名稱: %s, 分數: %dn", id, name, score);
return 0;
}
輸出結果ID: 123, 名稱: Taro, 分數: 95
4.5 應用錯誤處理
利用 sscanf
的返回值進行錯誤檢查是很重要的。範例:執行輸入檢查
#include <stdio.h>
int main() {
char str[] = "42";
int num;
int result = sscanf(str, "%d", &num);
if (result == 1) {
printf("取得成功: %dn", num);
} else {
printf("取得失敗n");
}
return 0;
}
輸出結果取得成功: 42
這樣透過檢查 sscanf
的返回值,即可適當處理輸入錯誤。4.6 小結
sscanf
的格式指定子若能活用,將能彈性地解析資料。- 可抽取特定資料(日期時間或逗號分隔資料等)。
- 透過活用
sscanf
的返回值,可進行錯誤檢查,實現安全的處理。
5. 使用 sscanf 時的注意事項與安全風險
sscanf
是便利的函式,但若使用不當,可能會導致 緩衝區溢位 或 未預期的行為。特別是處理從外部取得的資料時,需要適當的錯誤處理與驗證。 在此說明使用 sscanf
時應注意的要點,以及避免安全風險的方法。5.1 緩衝區溢位的風險
使用 sscanf
時,若未考慮適當的緩衝區大小,可能會導致 緩衝區溢位。危險的程式碼範例
#include <stdio.h>
int main() {
char name[10];
char str[] = "VeryLongUserName";
sscanf(str, "%s", name);
printf("名稱: %sn", name);
return 0;
}
問題點name
的大小是 10 位元組,但 "VeryLongUserName"
是 16 位元組。- 緩衝區溢位發生,可能導致記憶體破壞。
安全的程式碼範例
#include <stdio.h>
int main() {
char name[10];
char str[] = "VeryLongUserName";
sscanf(str, "%9s", name); // 指定 9,因為 9 個字元加上結尾的 '\0'
printf("名稱: %sn", name);
return 0;
}
使用 %9s
可限制最多讀取 9 個字元,防止記憶體破壞。5.2 對於非預期輸入的錯誤檢查
如果不檢查 sscanf
的返回值,當傳入錯誤資料時,程式可能異常運作。有問題的程式碼
#include <stdio.h>
int main() {
char str[] = "abc";
int num;
sscanf(str, "%d", &num); // 失敗但未檢查錯誤
printf("取得的數值: %dn", num);
return 0;
}
此時,num
的值不確定(垃圾值),可能導致未預期的行為。安全的程式碼
#include <stdio.h>
int main() {
char str[] = "abc";
int num;
if (sscanf(str, "%d", &num) == 1) {
printf("取得的數值: %dn", num);
} else {
printf("錯誤: 無法取得數值。n");
}
return 0;
}
輸出結果錯誤: 無法取得數值。
這樣即使有錯誤的輸入,也能安全地繼續處理。5.3 輸入資料的驗證
當非預期的資料進入時,程式的運作可能不穩定。因此,在使用 sscanf
前,先對資料進行 驗證(validation) 是重要的。範例:使用者輸入的驗證
#include <stdio.h>
#include <ctype.h>
int is_number(const char *str) {
while (*str) {
if (!isdigit(*str)) return 0; // 若包含非數字則錯誤
str++;
}
return 1;
}
int main() {
char input[] = "42a"; // 作為數值不正確
int num;
if (is_number(input)) {
sscanf(input, "%d", &num);
printf("取得的數值: %dn", num);
} else {
printf("錯誤: 輸入的數值無效。n");
}
return 0;
}
輸出結果錯誤: 輸入的數值無效。
這樣事先檢查資料是否為數值,即可實現安全的處理。5.4 fgets
結合的安全字串處理
可以使用 fgets
取代 sscanf
,安全地處理輸入。安全的字串取得
#include <stdio.h>
int main() {
char buffer[100];
printf("請輸入字串: ");
fgets(buffer, sizeof(buffer), stdin);
printf("取得的字串: %s", buffer);
return 0;
}
fgets
能防止緩衝區溢位,同時取得使用者輸入,與 sscanf
結合使用可提升安全性。5.5 小結
- 為防止緩衝區溢位,於格式指定子設定最大長度。
- 檢查返回值,以確認資料取得是否成功。
- 事先驗證輸入資料,防止處理不正當資料。
- 善用
fgets
等,執行安全的輸入處理。

6. 常見錯誤與其對策
sscanf
是便利的函式,但若使用不當會導致意外的行為。本節將詳細說明初學者容易犯的錯誤與其對策。6.1 指標誤用導致的段錯誤 (Segmentation Fault)
錯誤程式碼
#include <stdio.h>
int main() {
char *str = "123 456"; // 字串常量不可修改
int a, b;
sscanf(str, "%d %d", &a, &b);
printf("a = %d, b = %dn", a, b);
return 0;
}
此程式碼使用 sscanf
取得整數,但 str
指向字串常量("123 456"
),存放於不可修改的記憶體區域。 解決方案: 使用 char str[]
形式。修正程式碼
#include <stdio.h>
int main() {
char str[] = "123 456"; // 定義為陣列(可寫入)
int a, b;
sscanf(str, "%d %d", &a, &b);
printf("a = %d, b = %dn", a, b);
return 0;
}
6.2 格式指定子錯誤
錯誤程式碼
#include <stdio.h>
int main() {
char str[] = "123.45";
int num;
sscanf(str, "%d", &num); // 嘗試以整數解析
printf("取得的數值: %dn", num);
return 0;
}
此程式碼嘗試將 "123.45"
以整數 %d
解析。因小數點的關係,無法正確取得值。 解決方案: 使用 %f
。修正程式碼
#include <stdio.h>
int main() {
char str[] = "123.45";
float num;
sscanf(str, "%f", &num);
printf("取得的數值: %.2fn", num);
return 0;
}
輸出取得的數值: 123.45
6.3 未進行錯誤檢查
錯誤程式碼
#include <stdio.h>
int main() {
char str[] = "abc";
int num;
sscanf(str, "%d", &num); // 字串 "abc" 無法轉換為數值
printf("取得的數值: %dn", num);
return 0;
}
"abc"
無法轉換為整數,num
的值會變成垃圾值,導致意外的行為。 解決方案: 檢查 sscanf
的返回值。修正程式碼
#include <stdio.h>
int main() {
char str[] = "abc";
int num;
if (sscanf(str, "%d", &num) == 1) {
printf("取得的數值: %dn", num);
} else {
printf("錯誤: 無法取得數值。n");
}
return 0;
}
輸出錯誤: 無法取得數值。
6.4 含空格的字串無法正確取得
錯誤程式碼
#include <stdio.h>
int main() {
char str[] = "Hello World";
char word1[10], word2[10];
sscanf(str, "%s %s", word1, word2);
printf("字詞1: %s, 字詞2: %sn", word1, word2);
return 0;
}
%s
預設以空白作為分隔,因此會把 Hello World
的 "World"
放入另一個變數。 解決方案: 使用 %[^ ]
取得直到換行的字串。修正程式碼
#include <stdio.h>
int main() {
char str[] = "Hello World";
char sentence[50];
sscanf(str, "%[^
]", sentence);
printf("取得的字串: %sn", sentence);
return 0;
}
輸出取得的字串: Hello World
6.5 數值超出範圍
錯誤程式碼
#include <stdio.h>
int main() {
char str[] = "999999999999";
int num;
sscanf(str, "%d", &num);
printf("取得的數值: %dn", num);
return 0;
}
若超過 int
型的最大值(通常為 2147483647
),會發生溢位,導致意外的行為。 解決方案: 使用 long long
。修正程式碼
#include <stdio.h>
int main() {
char str[] = "999999999999";
long long num;
sscanf(str, "%lld", &num);
printf("取得的數值: %lldn", num);
return 0;
}
輸出取得的數值: 999999999999
6.6 總結
- 避免指標誤用,並確保適當的記憶體。
- 防止格式指定子錯誤,請依資料型別使用相應的指定子。
- 務必進行錯誤檢查,以防止意外的行為。
- 取得含空格的字串時,使用
%[^ ]
。 - 若超過
int
範圍,請使用 long long
。 - 檢查以避免傳遞
NULL
指標。
7. FAQ(常見問題)
sscanf
在使用時,開發者常有的疑問將詳細說明。從基本用法到進階,並以具體範例回答。7.1 sscanf 與 scanf 的差異是?
scanf
與 sscanf
兩者皆是根據格式指定子取得資料的函式,但 輸入來源不同。項目 | sscanf | scanf |
---|
輸入來源 | 字串 (char[] ) | 標準輸入 (stdin ) |
用途 | 解析現有字串 | 取得使用者輸入 |
彈性 | 高(資料轉換容易) | 低(即時輸入) |
錯誤處理 | 容易 | 不易 |
範例:scanf
的使用
#include <stdio.h>
int main() {
int num;
printf("請輸入數值: ");
scanf("%d", &num);
printf("輸入的數值: %dn", num);
return 0;
}
從標準輸入(鍵盤)取得值。範例:sscanf
的使用
#include <stdio.h>
int main() {
char str[] = "123";
int num;
sscanf(str, "%d", &num);
printf("解析的數值: %dn", num);
return 0;
}
將現有字串 "123"
轉換為數值。7.2 如何使用 sscanf 取得含空格的字串?
預設的 %s
會將 空格視為分隔符。若要取得含空格的字串,請使用 %[^ ]
。範例:取得含空格的字串
#include <stdio.h>
int main() {
char str[] = "Hello World!";
char result[50];
sscanf(str, "%[^
]", result);
printf("取得的字串: %sn", result);
return 0;
}
輸出取得的字串: Hello World!
7.3 sscanf 的返回值意義是?
sscanf
的返回值會回傳 成功取得的資料筆數。若取得失敗則回傳 0
或 EOF
(-1)。範例:檢查返回值
#include <stdio.h>
int main() {
char str[] = "42";
int num;
int result = sscanf(str, "%d", &num);
if (result == 1) {
printf("取得成功: %dn", num);
} else {
printf("取得失敗n");
}
return 0;
}
輸出取得成功: 42
7.4 如何使用 sscanf 同時取得數值與字串?
sscanf
可同時解析數值與字串。範例:ID、名稱、分數的解析
#include <stdio.h>
int main() {
char input[] = "ID123 Name:Taro Score:95";
char id[10], name[20];
int score;
sscanf(input, "ID%s Name:%s Score:%d", id, name, &score);
printf("ID: %s, 名稱: %s, 分數: %dn", id, name, score);
return 0;
}
輸出ID: 123, 名稱: Taro, 分數: 95
7.5 如何進行 sscanf 的錯誤處理?
若不進行錯誤檢查,可能會有不預期的資料進入。 請使用 sscanf
的返回值進行檢查。範例:輸入檢查
#include <stdio.h>
int main() {
char str[] = "abc"; // 作為數值無效的字串
int num;
if (sscanf(str, "%d", &num) == 1) {
printf("取得的數值: %dn", num);
} else {
printf("錯誤: 無法取得數值。n");
}
return 0;
}
輸出錯誤: 無法取得數值。
7.6 是否應該改用 strtok
?
視情況而定,strtok
可能更適合。用途 | sscanf | strtok |
---|
字串解析 | 使用格式指定子 | 指定分隔字元 |
取得方式 | 依照格式取得值 | 將字串切割為標記 |
彈性 | 高(可取得整數、字串、小數點等) | 適合連續的標記處理 |
範例:使用 strtok
進行字串分割
#include <stdio.h>
#include <string.h>
int main() {
char input[] = "apple,banana,orange";
char *token = strtok(input, ",");
while (token != NULL) {
printf("水果: %sn", token);
token = strtok(NULL, ",");
}
return 0;
}
輸出水果: apple
水果: banana
水果: orange
7.7 總結
scanf
與 sscanf
的差異 → sscanf
用於字串解析- 取得含空格的字串 → 使用
%[^ ]
- 錯誤檢查 → 確認
sscanf
的返回值 - 同時取得數值與字串 → 正確指定格式
- 替代方案 → 判斷何時使用
strtok
- 安全的使用方式 → 指定緩衝區大小·錯誤檢查·搭配
fgets
8. 總結
在本文中,我們詳細說明了 C 語言的 sscanf
函數,從基本用法到應用、注意事項、常見錯誤及其對策、FAQ。最後,彙總 重要要點,並介紹安全且有效使用 sscanf
的最佳實踐。8.1 本文的總結
✅ sscanf
的基本
sscanf
是 從字串解析資料 的函式。- 與
scanf
不同,處理字串而非標準輸入 是其特點。 - 基本語法:
int sscanf(const char *str, const char *format, ...);
✅ sscanf
的使用方法
sscanf("123", "%d", &num);
sscanf("100 200", "%d %d", &a, &b);
sscanf("ID123 Name:Taro Score:95", "ID%s Name:%s Score:%d", id, name, &score);
sscanf("Hello World!", "%[^
]", buffer);
8.2 使用 sscanf
時的注意事項
錯誤的使用方式 | 問題點 | 解決方案 |
---|
%s 未指定長度 | 緩衝區溢位 風險 | 以 %9s 等方式指定長度 |
未進行錯誤檢查 | 處理未預期的資料 之可能性 | 務必確認 sscanf 的返回值 |
NULL 指標 | 段錯誤 (Segmentation Fault) | 確認指標不為 NULL |
%d 取得 999999999999 | 整數溢位 | 使用 long long 型並指定 %lld |
8.3 sscanf
的最佳實踐
✅ 1. 指定緩衝區大小
char name[10];
sscanf(str, "%9s", name); // 取得最多 9 個字元(+ '\0')
→ 防止緩衝區溢位!✅ 2. 進行錯誤檢查
if (sscanf(str, "%d", &num) != 1) {
printf("錯誤: 無法取得數值。n");
}
→ 確認資料取得是否成功!✅ 3. 結合使用 fgets
char buffer[100];
fgets(buffer, sizeof(buffer), stdin);
→ 確保使用者輸入時的安全性!✅ 4. 解析字串時,分別使用 strtok
與 sscanf
char *token = strtok(str, ",");
while (token != NULL) {
printf("%sn", token);
token = strtok(NULL, ",");
}
→ sscanf
用於格式指定,strtok
用於切割 token!8.4 為了活用本文
📌 實際撰寫程式碼並測試 📌 學習格式指定子的變化 📌 具備撰寫安全程式碼的意識8.5 總結
🔹 code> 是 從字串解析資料 的便利函式
🔹 從 基本用法 到 應用技巧 都能廣泛活用
🔹 了解 注意事項並適當進行錯誤處理 是重要的
🔹 透過指定緩衝區大小及結合使用 fgets
提升安全性
正確使用 sscanf
,實踐安全的 C 語言程式設計!9. 參考文獻