[英]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);
正如user694733指出的那樣,使用snprintf
而不是sprintf
通常更安全。 兩者之間的區別在於,對於snprintf
您可以指定寫入字符串的最大字符數(這包括第二個參數中的終結符char \\0
!“。 有關snprintf的更多信息
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.