VC字符串格式化的用法(全面實用)


一、基本介紹

1、printf()函數的語法

關於格式化字符串,我們從最基本的一個函數入手,這個函數是printf()。它的的聲明如下:

int printf(

 const char *format [,

 argument]...

);

參數format

它用以格式控制,通過含%的字符串來實現,如”%d”。參數里的%可以不止1個。

其實,該參數中,還可以使用普通字符和轉義字符,如”My%d\n”。

該參數內除了輸出控制符和轉義字符外,其余字符原樣輸出。

該參數的完整語法如下:

%[flags] [width] [.precision] [{h | l | ll | I | I32 | I64}]type

后面講詳細介紹這些語法。

參數argument

它是可選參數,不是必須的,可能是1個,2個……,這跟前邊一個參數中%的數量有關。

返回值:若成功,返回打印字符串的數量;若失敗,返回負數。

 

2、典型格式化字符串函數的基本用法

關於格式化字符串的C運行庫函數較多,它們的格式化用法,跟printf()的用法大同小異。

典型的格式化字符串函數有如下:

printf, _printf_l, wprintf, _wprintf_l

sprintf, _sprintf_l, swprintf, _swprintf_l, __swprintf_l

scanf, _scanf_l, wscanf, _wscanf_l

sscanf, _sscanf_l, swscanf, _swscanf_l

(1)、第一組簡介

它們輸出類型,將字符串顯示在屏幕。

示例

int i = 35;

printf("%d",i); //顯示35

(2)、第二組簡介

它們為輸出類型,將格式化后的字符串保存在變量,而不顯示在屏幕。

示例

char buffer[200], s[] = "computer";

sprintf(buffer, "My %s\n", s);

printf("%s", buffer); //顯示My computer

(3)、第三組簡介

它們為輸入類型,從鍵盤輸入,保存在變量。

int i, result;

float fp;

char  c, s[81];

wchar_t wc, ws[81];

result = scanf( "%d %f %c %C %80s %80S", &i, &fp, &c, &wc, s, ws );

printf("The number of fields input is %d\n", result);

printf("The contents are: %d %f %c %C %s %S\n", i, fp, c, wc, s, ws);

 

從鍵盤輸入如下內容(最后還要按回車鍵):

71 98.6 h z Byte characters

然后將顯示如下內容:

The number of fields input is 6

The contents are: 71 98.599998 h z Byte characters

(4)、第四組簡介

它們為輸入類型,不從鍵盤輸入,將給定的字符串按指定格式,保存在變量。

char  tokenstring[] = "15 12 14...";

char  s[81];

char  c;

int   i;

float fp;

 

sscanf(tokenstring, "%80s", s);

sscanf(tokenstring, "%c", &c); 

sscanf(tokenstring, "%d", &i); 

sscanf(tokenstring, "%f", &fp);

  

printf("String    = %s\n", s);

printf("Character = %c\n", c);

printf("Integer:  = %d\n", i);

printf("Real:     = %f\n", fp);

 

顯示如下內容:

String    = 15

Character = 1

Integer:  = 15

Real:     = 15.000000

(5)、sscanf()與sprintf()的區別

它們都不需要硬件輸入輸出,且最終結果都是保存在變量中,但兩者還是有區別的。Sscanf()的最大特點是要給定一字符串(第1個參數),在該值基礎上格式化輸出;而sprintf()則不需要給定一字符串,直接將格式化的部分的內容保存在變量。

 

二、printf()函數的語法詳解

該函數的第1個參數是輸入參數,是字符串類型,用於格式化字符串,它的完整語法如下:

%[flags] [width] [.precision] [{h | l | ll | I | I32 | I64}]type

其中%是格式標志符號,是必須的且固定不變; [……] 部分是可選的;type表示數據類型,和%一樣,也是必須的。

1、[flags]部分的用法

它為標志符號,共有6個:–、+、0、空格符(' ')、#、*

(1)、“–”標志符號

    在缺省情況下,輸出結果采用右對齊;若使用了“-”標志,則在給定的字段寬度內采用左對齊。

(2)、“+”標志符號

如果輸出值是有符號整數類型,則在輸出值前面加上正負符號(+或-)。

(3)、“0”標志符號

