你真的懂C的格式化I/O嗎?(下)
阿新 • • 發佈:2021-01-30
系列文章目錄
文章目錄
回顧
上一篇文章主要是總結了C語言下格式化輸出相關的內容,這一節來總結一些格式化輸入相關的內容。
格式化輸入
下面是ANSI C定義的標準的輸入函式族:
#include <stdio.h>
int scanf(const char *format, ...);
int sscanf(const char *string, char *format, ...);
int fscanf(FILE *stream, const char* fromat, ...);
下面以scanf為例來說明一下格式化輸入的用法,sscanf、fscanf的使用方式類似。
int scanf(const char *format, ...);
scanf函式從標準輸入中讀取字元序列,並按照format中的格式說明對字元序列進行解釋,並把結果儲存到其餘 的引數中。關於scanf需要注意的幾點如下:
- 所有的引數都是指標型別。
- 當scanf掃描完format格式串時,或者碰到某些輸入無法與格式控制說明匹配的情況時,該函式終止,並返回,返回值為成功匹配並賦值的輸入項的個數,所以函式的返回值可以用來確定已匹配的輸入項的個數。
- 如果達到檔案結尾,該函式將返回EOF。
- 返回0表示下一個輸入字元與格式串中的第一個格式說明不匹配。
- 下一次呼叫scanf函式將從上一次轉換的最後一個字元的下一個字元開始繼續搜尋。
格式說明format用於控制輸入的轉換,其包括如下幾部分:
[空格或製表符][普通字元(除%之外)]%[*][最大寬度]轉換字元
其中,[]中的內容為可選欄位。
字元 | 含義 |
---|---|
空格或製表符 | 這些字元在處理過程中將被忽略 |
普通字元(不包括%) | 用於匹配輸入流中下一個非空白字元 |
轉換說明 | 依次由一個%,一個可選的賦值禁止符*、一個可選的數值(指定最大欄位寬度) |
h或l或L | 指定目標物件的寬度 |
轉換字元 | 轉換字元結尾,下表會介紹 |
這裡需要注意的是,如果轉換說明中存在*,則跳過該輸入欄位,不進行賦值。
輸入欄位定義為一個不包括空白符的字串,其邊界定義為到下一個空白符或達到指定的欄位寬度。這說明scanf函式將越過行邊界讀取輸入,因為換行符也是空白符。(空白符包括空格符、橫向製表符、換行符、回車符、縱向製表符以及換頁符
轉換字元定義如下:
字元 | 輸入資料 | 引數型別 |
---|---|---|
d | 十進位制整數 | int* 型別 |
i | 整數 | int*整型,可以是八進位制(以0開頭)或十六進位制(以0x或0X開頭) |
o | 八進位制整數(可以以0開頭也可以不以0開頭) | int*型別 |
u | 無符號十進位制整數 | unsigned int*型別 |
x | 十六進位制整數(可以以0x或0X開頭,也可以不以其開頭) | int *型別 |
c | 字元 | char *型別 |
s | 字串(不加引號) | char *型別,指向一個足以存放該字串(包括字串末尾’\0’)的字元陣列。字元創的末尾將自動新增一個結束符‘\0’ |
e/f/g | 浮點數,它可以包括正負號(可選)、小數點(可選)、指數部分(可選) | float *型別 |
% | 不進行任何賦值操作 |
轉換字元d、i、o、u及x的前面可以加上字元h或l。字首h表明引數表的相應引數是一個指向short型別而非int型別的指標,字首l表明引數表的相應引數是一個指向long型別的指標。類似地,轉換說明e、f和g的前面也可以加上字首l,它表明引數表的相應引數是一個指向double型別的而非float型別的指標。
下面通過幾個示例說明一下如何進行格式化輸入操作。
- 示例一:使用scanf解析格式如24/01/2021日期
int day, year;
char monthname[20];
scanf("%d/%2s/%d", &day, monthname, &year);//注意:%2s表示字串的寬度為2
printf("day:%d, month:%s, year:%d.\n", day, monthname, year);
輸入:24/01/2021
輸出:day:24, month:01, year:2021
- 示例二:使用sscanf解析格式如24/01/2021日期
int day, year;
char monthname[20];
char *date = "24/01/2021";
sscanf(date, "%d/%2s/%d", &day, monthname, &year);
printf("day:%d, month:%s, year:%d.\n", day, monthname, year);
輸出:day:24, month:01, year:2021
參考資料:《C程式設計語言》,一本每個C程式設計師都要精讀的書,向偉大的祖師爺 Brian W.Kernighan & Dennis M.Ritchie致敬!
sscanf與scanf的format格式類似,不同的地方是sscanf資料來源是個字串。
更多優質內容,請移步公眾號奔跑的碼仔