Strings: Copy
Now that we have learned how to calculate the length of the string, let's talk about one more standard string function which is called strcpy and copies one string into another.
As you remember, strings in C are char arrays that end with a special zero character. So, to copy one string into another, you need to iterate over the source string until you see 0, and copy each character, one by one, to the destination string. Then make sure to write the terminating 0 to the destination string, otherwise your new string will not be terminated and it will cause problems: no one will know where your string actually ends.
The standard strcpy function from string.h accepts two parameters, destination and source, and they come in this order: destination first, then source. It might look a little bit weird at first, but it's easy to remember: the order is the same as in the assignment operator.
Try to implement your own strcpy, and then we'll talk more. By convention–and also to make its behavior similar to the behavior of the assignment operator–strcpy always returns destination; not that it's very useful in the real life but let's keep it this way, so we return char *:
#include <stdio.h>
char *strcpy(char *destination, char *source) {
// TODO: copy source to destination
// don't forget the trailing 0!
return destination;
}
int main() {
// Test code, do not change
char *s[20];
char *res1 = strcpy(s, "hello world");
printf("<%s> %d\n", res1, res1 == s);
char *res2 = strcpy(s, "short");
printf("<%s> %d\n", res2, res2 == s);
return 0;
}
Note that in the test code in the main function I copy the longer string "hello world" to s first, and then the shorter string "short" on top of it; if you happened to forget the trailing 0, the second printf would not stop and will print something starting with "short world". We don't know what will happen next, since s is uninitialized at the beginning, so it may or may not be filled with zeros, so there is no guarantee that printing will stop where you expect it to stop if you don't explicitly put 0 at the end.
Now, let's take a look at this code, which is really classic C:
while (*destination++ = *source++)
;
To understand these two lines of code, we need to collect a lot of information discussed earlier.
Finally, the while loop executes while the condition is true, which in C means while it is not equal to zero.
With all this in mind, let's decouple these two lines:
while ( /* while the following expression is not zero */
*destination /* the character that the pointer destination points to */
++ /* increment the pointer but return the old value */
= /* is assigned the value of */
*source /* the character that the pointer source points to */
++ /* increment the pointer but return the old value */
)
; /* empty loop body */
How cool is that? Follow me here: first, to evaluate the while loop condition, it will assign *destination = *source, copying the first (0th) character of source to destination, and increment both source and destination so they both point to the next character (note that the pointer position in an assignment is the old position, i.e. the one before incrementing). Then, the assigned value (the character itself, not a pointer) will be compared with 0, so if we just happened to assign the last character of the source string-the terminating 0–we will exit the loop.
Don't write your code like that until you are very comfortable with this approach, but make sure you spend some time here to understand how this works. As I said, this is classic, and very important.
Also, feel free to copy that loop above and verify that it indeed works! Note that you cannot return destination after the destination has changed, so you would need to save it (char *saved_destination = destination) and return it instead.
We'll keep talking about strings on the following page!