如果width以“0”為前綴,則會添加0直到達到最小寬度為止。

注意:以下兩種情況,“0”標志符號功能將被忽略。

A、如果使用了“-”標志,則“0”標志符號功能不在起作用。

B、如果“0”是用整數格式指定的(i、u、x、X、o、d),並且還提供了精度規范(例如,%04.d), “0”標志符號功能也不在起作用。

(4)、blank(空格)標志符號

如果輸出值是帶符號且為正的正數,則在輸出值的前面加上一個空白;如果同時出現空白和+標志,空白將被忽略。

這里的blank標志符號,是針對帶符號的正整數而言。對於字符串的空格,則直接使用’ ’字符。

(5)、“#”標志符號

當與o、x或X格式一起使用時,分別輸出0、0x或0X作為任何非零輸出值的前綴,分別表示八進制數、十六進制數、十六進制數。前綴0x與0X都表示十六進制數。

 

(6)、“*”標志符號

“*”要占一個變量的位置,不過它被忽略,從“*”的下一個位置開始取值。整數類型支持這種功能,但是浮點數則不支持。

 

2、[width]部分的用法

    這個可選字段是寬度規范。寬度參數是一個非負的十進制整數,控制打印的最小字符數。如果輸出值中的字符數小於指定的寬度,則會在值的左邊或右邊添加空格(若使用了“-”標志,則左對齊,右邊補空格;否則右邊對齊,左邊補空格),直到達到最小寬度。

    一般情況下,寬度與“0”標志符號搭配使用,才有意義。如果width以“0”為前綴,則會添加0直到達到最小寬度為止(對於左對齊的數字沒有用處)。

    寬度規范不會導致值被截斷。如果輸出值中的字符數大於指定的寬度,或者寬度未指定,則打印該值的所有字符(根據精度要求)。

 

3、[.precision]部分的用法

這個可選字段是精度規范。它指定一個非負的十進制整數,前面有一個句點,即“.”符號,它指定要打印的字符數、小數點位數或有效位數(請參閱精度值如何影響類型表)。

與寬度規范不同,精度規范可能導致輸出值的截斷或浮點值的舍入。

如果將精度指定為0,且要轉換的值為0,則結果為不輸出字符,參考如下:

printf( "%.0d", 0);  //結果為空值

    類型決定了精度的解釋,當省略精度時,默認值如下表所示。

類型

含義

缺省值

a, A

精度指定小數點后的位數。

 

默認精度為6。如果精度為0,則不打印小數點,除非使用#標志。

c, C

非數值型數據,與精度無關。

字符直接打印出來。

d, i, u, o, x, X

精度指定要打印的最小數字個數。若參數中的數字個數小於精度,輸出值將在左側用零填充。若參數中的數字個數大於精度時,輸出值為參數值。

默認精度為1。

 

e, E

精度指定小數點后的位數,最后打印的數字四舍五入。

默認精度為6;如果precision為0或句點(.)后面沒有數字,則不打印小數點。

f

精度指定小數點后的位數。如果出現小數點,則小數點前至少出現一位數字。該值被四舍五入到適當的位數。

默認精度為6;如果精度為0,或者句點(.)后面沒有數字,則不打印小數點。

g, G

精度指定打印的最大有效數字數。

 

將打印6個有效數字,末尾的零將被截斷。

s, S

精度指定要打印的最大字符數,不打印超過精度的字符。

字符一直打印到遇到空字符為止。

 

4、[{h | l | ll | I | I32 | I64}]部分的用法

    type的可選前綴h、l、I、I32、I64和ll指定參數的“size”(長或短、32或64位、單字節字符或寬字符,取決於它們修改的類型說明符)。這些類型說明符前綴與printf函數或wprintf函數中的類型字符一起使用,以指定參數的解釋,如下表所示。

    當h和l前綴作為字符使用時,是Microsoft擴展字符,而不是ansi的。

說明

前綴

類型說明

long int

l

d, i, o, x或X

long unsigned int

l

o, u, x或X

long long

l l

d, i, o, x或X

short int

h

d, i, o, x或X

short unsigned int

h

o, u, x或X

__int32

I32

d, i, o, x或X

unsigned __int32

