size_t sz = 100;
char* length[3] = "LEN";
如何連接size_t和char *?在C中連接size_t和char *
我想要的結果是一樣的東西
char* length = "100LEN"
不只是打印出 「100LEN」。
size_t sz = 100;
char* length[3] = "LEN";
如何連接size_t和char *?在C中連接size_t和char *
我想要的結果是一樣的東西
char* length = "100LEN"
不只是打印出 「100LEN」。
如果你想length
是一個串,需要空終止符; char length[4] = "LEN";
或更好,char length[] = "LEN";
,以確保這一點。或者,length
可能是一個指向字符串文字的指針:char *length = "LEN";
。
您可以使用sprintf()
建立一個字符串,像這樣:
#include <stdio.h>
int main(void)
{
size_t sz = 100;
char *length = "LEN";
char result[7];
sprintf(result, "%zu%s", sz, length);
printf("%s\n", result);
return 0;
}
的result
緩衝區必須足夠大,以包含由sprintf()
寫的字。如果涉及的尺寸有不確定性,則使用snprintf()
(自C99開始)更安全。如果函數調用中存在錯誤,則此函數的返回值爲負數,否則它將寫入適當大小的緩衝區中的字符數,而不是空終止符。該返回值可用於檢查輸出是否被截斷,或可用於分配正確大小的緩衝區。
後面的方法在下面的代碼中說明。首先調用snprintf()
將零字符寫入空指針目標。返回值n
是將被寫入適當大小的緩衝區的字符數。這個值可以用來聲明一個VLA,但如果需要的話,這個數組不能再調整大小;這裏使用malloc()
來分配空間,包括空終止符的空間。如果需要再次使用result
緩衝區,則可以將其重新分配爲新的大小。該內存必須在退出程序之前解除分配。
請注意,檢查返回值snprintf()
是否有錯誤。還會檢查malloc()
的返回值是否存在錯誤。
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
size_t sz = 100;
char *length = "LEN";
int n;
n = snprintf(NULL, 0,"%zu%s", sz, length);
if (n < 0) {
fprintf(stderr, "Error in snprintf() size evaluation\n");
exit(EXIT_FAILURE);
}
/* Could use a VLA, but this cannot be resized */
// char result[n+1];
/* Using malloc() allows result to be reallocated later if necessary */
size_t result_sz = n + 1;
char *result = malloc(result_sz);
if (result == NULL) {
fprintf(stderr, "Allocation error\n");
exit(EXIT_FAILURE);
}
n = snprintf(result, result_sz, "%zu%s", sz, length);
if (n < 0) {
fprintf(stderr, "Error in snprintf() write\n");
exit(EXIT_FAILURE);
}
printf("%s\n", result);
free(result);
return 0;
}
程序輸出:
100LEN
一旦你解決上述所有其他問題的代碼,使用sprintf()
(或必要的變化,snprintf()
如果你有一個C99編譯器)
sprintf(dst, "%d%s", (int)sz, string);
/* make sure dst has enough space */
如果你想連接編譯時整數,字符串字面常量,這個問題減少到字符串化整在預處理水平不變,考慮到預處理程序自動串接字符串文字是相鄰的:
#define SZ 100
#define MYSTR "LEN"
int main()
{
#define _STR(X) #X
#define STR(X) _STR(X)
puts(STR(SZ) MYSTR);
}
如果任何兩個組件在編譯時已知的,你需要一個(suffi ciently large)緩衝區將結果寫入,你需要自己將該數字轉換爲一個字符串,例如與sprintf
:
#include<string.h>
#include<stdio.h>
#include<assert.h>
int main()
{
size_t sz = 100;
char const *str = "len";
char concat[40+strlen(str)+1];
assert(sizeof(size_t)*CHAR_BIT <= 128);
//40 is sufficiently large for up to 128 bit size_t's
//given that log_10(2^128) == 38
sprintf(concat, "%zu%s", sz, str);
puts(concat);
}
不要使用sprintf()
它的不安全和風險緩衝覆蓋。
始終使用snprintf()
並根據類型的大小分配輸出可能的最大空間。
#include <stdio.h>
#include <stdint.h>
int main() {
size_t sz = 100;
const char length[] = "LEN";
const size_t buffersz=24;//On 64-bit platform covers a 20 digit size, 2 characters of "LEN" and the '\0' terminator.
char buffer[buffersz];
int count=snprintf(buffer,buffersz,"%zu%s",sz,length);
printf("%d %s",count,buffer);
return 0;
}
腳註:爲什麼你不應該使用sprintf
。
只要您知道輸入的 尺寸,建議您可以使用sprintf
。
這仍然是一個風險,寫得很好的程序不再使用它。 在程序的其他部分改變輸出大小時,它總會有一些變化。這是一個典型的下游災難。將int更改爲long(或從32到64位...)和Boom。
該標準不贊成使用用戶輸入的標準,但所有的輸入都有充分的理由。或者,也許你剛剛得到了一筆錯誤,並且在許多變量接近極限的情況下,程序在不明確的情況下失敗。
假設日誌消息打印出用戶名的日期和大小以及緩衝區太短的睡眠錯誤。根據您的日期格式,您可能會遇到一個錯誤,該錯誤在一個月的特定時間僅對某些用戶崩潰!不要使用sprintf()
。真的沒有必要擔心。只是不要使用它。
我不同意。它總是會在程序的其他部分改變輸出大小時冒一些風險。這是一個典型的下游災難。將int更改爲long(或從32到64位...)和* Boom *。 該標準不贊成用戶輸入標準,而是所有輸入都有充分理由。 – Persixty
@DavidBowling:它在C++中不贊成使用C語言,但突出顯示的風險同樣適用於C.截斷輸出總體上被認爲比沒有輸出更好(緩衝區覆蓋通常會導致崩潰)並且更易於調試。如果您確實安全,請檢查'snprintf'的返回值,然後發出關於截斷的日誌或重新分配緩衝區,然後再次執行。 我從來沒有建議強大的編程只是使用這些功能,但它絕對涉及在可用的地方使用這些功能。 – Persixty
@PSkocik如果你正在處理一個字符串(可能是任意長度)或者輸出'double',這個字符串的'最大'輸出長度不明確,那麼靜態斷言可能是困難的或者是不可能的。計數的開銷最終相當微不足道,因爲與printf格式字符串的低效率相比,您指出的數額相當小。 – Persixty
也許你得到了downvote,因爲「*如果你使用一個數組* *,你需要空終止符,」就好像從字面上看它不是真的。 – alk
@ alk--也許吧。這似乎是一個倒退的輕微原因,因爲我認爲其含義很明確。但是,有一點要說,而且這可能會更好。我更新了我的答案,並添加了關於使用'snprintf()'的評論。我懷疑DV是對我使用'sprintf()'的膝蓋反應。 –
'如果(n> 100){'很混亂 - 尤其是因爲它使用幻數100並且與size_t sz = 100中的100無關。這個測試似乎是一個不必要的完整性測試。建議刪除或解釋其用處。 – chux