聲明:本文系原創,轉載請注明出處。
C語言中的幾種格式化輸入/輸出方式:
1. 函數功能:
- scanf(); //從標准輸入設備(控制台鍵盤)輸入
- sscanf(); //從字符串緩沖區輸入與指定格式相符的數據
- fscanf(); //從文件輸入
- printf(); // 從標准輸出設備(顯示器)輸出
- sprintf(); //向字符串緩沖區輸出與指定格式相符的數據
- fprintf(); //向文件輸出
2. 函數原型:
//格式化輸入函數 int scanf ( const char * format, ... ); int sscanf ( const char * s, const char * format, ...); int fscanf ( FILE * stream, const char * format, ... ); //格式化輸出函數 int printf ( const char * format, ... ); int sprintf ( char * str, const char * format, ... ); int fprintf ( FILE * stream, const char * format, ... );
3. 函數參數:
以上各函數無非是 從/向 緩沖區/文件(包括標准輸入/輸出)對數據進行格式化輸入/輸出。
關鍵參數是 const char * format , format 是一個字符串字面常量,其中含有若干格式描述符(format specifier),輸入/輸出函數的作用就是把給定的數據按照格式描述符(format specifier)規定的格式進行輸入/輸出。
一個格式描述符(format specifier)具有如下范式:
%[flags][width][.precision][length]specifier
下面以 printf 為例進行說明:
1)specifier
其中必不可少的是 specifier ,因為它規定了數據的類型和對其進行的解釋, specifier 的取值及含義如下:
specifier | Output | Example |
---|---|---|
d or i | 有符號十進制整數 | 392 |
u | 無符號十進制整數 | 7235 |
o | 無符號八進制整數 | 610 |
x | 無符號十六進制整數 | 7fa |
X | 無符號十六進制整數(大寫形式) | 7FA |
f | 十進制浮點數,小寫形式 | 392.65 |
F | 十進制浮點數,大寫形式 | 392.65 |
e | 科學記數法,小寫形式 | 3.9265e+2 |
E | 科學記數法,大寫形式 | 3.9265E+2 |
g | %e 和 %f 中的最短表示式 | 392.65 |
G | %E 和 %F 中的最短表示式 | 392.65 |
a | 十六進制浮點數,小寫形式 | -0xc.90fep-2 |
A | 十六進制浮點數,大寫形式 | -0XC.90FEP-2 |
c | 單字符 | a |
s | 字符串 | sample |
p | 指針的地址 | b8000000 |
n | 不輸出任何東西。 與之對應的參數必須是一個指向有符號整型變量的指針; 函數執行的結果是將至今已經寫入的字符數目寫入該指針指向的內存中。 |
|
% | %%將會輸出一個% | % |
specifier 可選的修飾描述符 sub-specifiers 包括: flags 、 width 、 .precision 等。
2)sub-specifiers
flags | description |
---|---|
- | 根據給定的寬度左對齊。默認情況下是右對齊。 |
+ | 對結果強制附加正號+或符號-在前面,即是是正數也要前置+。默認情況下是只有負數前置-。 |
(space) | 如果沒有任何符號位說明,將會在數據前插入一個空格。 |
# | 當描述符是o, x 或 X 時,若值非0,則結果前置0, 0x 或 0X; 當描述符是a, A, e, E, f, F, g 或 G時,若值非0,強制添加十進制小數點至輸出,即使小數點位后沒有其他數字。默認情況下,若小數點位置后無數字,則不予輸出小數點。 |
0 | 當可填充時,用數字0而不是默認的空格填充剩余的空間。 |
width | description |
---|---|
(number) | 最少打印number個字符。 如果待打印數據的寬度比number小,則結果會以空格進行填充。 如果結果的寬度大於number,則按實際寬度打印,而不進行截斷。 |
* | The width is not specified in the format string, but as an additional integer value argument preceding the argument that has to be formatted. |
.precision | description |
---|---|
.number | For integer specifiers (d, i, o, u, x, X): precision specifies the minimum number of digits to be written. If the value to be written is shorter than this number, the result is padded with leading zeros. The value is not truncated even if the result is longer. A precision of 0 means that no character is written for the value 0. For a, A, e, E, f and F specifiers: this is the number of digits to be printed after the decimal point (by default, this is 6). For g and G specifiers: This is the maximum number of significant digits to be printed. For s: this is the maximum number of characters to be printed. By default all characters are printed until the ending null character is encountered. If the period is specified without an explicit value for precision, 0 is assumed. |
.* | The precision is not specified in the format string, but as an additional integer value argument preceding the argument that has to be formatted. |
3)modifiers
length參數可以修改數據的類型長度。
specifiers | |||||||
---|---|---|---|---|---|---|---|
length | d i | u o x X | f F e E g G a A | c | s | p | n |
(none) | int | unsigned int | double | int | char* | void* | int* |
hh | signed char | unsigned char | signed char* | ||||
h | short int | unsigned short int | short int* | ||||
l | long int | unsigned long int | wint_t | wchar_t* | long int* | ||
ll | long long int | unsigned long long int | long long int* | ||||
j | intmax_t | uintmax_t | intmax_t* | ||||
z | size_t | size_t | size_t* | ||||
t | ptrdiff_t | ptrdiff_t | ptrdiff_t* | ||||
L | long double |
說明:hh, ll 同h, l, 但僅對C99有效。
4. 函數返回值
當讀寫成功時,返回被讀寫的字符數;
當讀寫失敗時,返回一個負數。
5. sscanf/scanf正則用法
- scanf族函數會忽略一行開始的空白,直到第一個非空白符出現為止,空白符有:
- space: ' '
- tab: '\t'
- newline: '\n'
- %* :表示空讀一個數據
- %*d:匹配到的整數被過濾掉;
- %*s:匹配到的字符串被過濾掉;
- %*[a] :匹配到的a字符均被過濾掉;
- %*[分隔符]:經常讀取的字符串中有分隔符,可以將分隔符過濾掉。
- %[ ] 的用法:
- %[ ] 表示要讀入一個字符集合 , 如果 [ 后面第一個字符是 ”^” ,則表示反意思。
- [ ] 內的字符串可以是 1 或更多字符組成。
- 空字符集( %[] )是違反規定的,可導致不可預知的結果。 %[^] 也是違反規定的。
- %[] 有很大的功能,但是並不是很常用到,主要因為:
- 許多系統的 scanf 函數都有漏洞. (典型的就是 TC 在輸入浮點型時有時會出錯);
- 用法復雜 , 容易出錯;
編譯器作語法分析時會很困難 , 從而影響目標代碼的質量和執行效率.
- %[a-z] 讀取在 a-z 之間的字符串,如果不在此之間則停止,如:
-
char s[]="hello, my friend” ; // 注意 : , 逗號在不 a-z 之間 sscanf( s, “%[a-z]”, string ) ; // string=hello
-
- %[^a-z] 讀取不在 a-z 之間的字符串,如果碰到 a-z 之間的字符則停止,如:
-
char s[]="HELLOkitty” ;// 注意 : , 逗號在不 a-z 之間 sscanf( s, “%[^a-z]”, string ) ; // string=HELLO
-
- %*[^=] 前面帶 * 號表示不保存變量。跳過符合條件的字符串。
-
char s[]="notepad=1.0.0.1001" ; char szfilename[32] = "" ; int i = sscanf( s, "%*[^=]", szfilename ) ; // szfilename=NULL, 因為沒保存 int i = sscanf( s, "%*[^=]=%s", szfilename ) ; // szfilename=1.0.0.1001
-
- %40c 讀取 40 個字符
- %[^=] 讀取字符串直到碰到 '=' 號, '^' 后面可以帶更多字符 , 如:
-
char s[]="notepad=1.0.0.1001" ; char szname[32] = "" ; char szver[32] = “” ; int i = sscanf( s, "%[^=]", szname ) ; // szname=notepad sscanf( s, "%[^=]=%s", szname , szver ) ; // szname=notepad, szver=1.0.0.1001
-
參考資料
- http://www.cplusplus.com/reference/cstdio/scanf/
- http://www.cplusplus.com/reference/cstdio/printf/
- https://blog.csdn.net/a_Treasure/article/details/82085937
- https://blog.csdn.net/21aspnet/article/details/174326
- https://www.cnblogs.com/mylinux/p/4635510.html
- https://www.jb51.net/article/138506.htm