I32

o, u, x或X

__int64

I64

d, i, o, x或X

unsigned __int64

I64

o, u, x或X

ptrdiff_t (在32位系統,為__int32類型;在64位系統,為__int64類型)

I

d, i, o, x或X

size_t (在32位系統,為__int32類型;在64位系統,為__int64類型)

I

o, u, x或X

long double

l

f

在printf函數中使用的單字節字符

h

 

c或C

在wprintf函數中使用的單字節字符

h

 

c或C

在printf函數中使用的寬字節字符

l

c或C

在wprintf函數中使用的寬字節字符

l

 

c或C

在printf函數中使用的單字節字符串

h

 

s或S

在wprintf函數中使用的單字節字符串

h

 

s或S

在printf函數中使用的寬字節字符串

l

 

s或S

在wprintf函數中使用的寬字節字符串

l

 

s或S

寬字節字符

w

c

寬字節字符串

w

s

 

printf函數和wprintf函數打印單字節或寬字符,請使用如下格式說明符。

輸出字符類別

使用函數

格式控制符

單字節字符

printf

c, hc或hC

單字節字符

wprintf

c, hc或hC

寬字節字符

wprintf

c, lc, lC或 wc

寬字節字符

printf

c, lc, lC或wc

 

5、type部分的用法

    類型字符是唯一必需的格式字段,它出現在任何可選的格式字段之后。類型字符確定關聯參數是被解釋為字符、字符串還是數字。類型C、n、p和S,以及C和S與printf函數的行為,都是Microsoft擴展,不是ANSI兼容的。

類型

實際類型

輸出格式

c

int 或 wint_t

當使用printf函數時,指定一個單字節字符;當使用wprintf函數時,指定一個寬字符。

注:wint_t為unsigned short

C

int 或 wint_t

當使用printf函數一起時,指定一個寬字符;當使用wprintf函數時,指定一個單字節字符。

d

int

有符號十進制整數。

i

int

有符號十進制整數。

o

unsigned int

無符號八進制整數。

u

unsigned int

無符號十進制整數。

x

unsigned int

無符號十六進制整數,使用abcdef。

X

unsigned int

無符號十六進制整數,使用ABCDEF。

e

double

采用科學計數法,形式為[-]d.dddd e [sign]dd[d]的帶符號值。其中d為單個十進制數,dddd為一個或多個十進制數,dd[d]為兩個或三個十進制數,符號為+或-。

E

double

和e格式一樣,只是輸出結果用E替換e。

f

double

形式為[-]dddd.dddd的帶符號值,其中dddd是一個或多個十進制數字。小數點前的位數取決於數字的大小,小數點后的位數取決於要求的精度。

g

double

以f或e格式打印帶符號值,這取決於哪個更短。e格式僅在值的指數小於-4或大於或等於precision參數時使用。后面的零會被截斷,小數點只在后面有一個或多個數字時才會出現。

G

double

與g格式相同,只是輸出結果用E替換e除了E。

a

double

采用P計數法,形式為[−]0xh.hhhh P±dd的有符號十六進制雙精度浮點值,其中h.hhhh為尾數的十六進制數字(用小寫字母表示),dd為指數的一個或多個數字。精度指定點后的位數。

A

double

采用P計數法,形式為[−]0Xh.hhhh P±dd的有符號十六進制雙精度浮點值,其中h.hhhh為尾數的十六進制數字(大寫字母),dd為指數的一個或多個數字。精度指定小數點后的位數。

n

指向整型的指針

到目前為止成功寫入流或緩沖區的字符數;該值存儲在整數中,其地址作為參數給出。

p

指向任意型的指針

將打印十六進制數表示的變量地址值。

s

字符串

當與printf函數一起使用時,指定一個單字節字符串;當與wprintf函數一起使用時,指定寬字符字符串。字符將一直打印到第一個空字符或直到達到精度值為止。

S

字符串

當與printf函數一起使用時,指定寬字符字符串;當與wprintf函數一起使用時,指定一個單字節字符串。字符將一直打印到第一個空字符或直到達到精度值為止。

 

注意:如果對應於%s或%S的參數是空指針,“(null)”將被打印。

