我在C工作,我必须连接一些东西。
现在我有这个:
message = strcat("TEXT ", var);
message2 = strcat(strcat("TEXT ", foo), strcat(" TEXT ", bar));
现在,如果您有C语言经验,我确信您在尝试运行时会发现这会给您带来分段错误。那么我该如何解决这个问题?
答案 0 :(得分:328)
在C中,“字符串”只是普通的char
数组。因此,您无法直接将它们与其他“字符串”连接起来。
您可以使用strcat
函数,该函数将src
指向的字符串附加到dest
指向的字符串的末尾:
char *strcat(char *dest, const char *src);
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);
答案 1 :(得分:227)
避免在C代码中使用strcat
。最干净,最重要的是,最安全的方法是使用snprintf
:
char buf[256];
snprintf(buf, sizeof buf, "%s%s%s%s", str1, str2, str3, str4);
一些评论者提出了一个问题,即参数的数量可能与格式字符串不匹配,代码仍会编译,但如果是这种情况,大多数编译器都会发出警告。
答案 2 :(得分:23)
伙计,使用str n cpy(),str n cat()或s n printf()。
超过你的缓冲空间会丢弃内存中的其他内容!
(并且记得为尾随的空'\ 0'字符留出空间!)
答案 3 :(得分:16)
如果你事先不知道连接多少个字符串,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);
}
答案 4 :(得分:14)
字符串也可以在编译时连接。
#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 */
;
答案 5 :(得分:5)
不要忘记初始化输出缓冲区。 strcat的第一个参数必须是一个以空字符结尾的字符串,并为结果字符串分配足够的额外空间:
char out[1024] = ""; // must be initialized
strcat( out, null_terminated_string );
// null_terminated_string has less than 1023 chars
答案 6 :(得分:4)
strcat()的第一个参数需要能够为连接字符串保留足够的空间。因此,请分配一个具有足够空间的缓冲区来接收结果。
char bigEnough[64] = "";
strcat(bigEnough, "TEXT");
strcat(bigEnough, foo);
/* and so on */
strcat()将第二个参数与第一个参数连接起来,并将结果存储在第一个参数中,返回的char *只是第一个参数,只是为了您的方便。
你没有得到一个新分配的字符串,第一个和第二个参数连接在一起,我猜你根据你的代码预期了。
答案 7 :(得分:4)
在没有有限缓冲区大小的情况下执行此操作的最佳方法是使用asprintf()
char* concat(const char* str1, const char* str2)
{
char* result;
asprintf(&result, "%s%s", str1, str2);
return result;
}
答案 8 :(得分:4)
正如人们所指出的那样,字符串处理有所改善。所以你可能想学习如何使用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中找到更好的方法。
答案 9 :(得分:3)
尝试修改字符串文字是未定义的行为,类似于:
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.
答案 10 :(得分:2)
您可以编写自己的函数,与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
的值以满足您的需求。
答案 11 :(得分:1)
如果您有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。 不确保缓冲区大小会导致内存损坏和远程利用错误。
答案 12 :(得分:1)
假设你有一个char [fixed_size]而不是char *,你可以使用一个单一的创意宏来一次性<<cout<<like
排序(相反,%s是脱节的%s \ n “,”而不是“,”printf样式格式“)。如果您正在使用嵌入式系统,此方法还允许您省略malloc和*printf
等大型snprintf()
函数系列(这使得dietlibc不会抱怨* printf)
#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);
答案 13 :(得分:1)
您正在尝试将字符串复制到静态分配的地址中。你需要进入一个缓冲区。
具体做法是:
...略...
目的地
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
这里也有一个例子。
答案 14 :(得分:1)
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;
}
答案 15 :(得分:0)
尝试类似的内容:
#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;
}
答案 16 :(得分: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");