我只是不明白 strcat

发布于 2024-10-12 21:49:38 字数 566 浏览 8 评论 0原文

我知道我不应该使用该功能,而且我不在乎。上次我检查 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";

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

I know I shouldn't be using that function, and I don't care. Last time I checked the spec for strcat, it said something along the lines of updating the first value as well as returning the same.

Now, this is a really stupid question, and I want you to explain it like you're talking to a really stupid person.

Why won't this work?

char* foo="foo";
printf(strcat(foo,"bar"));

EDIT: I don't know the difference between char[] and char*. How would I allocate a string of 255 characters?

EDIT 2: OK, OK, so char[number] allocates a string of that many bytes? Makes sense. Thanks.

EDIT 3: Also, how would I use a character array without declaring it? Would I typecast it as char[255]?

EDIT 4: strcat((char[256])"foo","bar") returns an error. I'm about fed up with C.

EDIT 5: So does strcat((char[256])"foo",(char[])"bar").

EDIT 5:

char[256] foo="bar";

Real smooth. "identifier expected"

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

无尽的现实 2024-10-19 21:49:38

几个问题...

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(n2) 因为重复遍历细绳。如果需要重复连接字符串,则应该维护一个指向字符串当前末尾的指针并从那里进行复制。

更新:您可以如何执行最后一个建议的示例如下...

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

A few problems...

1.
foo is constant here. You cannot modify string literals.

2.
The contract for strcat is that the first parameter is large enough to fit the concatenated string. So more realistically you'd do something this...

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

strcat(foo, "bar");

3.
As you might guess, it's not obvious to a newcomer how this is supposed to work. I say there's a reason for this: in general strcat is considered quite bad. A good C interface for interacting with buffers of potentially arbitrary length will make this a lot more explicit. You might want to look at strncat or strlcat which track sizes.

I would say in general though if you're using the strcat family you're doing something wrong. Each call to strcat will have to traverse the string to find where the end is. Imagine you are doing a lot of these operations -- it's very easy to imagine something that can easily be done in O(n) steps suddenly turning into O(n2) because of the repeated traversal of the string. If you need to concatenate to a string repeatedly, you should be maintaining a pointer to the current end of the string and doing the copy from there.

Update: Example of how you might do this last suggestion follows...

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

Then you might use this as follows:

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);
星光不落少年眉 2024-10-19 21:49:38

您需要:

  • 可写内存
  • 足够的空间

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

相反,请执行以下操作:

char foo[255] = "foo";

You need:

  • writable memory
  • sufficient space

String constants provide only the exact amount of memory in the literal and they aren't supposed to be written.

Instead, do:

char foo[255] = "foo";
请你别敷衍 2024-10-19 21:49:38

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

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

  • 它需要可写
  • 它需要足够的可用空间来保存复制到其中的第二个字符串

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

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

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

strcat is pretty simple -- it takes pointer to a buffer containing a string and pointer to another string, and copies that second string into the buffer at the end of the string that's already there.

Note the difference between the two arguments. Both are char *, but the first is really a pointer to a buffer and only incidentally a pointer to a string (thats already in the buffer). As a buffer, it needs two things that a simple string does not:

  • it needs to be writable
  • it needs enough free space to hold the second string that is being copied into it

In your example, you try to use char *foo="foo"; as the first argument, but its just a string and is missing both of the requirements for the buffer. Instead you need to do something like:

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

Now we're declaring foo as a writable char array with plenty of space to hold both strings -- an adequate buffer. This gets into the problem that most people have with strcat, which is the second requirement above -- how do you know if the buffer has enough space? In a simple example like this it does, but for more complex examples (where you don't necessarily know how long the strings are) it gets much harder. You end up needing to keep track of how big your buffer is, and use strlen to see how long the strings are to make sure they'll fit BEFORE you call strcat. This is both inefficient (you end up scanning over string strings multiple times to find lengths and then to copy) and error prone.

甲如呢乙后呢 2024-10-19 21:49:38
char* foo="foo";

是一个字符串文字。

无法被修改。相反,请执行 char [] foo = "foo"; 但请记住,像这样使用 strcat 会在这种情况下导致问题,因为它会在尝试 时写入内存,而它不应该写入内存中strcat "bar" so 你应该尝试类似 char foo[30] = "foo";

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

尝试一下:

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

is a string literal.

It can't be modified. Do char [] foo = "foo"; instead but keep in mind that using strcat like that, will cause problems in this case cause it will write in memory it shouldn't when trying to strcat "bar" so you should try something like char foo[30] = "foo";

Edit: The typecasting you do... sorry I do not have so many brain cells as to try to explain you what you are trying to do. I can only tell you it is wrong. you need to provide a memory location so strcat() can work.

Try that :

int main()
{
    char foo[255]="foo";
    printf("%s",strcat(foo,"bar"));
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文