注意:在所有指數格式中,默認顯示的指數位數是3。使用_set_output_format函數,可以將顯示的數字數設置為2,如果exponent的大小需要,則擴展為3。

安全注意:%n格式本質上是不安全的,默認情況下是禁用的;如果在格式字符串中遇到%n,將按照參數驗證中所述調用無效的參數處理程序。要啟用%n支持,請使用_set_printf_count_output函數。

 

三、printf()函數的用法

現在大多的程序是在MFC代碼,CString類的Format()成員的用法,跟printf()函數一致。因此,示例采用MFC程序。

可能要包含如下文件:#include <stdio.h>

1、[flags]部分的用法

(1)、“–”標志符號

CString strTemp1;

strTemp1.Format("|%15s|","1234567890");

//為了觀看效果直觀,需要加“參照物”,如這里的'|'

//給定15個字符長度,但這里只有10個字符,不夠15個;

//由於沒有加“–”,則缺省為右邊對齊,左邊補空格。 

MessageBox(strTemp1); //結果為|     1234567890|

 

strTemp1.Format("|%-15s|","1234567890");

//給定15個字符長度,但這里只有10個字符,不夠15個,則左對齊,右邊補空格。     

MessageBox(strTemp1); //結果為|1234567890   

 

(2)、“+”標志符號

CString strTemp2;

strTemp2.Format("%+d",200);

MessageBox(strTemp2); //結果為+200

 

strTemp2.Format("%+d",-200);

MessageBox(strTemp2); //結果為-200

 

strTemp2.Format("%d",-200); //對於負數,可以不加“+”

MessageBox(strTemp2); //結果為-200

 

(3)、“0”標志符號

CString strTemp3;

strTemp3.Format("%03d",4);  

//當前字符串的寬度為3

MessageBox(strTemp3); //結果為004

 

strTemp3.Format("%-03d",4); 

//使用“-”標志后,“0”標志符號功能將被忽略

MessageBox(strTemp3); //結果為4

 

strTemp3.Format("%03.d",4); 

//使用整數格式指定的(i、u、x、X、o、d),並且還提供了精度規范(例如,%04.d),

//“0”標志符號功能也不在起作用。

MessageBox(strTemp3); //結果為4

 

(4)、空格標志符號

CString strTemp4;

strTemp4.Format("%d",500);//正號用空格替代

MessageBox(strTemp2); //結果為500

 

(5)、“#”標志符號

CString strTemp5;

strTemp5.Format("%#o",35);

//輸出一個八進制數,將十進制數轉換為八進制數

MessageBox(strTemp5); //結果為043,前綴為零而非字母o

 

strTemp5.Format("%#x",35);

//輸出一個十六進制數,將十進制數轉換為十六進制數

MessageBox(strTemp5); //結果為0x23

 

strTemp5.Format("%#X",35); //前綴0x與0X都表示十六進制數

//輸出一個十六進制數,將十進制數轉換為十六進制數 

MessageBox(strTemp5); //結果為0X23

 

strTemp5.Format("%#x",0x35);

//輸出一個16進制數,這里0x35本身就是十六進制數

MessageBox(strTemp5); //結果為0x35

 

(6)、“*”標志符號

CString strTemp6;

strTemp6.Format("%*d,%d",12,28,89);

//首先,“*”要占一個變量的位置,不過它被忽略;

//因此,從“*”的下一個位置開始取值;

//這里“*”對應的數是28,但被忽略;后邊還有兩個%d,則分別對應28和89

MessageBox(strTemp6); //結果為28,89   

 

//strTemp6.Format("%*f,%f",28.45,67.26,83.02);

//float類型不支持“*”功能

//MessageBox(strTemp6);

 

2、[width]部分的介紹

CString strTemp;

strTemp.Format("%d",4); 

//不指定寬度,輸出本身。

MessageBox(strTemp); //結果為4

 

strTemp.Format("%2d",4);

//指定寬度,但不指定前綴“0”,也輸出本身。

MessageBox(strTemp); //結果為4

 

strTemp.Format("%02d:%02d:%02d:%03d",4,52,6,21);

//即指定了寬度,又指定了指定前綴“0”,才右意義。

MessageBox(strTemp); //結果為04:52:06:021

