我在C工作,我必須連接幾件事情。如何在C中連接const/literal字符串?
現在我有這樣的:
message = strcat("TEXT ", var);
message2 = strcat(strcat("TEXT ", foo), strcat(" TEXT ", bar));
現在,如果你在C我敢肯定你意識到這給你一個分割錯誤當您嘗試運行的經驗。那麼我該如何解決這個問題?
我在C工作,我必須連接幾件事情。如何在C中連接const/literal字符串?
現在我有這樣的:
message = strcat("TEXT ", var);
message2 = strcat(strcat("TEXT ", foo), strcat(" TEXT ", bar));
現在,如果你在C我敢肯定你意識到這給你一個分割錯誤當您嘗試運行的經驗。那麼我該如何解決這個問題?
在C中,「strings」只是數組。因此,您不能將它們與其他「字符串」直接連接起來。
可以使用strcat
功能,附加字符串指向src
到字符串的結尾由dest
指出:
char *strcat(char *dest, const char *src);
這裏是一個example from cplusplus.com:
char str[80];
strcpy(str, "these ");
strcat(str, "strings ");
strcat(str, "are ");
strcat(str, "concatenated.");
對於第一個參數,您需要提供目標緩衝區本身。目標緩衝區必須是char數組緩衝區。例如:char buffer[1024];
確保第一個參數有足夠的空間來存儲您要拷貝的內容。如果對您有用,使用以下功能會更安全:strcpy_s
和strcat_s
,您明確必須指定目標緩衝區的大小。
注意:字符串文字不能用作緩衝區,因爲它是一個常量。因此,你總是必須爲緩衝區分配一個char數組。
strcat
的返回值可以簡單地忽略,它只返回與第一個參數傳入的指針相同的指針。這是那裏的便利,並允許您鏈調用成一行代碼:
strcat(strcat(str, foo), bar);
那麼如下的問題可以解決:
char *foo = "foo";
char *bar = "bar";
char str[80];
strcpy(str, "TEXT ");
strcat(str, foo);
strcat(str, bar);
您能否以粗體字「請非常小心......」?這不能夠強調。濫用strcat,strcpy和sprintf是不穩定/不安全軟件的核心。 – plinth 2008-11-21 13:33:10
這是不確定的行爲,以嘗試修改字符串文字,這是什麼樣的:
strcat ("Hello, ", name);
會試圖做。它會嘗試將name
字符串添加到字符串文字"Hello, "
的末尾,該字符串的定義不明確。
試試這個。它實現了你看起來是試圖做:
char message[1000];
strcpy (message, "TEXT ");
strcat (message, var);
這將創建一個緩衝區面積是允許修改,然後拷貝這兩個字符串文字等文本。請注意緩衝區溢出。如果你控制輸入數據(或者事先檢查它),那麼使用像我這樣的固定長度的緩衝區是很好的。否則,您應該使用緩解策略,例如從堆中分配足夠的內存以確保您可以處理它。換句話說,類似於:
const static char TEXT[] = "TEXT ";
// Make *sure* you have enough space.
char *message = malloc (sizeof(TEXT) + strlen(var) + 1);
if (message == NULL)
handleOutOfMemoryIntelligently();
strcpy (message, TEXT);
strcat (message, var);
// Need to free message at some point after you're done with it.
strcat()的第一個參數需要能夠爲連接字符串保留足夠的空間。因此,分配一個足夠空間的緩衝區來接收結果。
char bigEnough[64] = "";
strcat(bigEnough, "TEXT");
strcat(bigEnough, foo);
/* and so on */
的strcat()將串聯的第一個參數的第二個參數,並將結果存儲在第一個參數,返回的char *僅僅是這第一個參數,只爲了您的方便。
你沒有得到一個新分配的字符串,第一個和第二個參數連接起來,我猜你會根據你的代碼預期的。
您試圖將一個字符串複製到靜態分配的地址中。你需要進入緩衝區。
具體做法是:
...略...
目的地
Pointer to the destination array, which should contain a C string, and be large enough to contain the concatenated resulting string.
...略...
http://www.cplusplus.com/reference/clibrary/cstring/strcat.html
這裏有一個例子如好。
避免在C代碼中使用strcat
。最乾淨,最重要的,最安全的方法是使用snprintf
:
char buf[256];
snprintf(buf, sizeof buf, "%s%s%s%s", str1, str2, str3, str4);
一些評論提出了一個問題,參數的數目可能不符合格式字符串和代碼仍然編譯,但大多數編譯器已經問題如果是這樣的話,會發出警告。
...但沒有對sizeof運算符的不必要的和易混淆的括號。只有當你想要一個實際類型的大小,而不是一個對象時才需要這些。寵物提示,抱歉。 – unwind 2008-11-21 13:23:38
這可以說是找出緩衝區大小的最佳方法,除非給出指針。如果你有一個指針,你會傳遞它指向的緩衝區的長度。 – 2008-11-21 13:26:57
跳棋,他在談論圍繞「buf」大小的論點的括號。如果參數是表達式,則不需要它們。但我不明白你爲什麼低調。我認爲你的答案是最好的,即使它是c99。 (也許是因爲他們不同意!lamers!)+1 – 2008-11-21 13:27:27
如果你有C的經驗,你會注意到字符串只是最後一個字符爲空字符的char數組。
現在這很不方便,因爲您必須找到最後一個字符才能追加內容。 strcat
會爲你做到這一點。
因此,strcat通過第一個參數搜索空字符。然後它將用第二個參數的內容替換它(直到它以null結尾)。
現在,讓我們通過您的代碼:
message = strcat("TEXT " + var);
在這裏,您要添加的東西的指針爲「TEXT」(的「TEXT」類型是爲const char *指針。)。
這通常不起作用。另外修改「TEXT」數組將不起作用,因爲它通常放置在一個常量段中。
message2 = strcat(strcat("TEXT ", foo), strcat(" TEXT ", bar));
這可能會更好,除非您再次嘗試修改靜態文本。 strcat不會爲結果分配新的內存。
我提議做這樣的事情,而不是:
sprintf(message2, "TEXT %s TEXT %s", foo, bar);
閱讀的sprintf
的文檔,以檢查它的選項。
現在一個重要的觀點:
確保緩衝區有足夠的空間來保存文本和空字符。有幾個函數可以幫助你,例如,爲你分配緩衝區的strncat和特殊版本的printf。 不確保緩衝區大小將導致內存損壞和可遠程利用的錯誤。
民間,使用STR Ñ CPY(),STR Ñ貓(),或S ñ printf()的。
超出您的緩衝區空間將會破壞內存中的任何其他內容!
(並且記住允許空格用於結尾零'\ 0'字符!)
不僅要記住爲NULL字符留出空間,還需要記住*添加* NULL字符。 strncpy和strncat不會爲你做。 – 2008-11-21 13:36:36
呃? strncpy()和strncat()確定添加終止字符。事實上,他們添加了太多。至少只要緩衝區中留有空間,這對這些調用來說是一個巨大的陷阱。不建議。 – unwind 2008-11-21 13:42:56
不要忘記初始化輸出緩衝區。第一個參數的strcat必須是一個空值終止字符串分配得到的字符串足夠的額外空間:
char out[1024] = ""; // must be initialized
strcat(out, null_terminated_string);
// null_terminated_string has less than 1023 chars
另外的malloc和realloc是有用的,如果你不知道的時間提前許多字符串是如何被連接在一起。
#include <stdio.h>
#include <string.h>
void example(const char *header, const char **words, size_t num_words)
{
size_t message_len = strlen(header) + 1; /* + 1 for terminating NULL */
char *message = (char*) malloc(message_len);
strncat(message, header, message_len);
for(int i = 0; i < num_words; ++i)
{
message_len += 1 + strlen(words[i]); /* 1 + for separator ';' */
message = (char*) realloc(message, message_len);
strncat(strncat(message, ";", message_len), words[i], message_len);
}
puts(message);
free(message);
}
正如人們指出的那樣,字符串處理有了很大的改進。所以你可能想學習如何使用C++字符串庫而不是C風格的字符串。不過這裏是純C的解決方案
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
void appendToHello(const char *s) {
const char *const hello = "hello ";
const size_t sLength = strlen(s);
const size_t helloLength = strlen(hello);
const size_t totalLength = sLength + helloLength;
char *const strBuf = malloc(totalLength + 1);
if (strBuf == NULL) {
fprintf(stderr, "malloc failed\n");
exit(EXIT_FAILURE);
}
strcpy(strBuf, hello);
strcpy(strBuf + helloLength, s);
puts(strBuf);
free(strBuf);
}
int main (void) {
appendToHello("blah blah");
return 0;
}
我不知道它是否是正確的/安全的,但現在我找不到更好的辦法來做到這一點的ANSI C.做
最好的方法它不具有有限緩衝器大小是通過使用asprintf()
char* concat(const char* str1, const char* str2)
{
char* result;
asprintf(&result, "%s%s", str1, str2);
return result;
}
嘗試類似於這樣:
#include <stdio.h>
#include <string.h>
int main(int argc, const char * argv[])
{
// Insert code here...
char firstname[100], secondname[100];
printf("Enter First Name: ");
fgets(firstname, 100, stdin);
printf("Enter Second Name: ");
fgets(secondname,100,stdin);
firstname[strlen(firstname)-1]= '\0';
printf("fullname is %s %s", firstname, secondname);
return 0;
}
甲假設你有一個char [fixed_size]而不是char *,你可以使用一個單一的創造性的宏來以一個<<cout<<like
的順序一次完成所有的操作(「寧可%s不相交%s \ n」,「than」,「 printf樣式格式「)。如果您正在使用的嵌入式系統的工作,這種方法也可以讓你離開了malloc和大*printf
家庭像snprintf()
功能
#include <unistd.h> //for the write example
//note: you should check if offset==sizeof(buf) after use
#define strcpyALL(buf, offset, ...) do{ \
char *bp=(char*)(buf+offset); /*so we can add to the end of a string*/ \
const char *s, \
*a[] = { __VA_ARGS__,NULL}, \
**ss=a; \
while((s=*ss++)) \
while((*s)&&(++offset<(int)sizeof(buf))) \
*bp++=*s++; \
if (offset!=sizeof(buf))*bp=0; \
}while(0)
char buf[256];
int len=0;
strcpyALL(buf,len,
"The config file is in:\n\t",getenv("HOME"),"/.config/",argv[0],"/config.rc\n"
);
if (len<sizeof(buf))
write(1,buf,len); //outputs our message to stdout
else
write(2,"error\n",6);
//but we can keep adding on because we kept track of the length
//this allows printf-like buffering to minimize number of syscalls to write
//set len back to 0 if you don't want this behavior
strcpyALL(buf,len,"Thanks for using ",argv[0],"!\n");
if (len<sizeof(buf))
write(1,buf,len); //outputs both messages
else
write(2,"error\n",6);
字符串也可以在編譯時連接。
#define SCHEMA "test"
#define TABLE "data"
const char *table = SCHEMA "." TABLE ; // note no + or . or anything
const char *qry = // include comments in a string
" SELECT * " // get all fields
" FROM " SCHEMA "." TABLE /* the table */
" WHERE x = 1 " /* the filter */
;
您可以編寫自己的功能,做同樣的事情strcat()
但是這不會改變任何東西:
#define MAX_STRING_LENGTH 1000
char *strcat_const(const char *str1,const char *str2){
static char buffer[MAX_STRING_LENGTH];
strncpy(buffer,str1,MAX_STRING_LENGTH);
if(strlen(str1) < MAX_STRING_LENGTH){
strncat(buffer,str2,MAX_STRING_LENGTH - strlen(buffer));
}
buffer[MAX_STRING_LENGTH - 1] = '\0';
return buffer;
}
int main(int argc,char *argv[]){
printf("%s",strcat_const("Hello ","world")); //Prints "Hello world"
return 0;
}
如果兩個串在一起的超過1000個字符長,將下調1000個字符的字符串。您可以更改MAX_STRING_LENGTH
的值以滿足您的需求。
int main()
{
char input[100];
gets(input);
char str[101];
strcpy(str, " ");
strcat(str, input);
char *p = str;
while(*p) {
if(*p == ' ' && isalpha(*(p+1)) != 0)
printf("%c",*(p+1));
p++;
}
return 0;
}
這是我的解決方案
#include <stdlib.h>
#include <stdarg.h>
char *strconcat(int num_args, ...) {
int strsize = 0;
va_list ap;
va_start(ap, num_args);
for (int i = 0; i < num_args; i++)
strsize += strlen(va_arg(ap, char*));
char *res = malloc(strsize+1);
strsize = 0;
va_start(ap, num_args);
for (int i = 0; i < num_args; i++) {
char *s = va_arg(ap, char*);
strcpy(res+strsize, s);
strsize += strlen(s);
}
va_end(ap);
res[strsize] = '\0';
return res;
}
,但你需要指定你要多少字符串來連接
char *str = strconcat(3, "testing ", "this ", "thing");
我想建議你使用的strlcat提供,而不是strcat的! http://www.gratisoft.us/todd/papers/strlcpy.html – 2008-11-21 13:37:49