2012-10-17 119 views
7

所以我试图追加一个charchar*C追加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 [500]这样的字符,我还需要清除char*;一旦它附加了一些字符,我将如何清除它?它的strlen是否总是500?提前致谢。

+2

“因为s [len]超出范围。” < - 非常适合初学者!恭喜。但是,您仍然有其他错误 - 字符串文字是只读的,您无法修改其内容。 – 2012-10-17 16:56:24

+2

@ H2CO3's [len + 1]'超出界限。 '[len]'是空字节,它不被'strlen'计数。 – pmr

+0

@pmr是的,技术上是正确的。我应该写'sizeof(s)'代替。 – 2012-10-17 17:01:52

回答

10

典型的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**作为输入,但您必须仔细考虑如何在这种情况下管理堆内存。但没有重新分配,是的,你的功能必须以某种方式失败,如果它被要求追加时没有剩余空间,它是为你如何失败。

+0

这是不好的答案,因为您不知道* s是否包含字符串文字。它们通常存储在只读存储器中,如果您修改它们,可能会导致访问冲突。你的代码可能工作,但它被认为是未定义的行为。 – user1888162

+0

@ user1888162如果您传递大量数据,它也是UB。 – djechlin

3

如果你正在传递

append("foo", 'X'); 

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

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]之一)。

+0

char buf [len + 2]可能无法编译,具体取决于其编译器的版本 –

0

是的,你所做的假设是 - 几乎是 - 正确的 - 崩溃可能是因为你试图写过去的字符串(实际上只s[strlen(s) + 1]是出界,因为s[strlen(s)]仍然是一个有效的位置的边界 - 终止的NUL字节存储在那里)。但是你也不能修改字符串文字,因为它通常在进程内存的一些只读部分。这两种行为都会导致调用未定义的行为,这些行为可能会崩溃。您可以通过将字符串复制到动态分配的存储器然后修改副本来解决此问题。此外,你应该在你的函数的参数中使用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; 
} 

此外,当不是不再需要它不要忘了free()返回的字符串。

0

你不能安全地追加到任意字符串,因为首先,字符串常量倾向于在只读内存中,所以试图写入它们可能会导致分段错误,其次,你有不保证如果他们已经通过了你一个缓冲区,你还没有结束它的射击。

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

不能保证strlen(x)会返回500.它会返回从x的起始位置开始计数前有多少个字符。它可能会返回0,1 ... 500,501 ...,这取决于x中的内容。

真的,你唯一的选择是调用append与你追加的缓冲区的大小(所以你可以做一些适当的东西,如果缓冲区已满),或使append每次调用时分配一个新的缓冲区,在这种情况下,您将需要再次释放缓冲区。