本篇博文內容摘自《UNIX環境高級編程》(第二版),僅作個人學習記錄所用。關于本書可參考:http://www.apuebook.com/。
一、格式化輸出執行格式化輸出處理的是4個PRintf函數。
#include <stdio.h>int printf( const char *restrict format, ... );int fpritnf( FILE *restrict fp, const char *restrict fromat, ... );兩個函數的返回值:若成功則返回輸出字符數,若輸出出錯則返回負值int sprintf( char *restrict buf, const char *restrict format, ... );int snprintf( char *restrict buf, size_t n, const char *restrict format, ... );兩個函數返回值:若此成功則返回存入數組的字符數,若編碼出錯則返回負值
printf將格式化數據寫到標準輸出,fprintf寫至指定的流,sprintf將格式化的字符送入數組buf中。sprintf在該數組的尾端自動加一個null字節,但該字節不包括在返回值中。
注意,sprintf函數可能會造成由buf指向的緩沖區的溢出。調用者有責任確保該緩沖區足夠大。為了解決這種緩沖區溢出的問題,引入了snprintf函數。在該函數中,緩沖區長度是一個顯示參數,超過緩沖區尾端寫的任何字符都會被丟棄。如果緩沖區足夠大,snprintf函數就會返回寫入緩沖區的字符數。與sprintf相同,該返回值不包括結尾的null字節。若snprintf函數返回小于緩沖區長度n的正值,那么沒有截短輸出。若發生了一個編碼錯誤,snprintf則返回負值。
格式說明控制其余參數如果編寫,以后又如何顯示。每個參數按照轉換說明編寫,轉換說明以字符%開始,除轉換說明外,格式字符串中的其他字符將按原樣,不經任何修改地被復制輸出。一個轉換說明有4個可選部分,下面將它們都示于方括號中:
%[flags] [fldwidth] [precision] [lenmodifier] convtype
表5-5 轉換說明中的標志部分
標志 | 說明 |
- | 在字段內左對齊輸出 |
+ | 總是顯示帶符號轉換的符號 |
(空格) | 如果第一個字符不是符號,則在其前面加上一個空格 |
# | 指定另一種轉換形式(例如,對于十六進制格式,加0x前綴 |
0 | 添加前導0(而非空格)進行填充 |
fldwidth說明轉換的最小字段寬度。如果轉換得到的字符較少,則用空格填充它。字段寬度是一個非負十進制數,或是一個星號(*)。
precision說明整型轉換后最少輸出數字位數、浮點數轉換后小數點后的最少位數、字符串轉換后的最大字符數。精度是一個句點(.),后接一個可選的非負十進制整數或一個星號(*)。
寬度和精度字段兩者皆可為*。此時,一個整型參數指定寬度或精度的值。該整型參數正好位于被轉換的參數之前。(注意對這句話的理解)。我們還是用一個實例來說明比較容易接受:
我們可以直接在fldwidth位置用一個整數10指定輸出寬度:
printf("%10d/n", 123);
也可以在fldwidth位置用*,而把指定寬度參數10放在轉換說明后面,被轉換的參數之前:
printf("%*d/n", 10, 123);
lenmodifier說明參數長度。其可能的取值示于表5-6中。
表5-6 轉換說明中的長度修飾符
長度修飾符 | 說明 |
hh | 有符號或無符號的char |
h | 有符號或無符號的short |
l | 有符號或無符號的long或者寬字符 |
ll | 有符號或無符號的long long |
j | intmax_t或uintmax_t |
z | size_t |
t | ptrdiff_t |
L | long double |
convtype不是可選的。它控制如何解釋參數。表5-7中列出了各種轉換類型。
表5-7 轉換說明中的轉換類型部分
轉換類型 | 說明 |
d、i | 有符號十進制 |
o | 無符號八進制 |
u | 無符號十進制 |
x、X | 無符號十六進制 |
f、F | double精度浮點數 |
e、E | 指數格式的double精度浮點數 |
g、G | 解釋為f、F、e或E,取決于被轉換的值 |
a、A | 十六進制指數格式的double精度浮點數 |
c | 字符(若帶長度修飾符l,則為寬字符) |
s | 字符串(若帶長度修飾符l,則為寬字符串) |
p | 指向void的指針 |
n | 將到目前為止,所寫的字符數寫入到指針所指向的無符號整型中 |
% | %字符 |
C | 寬字符(XSI擴展,等效于lc) |
S | 寬字符串(XSI擴展,等效于ls) |
下列4中printf族的變體類似于上面的4種,但是可變參數表(...)代換成了arg。
#include <stdarg.h>#include <stdio.h>int vprintf( const char *restrict format, va_list arg );int vfprintf( FILE *restrict fp, const char *restrict format, va_list arg );兩個函數返回值:若成功則返回輸出字符數,若輸出出錯則返回負值int vsprintf( char *restrict buf, const char *restrict format, va_list arg );int vsnprintf( char *restrict buf, size_t n, const char *restrict format, va_list arg );兩個函數返回值:若成功則返回存入數組的字符數,若編碼出錯則返回負值
關于可變參數列表可參考《C和指針》7.6:Variable Argument Lists。
二、格式化輸入執行格式化輸入處理的是三個scanf函數。
#include <stdio.h>int scanf( const char *restrict format, ... );int fscanf( FILE *restrict fp, const char *restrict format, ... );int sscanf( const char *restrict buf, const char *restrict format, ... );三個函數返回值:若成功則返回指定的輸入項數;若輸入出錯或在任意變換前已到達文件結尾則返回EOF
scanf族用于分析輸入字符串,并將字符序列轉換成指定類型的變量。格式之后的各參數包含了變量的地址,以用轉換結果初始化這些變量。
格式說明控制如何轉換參數,以便對它們賦值。轉換說明以%字符開始。除轉換說明和空白字符外,格式字符串中的其他字符必須與輸入匹配。若有一個字符不匹配,則停止后續處理,不再讀輸入的其余部分。
一個轉換說明有三個可選部分,下面將它們都示于方括號中:
%[*] [fldwidth] [lenmodifier] convtype
可選的前導星號(*)用于抑制轉換。按照轉換說明的其余部分對輸入進行轉換,但轉換結果并不存放在參數中。
fldwidth說明最大寬度(即最大字符數)。
lenmodifier說明要用轉換結果初始化的參數大小。由printf函數族支持的長度修飾符同樣得到scanf函數族的支持(見表5-6中的長度修飾符列表)。
convtype字段類似于printf族的轉換類型字段,但兩者之間還有些差別。一個差別是,存儲在無符號類型中的結果可在輸入時帶上符號。例如,-1可被轉換成4 294 967 295賦予無符號整型變量。表5-8列出了scanf函數族支持的轉換類型。
表5-8 轉換說明中的轉換類型
轉換類型 | 說明 |
d | 有符號十進制,基數為10 |
i | 有符號十進制,基數由輸入格式決定 |
o | 無符號八進制(輸入可選地有符號) |
u | 無符號十進制,基數為10(輸入可選地有符號) |
x | 無符號十六進制(輸入可選地有符號) |
a、A、e、E、f、F、g、G | 浮點數 |
c | 字符(若帶長度修飾符l,則為寬字符) |
s | 字符串(若帶長度修飾符l,則為寬字符串) |
[ | 匹配列出的字符序列,以]終止 |
[^ | 匹配除列出字符以外的所有字符,以]終止 |
p | 指向void的指針 |
n | 將到目前為止讀取的字符數寫入到指針所指向的無符號整型中 |
% | %字符 |
C | 寬字符(XSI擴展,等效于lc) |
S | 寬字符串(XSI擴展,等效于ls) |
與printf族一樣,scanf族也支持函數使用由<stdarg.h>說明的可變參數表。
#include <stdarg.h>#include <stdio.h>int vscanf( const char *restrict format, va_list arg );int vfscanf( FILE *restrict fp, const char *restrict format, va_list arg );int vsscanf( const char *restrict buf, const char *restrict format, va_list arg );三個函數返回值:指定的輸入項數,若輸入出錯或在任一變換前已到達文件結尾則返回EOF
新聞熱點
疑難解答