所以我正在尝试将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
吗?提前谢谢。
答案 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在每次调用时分配一个新的缓冲区,在这种情况下,你需要再次释放缓冲区。