//其中小時部分“4”,不足兩位,則補齊為“04”;

//其中分鍾部分“52”,本身就是兩位,則不變。

 

strTemp.Format("%-03d",4);   

//使用“-”標志后,“0”標志符號功能將被忽略

MessageBox(strTemp); //結果為4

 

strTemp.Format("%8s","abcdefghijk"); 

//這里指定輸出值的字符數為8,而實際給定的字符數為11;

//這種輸出值中的字符數大於指定的寬度,輸出值不會被截斷。

MessageBox(strTemp); //結果為abcdefghijk,而不是abcdefgh

      

strTemp.Format("|%15s|","1234567890"); //未使用“–”標志符號

//為了觀看效果直觀,需要加“參照物”,如這里的'|'

//給定15個字符長度,但這里只有10個字符,不夠15個;

//由於沒有加“–”,則缺省為右邊對齊,左邊補空格。 

MessageBox(strTemp); //結果為|     1234567890|

 

strTemp.Format("|%-15s|","1234567890"); //使用了“–”標志符號

//給定15個字符長度,但這里只有10個字符,不夠15個,則左對齊,右邊補空格。     

MessageBox(strTemp); //結果為|1234567890      

 

3、[.precision]部分的介紹

float fVal = 45.27;

CString strTemp;

strTemp.Format("%f",fVal);    

//不指定精度,缺省情況下,float類型的變量會顯示6位小數。

MessageBox(strTemp); //結果為45.270000

strTemp.Format("%.3f",fVal); 

//指定輸出3位小數

MessageBox(strTemp); //結果為45.270

strTemp.Format("%.2f",fVal); 

//指定輸出2位小數

MessageBox(strTemp); //結果為45.27

strTemp.Format("%.1f",fVal); 

//指定輸出1位小數,最后一位小數執行四舍五入

MessageBox(strTemp); //結果為45.3

 

strTemp.Format("%.0d",0);     

//精度指定為0,且要轉換的值為0,則結果為不輸出字符

MessageBox(strTemp); //結果為空值

 

strTemp.Format("%.2d",452);

//參數452的數字個數為3,精度為2

//參數中的數字個數大於精度,輸出值為參數值。

MessageBox(strTemp); //結果為452

strTemp.Format("%.5d",452);

//參數452的數字個數為3,精度為5

//參數中的數字個數小於精度,輸出值將在左側用零填充。

MessageBox(strTemp); //結果為00452

 

4、[{h | l | ll | I | I32 | I64}]部分的介紹

int iVal = -269;

//int的范圍為-2147483648-2147483647

unsigned int uVal = 248;

//unsigned int的范圍為0-4294967295

long long llVal = -9223372036854775808;

//long long的范圍為-9223372036854775808-9223372036854775807

__int32 __iVal32 = 678;

//__int32等效為int

__int64 __iVal64 = 9223372036854775807;

//__int64等效為long long

unsigned __int64 u__iVal64 = 18446744073709551615;

//unsigned __int64等效為unsigned long long

//unsigned __int64的范圍為0-18446744073709551615

//18446744073709551615(0xffffffffffffffff)

long double dVal = 67.34576899;

 

char cChar = 'D';

WCHAR wChar = 'F';

 

char* sStr = "abcd";

WCHAR* wStr = L"efgh"; //寬字符串要以L為前綴

 

CString strTemp;

strTemp.Format("%d",iVal);         

MessageBox(strTemp); //結果為-269

strTemp.Format("%ld",iVal);       

MessageBox(strTemp); //結果為-269

strTemp.Format("%u",uVal);       

MessageBox(strTemp); //結果為248

strTemp.Format("%u",iVal);//類型不一致,雖不報錯,但結果錯誤   

MessageBox(strTemp); //結果為4294967027

//4294967027 = 4294967295+(-269)

 

strTemp.Format("%lld",llVal); //ll對應long long類型 

MessageBox(strTemp); //結果為-9223372036854775808

strTemp.Format("%I32d",__iVal32); //I32對應int類型 

MessageBox(strTemp); //結果為678

strTemp.Format("%I64d",__iVal64); //I64對應long long類型 

MessageBox(strTemp); //結果為9223372036854775808

