-1

I posted this code elsewhere to get insight on why it didn't output "ratdog" as expected. Someone said there wasn't enough room to append "dog" to "rat" or something. What did they mean?

#include <stdio.h>

char *strcat(char*, char*);

char* strcat(char *s, char *t) {
    char* result = *s;
    while(*s != '\0')
        printf("%s", *s);
        *s++;   // advance pointer until you reach the null terminator.

    while(*t != '\0')
        *s = *t;    // copy t to the end of s until we reach the end of t.
    return (char*) result;
}

int main() {
    char rat[] = "rat";
    char dog[] = "dog";
    printf("%s", strcat(rat, dog));
    return 0;
}
Lanegan
  • 29
  • 5
  • 1
    Your posted code won't compile. https://repl.it/@robertwharvey/AltruisticNewShelfware – Robert Harvey Jan 04 '20 at 17:53
  • 1
    The code also has an infinite loop (the first one counting from the top). The line `*s++;` is not inside the loop - and that's why you should always use curly brackets (at the very least until you are well-acquainted with C/C++ and know exactly what you are doing). – 0x4d45 Jan 04 '20 at 17:57

2 Answers2

1

There are 3 problems with your code :

  1. Increment t and s while copying, otherwise it's an infinite loop.

    while(*t != '\0')
      *s = *t; //See you're only assigning
    
    while(*t != '\0')
      *(s++) = *(t++); //increment them
    

Similarly, as mentioned in comments by @ihonen : *s++; // advance pointer until you reach the null terminator. is not inside loop body.

  1. Allocate more memory for data - source pointer points to, so that it can contain concatenated string and \0.

      char rat[7] = "rat"; //See i am allocating len(rat) + len(dog) + '\0' = 3+3+1 = 7 
      char dog[] = "dog";
      printf("%s", strcat(rat, dog));
    
  2. Thirdly, you'd want to append \0 to *s after second loop like this *s = '\0'

H S
  • 1,211
  • 6
  • 11
  • Why do #3? That's how C knows when the string is done right? – Lanegan Jan 06 '20 at 17:48
  • 1
    Yup, It serves as a reserved character used to signify the end of a string,often called a null-terminated string(https://en.wikipedia.org/wiki/Null-terminated_string) – H S Jan 06 '20 at 18:20
0

If your code you are doing this:

    char rat[] = "rat";
    char dog[] = "dog";

It is implicit in these lines that the compiler will allocate space, of type char, to hold these 3 characters, plus an extra null terminator (so 4 bytes total).

If you then try to append to one of these strings, it won't work, because you declared them statically and the space in memory was allocated at that time. Once you create a variable in C, the amount of space available is fixed unless you explicitly change it later. So, exactly as you stated: the variable rat is pointing to a memory location that was allocated to hold 3 characters plus the null terminator, and there is no room to add "dog" to the end.

If you need "ratdog" then you need to create a new variable that is large enough to hold it.

you could do it like this:

#include <stdio.h>
#include <string.h>
int main(void) {
    char rat[] = "rat";
    char dog[] = "dog";
    char ratdog[7];

    strncpy(ratdog, rat, 3);
    strncpy(&ratdog[3], dog, 4);
    printf("%s", ratdog);
    return 0;
}

Notice that the second strncpy is copying four bytes. The 4th byte is the null terminator from dog.

Hypothetically, if rat was created using one of the malloc functions, you could also try extending its size using realloc, but that won't work in this case.

Z4-tier
  • 7,287
  • 3
  • 26
  • 42
  • Why not: `char rat[7] = "rat";`? Also you don't have to hard-code the last argument of `strncpy()`, you could write: `strncpy(ratdog, rat, strlen(rat));` and `strncpy(ratdog + 3, dog, sizeof(dog));` – machine_1 Jan 04 '20 at 18:17
  • sure, you could do that too. I hard coded the `strncpy` size argument to clearly illustrate the need to get that `\0` from `dog`. It's a contrived example, I'm not planning to release this to production :) – Z4-tier Jan 04 '20 at 18:22
  • 1
    Reason for not using `char rat[7] = "rat";` is really just because that is how the original question was framed. Doing it as you suggest would definitely make it easier, but might miss the intent of the original question. – Z4-tier Jan 04 '20 at 18:25