我只是想不通strcat

时间:2011-01-16 20:40:25

标签: c string char strcat

我知道我不应该使用这个功能,我也不在乎。上次我检查了strcat的规范时,它说了更新第一个值以及返回相同的内容。

现在,这是一个非常愚蠢的问题,我希望你解释一下,就像你和一个非常愚蠢的人说话一样。

为什么这不起作用?

char* foo="foo";
printf(strcat(foo,"bar"));
编辑:我不知道char []和char *之间的区别。我如何分配255个字符的字符串?

编辑2:好的,好的,所以char [number]分配了那么多字节的字符串?说得通。感谢。

编辑3:另外,如何在不声明字符数组的情况下使用字符数组?我会将它作为char [255]进行类型转换吗?

编辑4:strcat((char [256])“foo”,“bar”)返回错误。我对C感到厌烦。

编辑5:strcat((char [256])“foo”,(char [])“bar”也是如此。

编辑5:

char[256] foo="bar";

真正顺利。 “预期的标识符”

4 个答案:

答案 0 :(得分:3)

一些问题......

1。 foo在这里不变。您无法修改字符串文字。

2。 strcat的合同是第一个参数足够大以适应连接字符串。更现实地说,你会做点什么......

char foo[8] = "foo";  /* Note that buffer size is larger than the string... */

strcat(foo, "bar");

3。 正如你可能猜到的那样,对于一个新手来说,这应该是怎么回事并不明显。我说这是有原因的:一般来说strcat被认为是非常糟糕的。用于与可能任意长度的缓冲区交互的良好C接口将使这更加明确。您可能希望查看跟踪大小的strncatstrlcat

总的来说,如果你使用的是strcat家庭,你会做错事。每次调用strcat都必须遍历字符串以查找结尾的位置。想象一下,你正在进行大量的这些操作 - 很容易想象一些事情很容易在O(n)步骤中突然变成O(n 2 )因为重复遍历串。如果需要重复连接到字符串,则应该维护指向字符串当前末尾的指针并从那里执行复制。

更新:如何执行此最后建议的示例如下......

struct string
{
   char *current_end;
   size_t bytes_remaining;
};

int
smart_concat(struct string *str, const char *tail)
{
   size_t new_length = strlen(tail);

   /* Do we have enough space?  (include NUL character) */
   if (new_length + 1 < str->bytes_remaining)
   {
      /* Evidently not... */
      return -1;
   }

   /* Copy the string...  (including NUL character) */
   memcpy(str->current_end, tail, new_length + 1);

   /* Update the pointer to the end of our string, and bytes remaining.. */
   str->current_end += new_length;
   str->bytes_remaining -= new_length;

   return 0;
}

然后你可以按如下方式使用它:

struct string str;
char buffer[some_size];

/* Initialize the structure to point at our buffer... */
str.current_end = buffer;
str.bytes_remaining = sizeof(buffer);

/* Strictly speaking, you should check the return code for overflow... */
smart_concat(&str, "foo");
smart_concat(&str, "bar");

/* Print out the result: */
puts(buffer);

答案 1 :(得分:2)

你需要:

  • 可写内存
  • 足够的空间

字符串常量仅提供文字中的确切内存量,并且不应写入它们。

相反,请执行:

char foo[255] = "foo";

答案 2 :(得分:2)

strcat非常简单 - 它指向包含字符串和指向另一个字符串的指针的缓冲区,并将第二个字符串复制到已经存在的字符串末尾的缓冲区中。

注意两个参数之间的区别。两者都是char *,但第一个实际上是指向缓冲区的指针,只是偶然指向字符串的指针(已经在缓冲区中)。作为一个缓冲区,它需要两个简单字符串不能的东西:

  • 它需要是可写的
  • 它需要足够的可用空间来容纳正在复制到其中的第二个字符串

在您的示例中,您尝试使用char *foo="foo";作为第一个参数,但它只是一个字符串,并且缺少缓冲区的两个要求。相反,你需要做类似的事情:

char foo[16] =  "foo";
printf(strcat(foo, "bar"));

现在我们将foo声明为可写char数组,并且有足够的空间来容纳两个字符串 - 一个足够的缓冲区。这就解决了大多数人对strcat的问题,这是上面的第二个要求 - 你怎么知道缓冲区是否有足够的空间?在这样一个简单的例子中,但是对于更复杂的例子(你不一定知道字符串有多长),它变得更加困难。您最终需要跟踪缓冲区的大小,并使用strlen来查看字符串的长度,以确保在调用strcat之前它们是否适合。这既效率低下(最后多次扫描字符串字符串以查找长度然后复制)并且容易出错。

答案 3 :(得分:1)

char* foo="foo";

是一个字符串文字。

无法进行修改。请改为char [] foo = "foo";,但请记住,使用这样的strcat会在这种情况下导致问题,因为它会在内存中写入时不应该尝试strcat“bar”所以你应该试试像char foo[30] = "foo";

这样的东西

编辑:你做的类型转换...抱歉,我没有那么多的脑细胞,试图解释你想要做什么。我只能告诉你这是错的。您需要提供内存位置,以便strcat()可以正常工作。

试试:

int main()
{
    char foo[255]="foo";
    printf("%s",strcat(foo,"bar"));
}