2017-06-27 22 views
4

我知道%%用來逃避字符串中的實際%跡象,所以%%%ds最終會在以下格式字符串%10s,但我不知道爲什麼我在這個字符串需要%%5s格式字符串與多個百分號

畢竟,只有兩個附加參數(BUFFSIZE/10)。

#define BUFFSIZE 100 
char buf[100]={0} 
sprintf(buf, "%%5s %%%ds %%%ds", BUFFSIZE/10, BUFFSIZE/10); 

運行上面的代碼後,BUF將包含字符串,

%10s %10s 
+5

我在'buf'中獲得'%5s%10s%10s',在這裏演示http://ideone.com/c8MhN6。 _you_期望什麼? –

+2

這意味着某人要麼過於聰明,要麼不知道['%* s'](https://stackoverflow.com/questions/7105890/set-variable-text-column-width-in-printf)。 –

+1

@ n.m。或者,不怕維護者(_Ref:暴力精神病患者) –

回答

5

的目的是爲了獲得一個格式字符串中,需要一個格式字符串像sscanf()另一個函數來使用它。

使用您的代碼,您將得到:%5s %10s %10s寫入您的bufsee online,這意味着它將接受三個具有長度標識符的字符串。

%%5s   --> %5s 
%%%ds with 10 --> %10s (read it that way: {%%}{%d}{s}) 

即緩衝器%5s %10s %10s現在可以在一個sscanf()呼叫可以使用像所示here

但是,最好的做法是防止由sscanf()引起的緩衝區溢出,Kernighan和Pike在其書The Practice of Programming中也描述了緩衝區溢出,請參見here on SO


爲什麼你也許不能使用%*s可能是這個原因,看here on SO

printf,則*允許您通過一個額外的參數指定最小字段寬度,即printf("%*d", 4, 100);指定字段寬度爲4.

對於scanf,*表示該字段將被讀取但被忽略,因此,即輸入「12 34」的scanf("%*d %d", &i)將忽略12並將其讀入整數i。

2

%本身是一個有效的轉換說明符。在規定的語法,如在C11,章§7.21.6.1/ P2,(重點煤礦

每種轉換規範由字符%引入提及。 %後,以下 出現在序列:

  • 零個或更多個標誌[...]

  • 可選最小字段寬度。

  • 可選的精度[...]

  • 可選長度修改[...]

  • 轉換說明符字符,指定要應用的轉換類型。

然後,P8,用於轉換說明

轉換標識符和它們的含義如下:

......

%

A %字符被寫入。沒有參數被轉換。完整的 轉換規範應爲%%

因此,基於貪婪方法,編譯器將組像

.... %%%ds, BUFFSIZE/10 .... 

作爲

{%%}{%d}{s} 
    ^^--------------------------Replaced as % 
     ^^----------------------Actual conversion specification happens, argument is used 
     ^^------------------just part of final output 

語法這最終產生

%Xs //where X is the value of (BUFFSIZE/10) 

這是一個有效格式字符串(%,最小字段寬度,轉換說明符,全部按順序),以後再使用。

+0

你解釋了一切,我的錯誤 –

+0

@VishwajeetVishu Nevermind,沒關係。同時我也在更新答案。 :) –

0

OP從參數大小計算格式字符串。給定的參數,該字符串將包含%5s %10s %10s,其可與任一printfscanf使用:

printf("%5s %10s %10s", "A", "B", "C"); 

輸出:

A   B   C 

char a[6], b[11], c[11]; 
scanf("%5s %10s %10s", a, b, c); 

將讀取3串入abc但限制了數爲每個字符串讀取字符以防止緩衝區溢出。

不過請注意,對於printf情況下,沒有必要計算字符串作爲貼了,因爲你也可以使用:

printf("%5s %*s %*s", "A", BUFFSIZE/10, "B", BUFFSIZE/10, "C"); 

不幸的是,scanf()高度不同的語義爲*格式修改,這是無法指定要使用參數存儲的最大字符數,只能使用格式字符串中的數字,因此需要單獨的格式化步驟。