scanf 函數
- 1. scanf 函數基礎
- 1.1 函數原型與頭文件
- 1.2 格式化輸入的基本概念
- 2.1 常見格式說明符
- 整數格式說明符
- 浮點數格式說明符
- 字符和字符串格式說明符
- 其他格式說明符
- 2.2 格式說明符的高級用法
- 寬度修飾符
- 精度修飾符
- 跳過輸入
- 字段寬度
- 組合修飾符
- 對齊修飾符
- 實際應用示例
- 3.2 精度控制
- 浮點數精度
- 字符串精度
- 動態精度
- 實際應用示例
- 4.1 返回值的含義
- 4.2 返回值的應用場景
- 4.2.1 輸入校驗
- 4.2.2 循環讀取輸入
- 4.2.3 動態調整輸入邏輯
- 4.2.4 調試與日志記錄
- 5.1 格式化字符串漏洞
- 格式化字符串漏洞的成因
- 格式化字符串漏洞的利用
- 格式化字符串漏洞的實例
- 5.2 安全使用建議
- 1. 避免用戶可控的格式化字符串
- 2. 確保格式說明符與參數匹配
- 3. 使用安全的格式化函數
- 4. 檢查 `scanf` 的返回值
- 5. 避免使用 `%n` 格式說明符
- 6. 使用編譯器的安全檢查功能
- 6.1 fscanf
- 使用場景
- 返回值
- 6.2 sscanf
- 使用場景
- 返回值
- 7.1 日常編程中的使用場景
- 1. 輸入用戶數據
- 2. 讀取配置文件
- 3. 輸入表格數據
- 4. 輸入帶條件的數據
- 5. 輸入帶時間戳的數據
- 7.2 復雜格式化輸入示例
- 1. 輸入多行格式化數據
- 2. 動態格式化輸入
- 3. 輸入帶有顏色的文本
- 4. 輸入帶有條件的文本
- 5. 輸入帶有時間戳的日志信息
1. scanf 函數基礎
1.1 函數原型與頭文件
scanf
函數是 C 語言中用于格式化輸入的標準函數,其函數原型定義在頭文件 <stdio.h>
中。具體原型如下:
int scanf(const char *format, ...);
const char *format
:格式控制字符串,用于指定輸入的格式。它由普通字符和格式說明符組成。普通字符用于匹配輸入中的相同字符,而格式說明符則用于指定后續參數的輸入格式。...
:表示可變參數列表,這些參數是用于存儲輸入數據的變量的地址。每個格式說明符對應一個參數,參數的類型必須與格式說明符匹配。
在使用 scanf
函數時,必須包含頭文件 <stdio.h>
,否則編譯器將無法識別該函數。
1.2 格式化輸入的基本概念
scanf
函數通過格式控制字符串來實現靈活的輸入。格式控制字符串中的格式說明符以 %
開頭,后跟一個或多個字符,用于指定輸入數據的類型和格式。以下是一些常見的格式說明符及其含義:
格式說明符 | 含義 |
---|---|
%d 或 %i | 輸入有符號十進制整數。例如:scanf("%d", &var); 輸入 123 ,var 的值為 123 。 |
%u | 輸入無符號十進制整數。例如:scanf("%u", &var); 輸入 456 ,var 的值為 456 。 |
%f | 輸入浮點數。例如:scanf("%f", &var); 輸入 3.14 ,var 的值為 3.14 。 |
%c | 輸入單個字符。例如:scanf("%c", &var); 輸入 A ,var 的值為 A 。 |
%s | 輸入字符串。例如:scanf("%s", str); 輸入 Hello ,str 的值為 "Hello" 。 |
%p | 輸入指針地址。例如:scanf("%p", &ptr); 輸入地址,ptr 的值為該地址。 |
%% | 輸入一個百分號 % 。例如:scanf("%%", &var); 輸入 % ,var 的值為 % 。 |
格式說明符還可以包含一些可選的修飾符,用于控制輸入的寬度、精度、對齊方式等。以下是一些常見的修飾符及其用法:
-
寬度修飾符:指定輸入的最大寬度。對于字符串,指定最大輸入字符數。例如:
char str[10]; scanf("%9s", str); // 最多讀取 9 個字符
-
精度修飾符:對于浮點數,指定小數點后的位數。例如:
float var; scanf("%f", &var); // 默認讀取浮點數
-
對齊修飾符:
-
用于左對齊,+
用于強制輸出正負號,空格用于在正數前輸出空格。例如:int var; scanf("%d", &var); // 默認讀取整數
通過合理使用格式說明符和修飾符,scanf
函數可以實現靈活多樣的格式化輸入,滿足各種編程需求。# 2. 格式說明符詳解
2.1 常見格式說明符
scanf
函數的格式說明符是實現格式化輸入的核心,以下是一些常見的格式說明符及其詳細用法:
整數格式說明符
-
%d
或%i
:用于輸入有符號十進制整數。這是最常用的整數格式說明符,適用于正負整數。int var; scanf("%d", &var); // 輸入 123,var 的值為 123
-
%u
:用于輸入無符號十進制整數。它適用于非負整數,輸入時不會顯示負號。unsigned int var; scanf("%u", &var); // 輸入 456,var 的值為 456
-
%o
:用于輸入無符號八進制整數。輸入時需要以八進制形式輸入,不顯示前綴0
。int var; scanf("%o", &var); // 輸入 377,var 的值為 255
-
%x
或%X
:用于輸入無符號十六進制整數。%x
輸入小寫字母,%X
輸入大寫字母。int var; scanf("%x", &var); // 輸入 ff,var 的值為 255 scanf("%X", &var); // 輸入 FF,var 的值為 255
浮點數格式說明符
-
%f
:用于輸入十進制浮點數。默認情況下,scanf
會讀取小數點和數字,直到遇到非數字字符為止。float var; scanf("%f", &var); // 輸入 3.14159,var 的值為 3.14159
-
%e
或%E
:用于輸入科學計數法表示的浮點數。%e
輸入小寫字母e
,%E
輸入大寫字母E
。float var; scanf("%e", &var); // 輸入 3.14159e+00,var 的值為 3.14159 scanf("%E", &var); // 輸入 3.14159E+00,var 的值為 3.14159
字符和字符串格式說明符
-
%c
:用于輸入單個字符。輸入時只讀取一個字符,包括空格和換行符。char var; scanf("%c", &var); // 輸入 A,var 的值為 'A'
-
%s
:用于輸入字符串。輸入時會讀取連續的字符,直到遇到空格、制表符或換行符為止。char str[10]; scanf("%s", str); // 輸入 Hello,str 的值為 "Hello"
其他格式說明符
-
%p
:用于輸入指針地址。輸入時需要輸入一個有效的指針地址。int *ptr; scanf("%p", &ptr); // 輸入地址,ptr 的值為該地址
-
%%
:用于輸入一個百分號%
。輸入時需要輸入一個%
符號。char var; scanf("%%", &var); // 輸入 %,var 的值為 '%'
2.2 格式說明符的高級用法
格式說明符還可以結合多種修飾符來實現更復雜的格式化輸入,以下是一些高級用法:
寬度修飾符
寬度修飾符用于指定輸入的最大寬度。對于字符串,指定最大輸入字符數。可以通過以下方式指定寬度:
-
固定寬度:直接指定一個整數。
char str[10]; scanf("%9s", str); // 最多讀取 9 個字符
-
動態寬度:使用
*
表示寬度由后續參數指定。int width = 9; scanf("%*s", &width, str); // 最多讀取 9 個字符
精度修飾符
精度修飾符用于控制輸入的精度,對于浮點數和字符串有不同的含義:
-
浮點數:指定小數點后的位數。
float var; scanf("%f", &var); // 默認讀取浮點數
-
字符串:指定最大輸入長度。
char str[10]; scanf("%.9s", str); // 最多讀取 9 個字符
跳過輸入
使用 *
修飾符可以跳過某些輸入項,不將其存儲到變量中。例如:
int a, b;
scanf("%d %*d %d", &a, &b); // 輸入 1 2 3,a 的值為 1,b 的值為 3
字段寬度
字段寬度修飾符用于指定輸入字段的寬度。對于字符串,指定最大輸入字符數。對于數字,指定最大輸入數字的位數。例如:
int a;
scanf("%3d", &a); // 輸入 1234,a 的值為 123
組合修飾符
可以將多種修飾符組合使用,以實現復雜的格式化需求:
char str[10];
scanf("%-9.5s", str); // 最多讀取 9 個字符,字符串的最大長度為 5
```# 3. 輸入控制與格式化
## 3.1 寬度與對齊`scanf` 函數通過寬度修飾符和對齊修飾符來控制輸入的寬度和