C将char附加到char *

时间:2012-10-17 16:53:26

标签: c string char segmentation-fault append

所以我正在尝试将char附加到char*

例如我有char *word = " "; 我也有char ch = 'x';

我做append(word, ch);使用此方法..

void append(char* s, char c)
{

    int len = strlen(s);
    s[len] = c;
    s[len+1] = '\0';
}

它给了我一个分段错误,我理解为什么我想。因为s[len]超出范围。我该如何制作呢?我需要清除char*,如果我使用像char word [500]这样的东西;一旦附加了一些字符,我该如何清除?它的strlen总是500吗?提前谢谢。

5 个答案:

答案 0 :(得分:11)

典型的C练习如下:

//returns 1 if failed, 0 if succeeded 
int  append(char*s, size_t size, char c) {
     if(strlen(s) + 1 >= size) {
          return 1;
     }
     int len = strlen(s);
     s[len] = c;
     s[len+1] = '\0';
     return 0;
}

当传递一个函数时,一个数组来修改函数在编译时不知道它有多少空间。 C中的常规做法是传递数组的长度,如果函数不能在它所拥有的空间中完成工作,函数将信任该约束并失败。另一种选择是重新分配并返回新数组,您需要返回char*或将char**作为输入,但在这种情况下您必须仔细考虑如何管理堆内存。但是,如果没有重新分配,是的,如果在没有剩余空间的情况下要求追加,你的函数必须以某种方式失败,这取决于你如何失败。

答案 1 :(得分:5)

很难在C语言中附加到字符串中。尝试这样的事情:

char *append(const char *s, char c) {
    int len = strlen(s);
    char buf[len+2];
    strcpy(buf, s);
    buf[len] = c;
    buf[len + 1] = 0;
    return strdup(buf);
}

确保在完成后取消分配返回的字符串。

仅供参考:因为您传递的字符串存储在只读内存中,所以会出现段错误。但是你是对的,你也在写完([len+1]写,而不是[len])。

答案 2 :(得分:3)

如果你传入

append("foo", 'X');

它会崩溃,因为foo通常放在只读存储中。即使不是它也可能会覆盖不好的东西! 在这种情况下,编译器是否应该警告您从const char *转换为char *这将是一个线索。

答案 3 :(得分:0)

是的,你所做的假设 - 几乎是正确的 - 崩溃可能是因为你试图写过字符串的边界(实际上只有s[strlen(s) + 1]超出范围,因为{{1} }仍然是一个有效的位置 - 终止NUL字节存储在那里)。但是你也无法修改字符串文字,因为它通常位于进程内存的某些只读部分。这两个操作都会导致调用未定义的行为,这些行为可能会崩溃。您可以通过将字符串复制到动态分配的存储,然后修改副本来解决此问题。此外,您应该在函数的参数中使用s[strlen(s)],因为const char *表示无法传入只读字符串。

char *

另外,当不再需要时,不要忘记char *append(const char *orig, char c) { size_t sz = strlen(orig); char *str = malloc(sz + 2); strcpy(str, orig); str[sz] = c; str[sz + 1] = '\0'; return str; } 返回的字符串。

答案 4 :(得分:0)

你无法真正安全地附加到任意字符串,因为首先,字符串常量往往是在只读内存中,所以尝试写入它们可能会导致分段错误,其次,你没有保证,如果他们已经通过你一个缓冲区,你没有拍到它的结尾。

特别是,如果你这样做     char x [500];

不能保证strlen(x)会返回500.它将返回它在x到达null之前从x的开头向前计数的字符数。它可能会返回0,1 ... 500,501 ......,具体取决于x中的内容。

实际上你唯一的选择就是调用append和你要追加的缓冲区的大小(这样你可以在缓冲区已满的情况下做一些事情),或者让append在每次调用时分配一个新的缓冲区,在这种情况下,你需要再次释放缓冲区。