我在用C语言工作,我必须把一些东西连接起来。

现在我有这个:

message = strcat("TEXT ", var);

message2 = strcat(strcat("TEXT ", foo), strcat(" TEXT ", bar));

现在,如果你有C语言的经验,我相信你会意识到,当你试图运行它时,这会给你一个分割错误。我该怎么做呢?


当前回答

尝试修改字符串字面量是未定义的行为,这是类似于:

strcat ("Hello, ", 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.

其他回答

正如人们指出的,字符串处理改进了很多。所以你可能想学习如何使用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。

请使用strncpy()、strncat()或snprintf()。 超过你的缓冲空间将会破坏内存中的任何东西! (并且记住要为尾随的空“\0”字符留出空间!)

假设你有一个char[fixed_size]而不是char*,你可以使用一个单一的,创造性的宏来一次性完成它,使用<<cout<<,比如排序(“而不是%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);

注1,你通常不会像这样使用argv[0]——只是一个例子 注意2,您可以使用输出char*的任何函数,包括用于将整数转换为字符串类型的itoa()等非标准函数。 注意3,如果你已经在程序的任何地方使用了printf,那么没有理由不使用snprintf(),因为编译后的代码会更大(但内联且明显更快)。

您正在尝试将字符串复制到静态分配的地址中。你需要进入缓冲地带。

具体地说:

剪断…

目的地

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

这里也有一个例子。

这就是我的解

#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");