2012-06-21 201 views
0

如何在不使用兩個printf調用的情況下正確打印此打印?如何在c中打印

char* second = "Second%d"; 
printf("First%d"second,1,2); 
+3

有(IIRC)沒有內置的方法來做到這一點,因爲它可能是一個**主要**安全問題。查看http://en.wikipedia.org/wiki/Uncontrolled_format_string瞭解如何使用該程序的詳細信息。 – templatetypedef

+0

謝謝。非常有幫助 –

回答

2

你向我們展示的代碼在語法上是無效的,但我想你想要做的東西,有相同的效果:

printf("First%dSecond%d", 1, 2); 

由於你知道,printf的第一個參數是格式字符串。它不一定是文字;你可以用你喜歡的任何方式構建它。

下面是一個例子:

#include <stdio.h> 
#include <string.h> 
int main(void) 
{ 
    char *second = "Second%d"; 
    char format[100]; 
    strcpy(format, "First%d"); 
    strcat(format, second); 

    printf(format, 1, 2); 

    putchar('\n'); 
    return 0; 
} 

一些注意事項:

我的輸出後添加一個換行符。輸出文本應該(幾乎)總是以換行符終止。

我已經爲格式字符串設置了100個字節的任意大小。更一般地,你可以聲明

char *format; 

,並以malloc()調用初始化,分配你實際需要的尺寸(並檢查malloc()沒有通過返回一個空指針信號故障);完成之後,您想要撥打free(format);

由於templatetypedef在註釋中說,如果格式字符串來自不受控制的源,這種事情可能會潛在地危險。

(或者您也可以撥打printf兩倍;它不是更昂貴比調用一次)

+0

我測試過這個解決方案,並且它與使用兩個printf類似的成本。我想我沒有別的選擇。謝謝! –

0
char *second = "Second%d"; 
char tmp[256]; 
memset(tmp, 0, 256); 
sprintf(tmp, second, 2); 
printf("First%d%s", 1,tmp); 

或者類似的東西

+1

你的意思是'printf(「First%d%s」,1,tmp);'? – Shahbaz

+0

當然。這更好 – Matthieu

+0

我的意思是,你寫的是行不通的。您不能通過將C和C中的字符串和char *'/'char數組放在一起。 – Shahbaz

0

使用預處理程序來連接兩個字符串。

#define second "Second%d" 
printf("First%d"second,1,2); 

不要在真正程序做到這一點。

+0

這應該是答案,因爲這是最快的方式(正如OP顯然希望的那樣)。但是,第二個顯然必須在編譯時才知道。 +1 – jn1kk

+0

語法錯誤。參見[stringfication](http://gcc.gnu.org/onlinedocs/cpp/Stringification.html)或[Convert](http://stackoverflow.com/questions/240353/convert-a-preprocessor-token-to-一個字符串)。 –

+0

@RichardChambers我在哪裏說這是串化?這是使用預處理器來連接兩個字符串。請刪除downvote。 http://ideone.com/eUGVI – Marlon

-1

我假設你想要的輸出:

First 1 Second 2

要做到這一點,我們需要了解printf的功能好一點。 printf非常有用的真正原因是它不僅打印字符串,還爲您設置變量格式。根據你希望你的變量格式化你需要使用不同的格式化字符。 %d告訴printf將變量格式化爲已知的有符號整數。但是,還有其他格式,例如浮點數和浮點數的%f,長整數的%l%,字符串的%schar*

使用%s格式化字符打印您char*變量,second,我們的代碼看起來是這樣的:

char* second = "Second"; 
printf (" First %d %s %d ", 1, second, 2); 

這告訴你要格式化爲一個整數的第一個變量,第二個作爲一個字符串printf,第三個是另一個整數。

+0

我認爲OP實際上是在問如何使用預處理器進行雙重評估(W/O)。 –

+0

-1表示非const char *'。 – Puppy

0
char *second = "Second %d"; 
char *first = "First %d"; 
char largebuffer[256]; 

strcpy (largebuffer, first); 
strcat (largebuffer, second); 
printf (largebuffer, 1, 2); 

問題與使用所生成的格式,如上述方法是,printf()函數,因爲它是一個可變長度的參數列表中,無法知道的設置參數的數目的方式。它所做的是使用提供的格式字符串,並使用格式字符串中描述的類型,然後從參數列表中選擇該數量和類型的參數。

如果您提供了正確數量的參數,如上面的示例中有兩個%d格式,並且提供了兩個要在這些地方打印的整數,則一切正常。但是如果你這樣做了以下內容:

char *second = "Second %s"; 
char *first = "First %d"; 
char largebuffer[256]; 

strcpy (largebuffer, first); 
strcat (largebuffer, second); 
printf (largebuffer, 1); 

在這個例子中的printf()函數需要的格式字符串,以及的參數個數可變。格式字符串表示將會有兩個附加參數,一個整數和一個以零結尾的字符串。然而,只提供了一個額外的參數,所以printf()函數將使用堆棧中接下來的內容作爲零終止字符串的指針。

如果幸運的話,printf()函數解釋爲指針的數據將成爲您的應用程序的有效內存地址,並且指向的內存區域將是由零結尾的幾個字符。如果你不那麼幸運,那麼指針將爲零或垃圾,那麼你將會得到一個訪問衝突,這將很容易找到應用程序崩潰的原因。如果你根本沒有運氣,指針就會足夠好,它會指向一個大約2K字符的有效地址,結果是printf()會將你的堆棧完全搞亂並進入雜草,結果是崩潰數據將是無用的。