开发者

I just can't figure out strcat [duplicate]

This question already has answers here: How do I concatenate const/literal strings in C? (17 answers) Closed 4 years ago.

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 w开发者_开发技巧ould 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"


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


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


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.


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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