strTemp.Format("%I64u",u__iVal64); //I64也對應unsigned long long類型 

MessageBox(strTemp); //結果為18446744073709551615

 

strTemp.Format("%f",dVal); 

MessageBox(strTemp); //結果為67.345769

strTemp.Format("%lf",dVal);

MessageBox(strTemp); //結果為67.345769

 

strTemp.Format("%c",cChar); //“c”為單字節字符

MessageBox(strTemp); //結果為D

strTemp.Format("%hc",cChar); //“hc”為單字節字符

MessageBox(strTemp); //結果為D

strTemp.Format("%lc",wChar); //“lc”為寬字符

MessageBox(strTemp); //結果為F

 

strTemp.Format("%s",sStr); //“s”為單字節字符串

MessageBox(strTemp); //結果為abcd

strTemp.Format("%hs",sStr); //“hs”為單字節字符串

MessageBox(strTemp); //結果為abcd

strTemp.Format("%ls",wStr); //“ls”為寬字節字符串

MessageBox(strTemp); //結果為efgh

 

strTemp.Format("%wc",wChar); //“wc”為寬字符

MessageBox(strTemp); //結果為F

strTemp.Format("%ws",wStr); //“ws”為寬字節字符串

MessageBox(strTemp); //結果為efgh

 

5、type部分的介紹

char cChar = 'D';

WCHAR wChar = 'F';

char* sStr = "abcd";

WCHAR* wStr = L"efgh"; //寬字符串要以L為前綴

CString strTemp;

strTemp.Format("%c",cChar); //“c”為單字節字符

MessageBox(strTemp); //結果為D

strTemp.Format("%C",wChar); //“C”為寬字符

MessageBox(strTemp); //結果為F

strTemp.Format("%s",sStr); //“s”為單字節字符串

MessageBox(strTemp); //結果為abcd

strTemp.Format("%S",wStr); //“S”為寬字符串

MessageBox(strTemp); //結果為efgh

 

int iVal = -248;

//int的范圍為-2147483648-2147483647

unsigned int uVal = 248;

//unsigned int的范圍為0-4294967295

strTemp.Format("%d",iVal); //“d”為int

MessageBox(strTemp); //結果為-248

strTemp.Format("%u",uVal); //“u”為unsigned int

MessageBox(strTemp); //結果為248

strTemp.Format("%x",uVal); //“x”為無符號十六進制整數

MessageBox(strTemp); //結果為f8

strTemp.Format("%X",uVal); //“X”為無符號十六進制整數

MessageBox(strTemp); //結果為F8

 

double dVal = 41.25;

strTemp.Format("%A",dVal);

//采用P計數法,底數為2,p+5為2的5次方

MessageBox(strTemp); //結果為0X1.4A0000P+5

strTemp.Format("%a",dVal);

//采用P計數法,底數為2,p+5為2的5次方

MessageBox(strTemp); //結果為0x1.4a0000p+5

strTemp.Format("%E",dVal);

//采用科學計數法,底數為10,E+001為10的1次方    

MessageBox(strTemp); //結果為4.125000E+001

strTemp.Format("%e",dVal);

//采用科學計數法,底數為10,E+001為10的1次方    

MessageBox(strTemp); //結果為結果為4.125000e+001

strTemp.Format("%.3e",dVal);

//采用科學計數法,底數為10,E+001為10的1次方    

MessageBox(strTemp); //結果為結果為4.125e+001

strTemp.Format("%f",dVal);

//缺省情況下,小數位保留6位 

MessageBox(strTemp); //結果為結果為41.250000

strTemp.Format("%.2f",dVal);

//小數位保留兩位    

MessageBox(strTemp); //結果為結果為41.25

strTemp.Format("%g",dVal);

//選取f與e輸出結果的簡潔值,41.25比4.125000e+001簡潔

MessageBox(strTemp); //結果為結果為41.25

strTemp.Format("%G",dVal);

//選取f與E輸出結果的簡潔值,41.25比4.125000E+001簡潔

MessageBox(strTemp); //結果為結果為41.25

 

void* pVoid = "ASD";

strTemp.Format("%p",pVoid);

//輸出變量的地址值。

MessageBox(strTemp); //結果為結果為012BE250


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM