簡體   English   中英

連接像printf一樣的字符串

[英]Concatenate a string like in printf

printf是一個很棒的函數,因為它可以幫助你以非常干凈的方式格式化字符串。

printf("Player %s has lost %d hitpoints", victim.name, damage);

是否有類似的方法連接和執行強制在“正常字符串”,如下所示:

uint8_t myString = ("Player %s has lost %d hitpoints", victim.name, damage); //SOMETHING LIKE THIS

你可以使用sprintf() 像這樣

char* myString = malloc(50);

sprintf(myString, "Player %s has lost %d hitpoints", victim.name, damage);

正如您所猜測的那樣,它代表字符串printf


請注意sprintf()需要char* ,而不是uint8_t


當然你也可以使用snprintf() 附加的優點是您可以將要復制的字符數賦予字符串。 這可以防止緩沖區溢出。

char* myString = malloc(50);

snprintf(myString, 50, "Player %s has lost %d hitpoints", victim.name, damage);

C99的snprintf打印到字符串並保證不會溢出緩沖區:

char msg[48];

snprintf(msg, sizeof(msg),
    "Player %s has lost %d hitpoints", victim.name, damage);

snprintf返回字符串足夠大時可能寫入的字符數。 因此,如果返回的值等於或大於緩沖區大小,則字符串將被截斷。

傳遞緩沖區大小為零和空指針是合法的,這樣您就可以通過首先進行探測調用來進行自己的分配:

char *msg;
int n;

n = snprintf(NULL, 0,
    "Player %s has lost %d hitpoints", victim.name, damage);

msg = malloc(n + 1);
n = snprintf(msg, n + 1,
    "Player %s has lost %d hitpoints", victim.name, damage);

// do stuff with msg

free(msg);

在GNU編譯器上,非sandard函數asprintf將為您做到這一點:

char *msg = asprintf("Player %s has lost %d hitpoints",
    victim.name, damage);

// do stuff with msg

free(msg);

每個人都在建議sprintf ,但在我看來,總是使用snprintf要好得多。 函數原型如下:

int snprintf ( char * s, size_t n, const char * format, ... );

第一個參數是您的字符串緩沖區,第二個參數是其最大容量,后跟格式說明符字符串和參數。 用法示例:

char str[STR_LEN];
snprintf(str, sizeof(str), "Player %s has lost %d hitpoints", victim.name, damage);

請注意,雖然這永遠不會做任何違法行為(使用sprintf可能會產生未定義的行為),如果您的緩沖區不夠長,字符串將被截斷,這可能會導致一些令人驚訝的輸出。 最好是檢查snprintf的結果,看看真正寫了多少個字符(感謝chux指出這個)。

如果你有興趣能夠編寫類似你問題中的代碼,從格式化函數返回給你的字符串,你可能會發現Carmack從他的idTech3引擎發出的va有趣: https//github.com/id -Software / Quake-III-Arena / blob / master / code / splines / q_shared.cpp (700行)。 請注意,您應該了解它的工作原理及其對嵌套調用的可能影響,更不用說在多線程環境中使用它時可能出現的問題。

試試這樣吧

   char str[MAX_LEN];
   sprintf(str,"Player %s has lost %d hitpoints", victim.name, damage);

但我不確定將uint8_t*傳遞給sprintf而不是char *是非常安全的。 (它可能違反約束,請參閱此處了解有關類似情況的更多詳細信息)。

確實,為了更安全,你也可以使用snprintf

printf("Player %s has lost %d hitpoints", victim.name, damage);

如果要將結果保存在字符串中而不是打印它,則可以使用同一系列中的另一個函數sprintf 在您的情況下,使用它像這樣:

sprintf(myString,"Player %s has lost %d hitpoints", victim.name, damage);

有關sprintf的更多信息

正如user694733指出的那樣,使用snprintf而不是sprintf通常更安全。 兩者之間的區別在於,對於snprintf您可以指定寫入字符串的最大字符數(這包括第二個參數中的終結符char \\0 !“。 有關snprintf的更多信息

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM