我只是想不通strcat

我知道我不应该使用这个function,我不在乎。 上次我检查了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"; 

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

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

一些问题……

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

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

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

正如你可能猜到的那样,对于一个新手来说,这应该是多么有用。 我说有一个原因:一般来说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); 

你需要:

  • 可写的记忆
  • 足够的空间

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

相反,做:

 char foo[255] = "foo"; 

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

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

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

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

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

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