Is there a specific reason for using strcpy and memcpy for different uses? They look to me like the same thing.
Do us all a favor and learn about Data Representation. None of the interfaces will make any sense until you understand Data Representation.
strcpy () is designed to be used on entities that are represented by a variable length series of contiguous bytes which end with a NUL character ('\0').
memcpy () is designed to be used on entities which are represented by a series of contiguous bytes of known length (and which might include NUL characters). These include structs, arrays of structs, arrays of scalars, or any combination. They could even include a group of variable length entities that are NUL terminated provided you know the total length.
If you will notice, there is also a function strncpy () whose parameters look to be exactly the same as memcpy, but memcpy () and strncpy () do very different things (known size vs. variable with a limit).
So, until you understand how the data are represented, none of these functions is particularly useful, but these functions are used all of the time, even if you spend most of your life working with other interfaces. There is more that one way to represent what in other languages might be called a string.
A few of them are "fixed size, (usually blank) padded", "variable size, NULterminated", "variable size, NUL terminated with a limit", and "variable size, possibly with a limit, with an external size". You would probably use memcpy () for the first and last representations, strcpy () for the second,and strncpy () with the third. The thing to keep in mind, is that, in mostother languages, all of these functions would be done with assignment or MOVE statements. In C, you have to manage your own representations. These functions give a little help in copying one entity represented in one of these ways to another place where that entity can be represented.
I have used other data representations and have had to create copying functions for them [most of them use combinations of memcpy (), strcpy (), stncpy (), and memset()]. For instance, a string with a length prefix (called an"MCW") that, if the prefix is a positive is the length of the string, if asmall negative number it is the number of copies of one byte, and, if a large negative number was one of a number of strings from a defined list (which were, of course, MCW prefixed). Copying an MCWString to another MCWString or to the end of a growing block was a snap (and you could even know, in advance, if you needed to flush the block before during or after you added).. Copying from a block to an MCWString in an optimal fashion was decidely non-trivial, but once created, anybody with access to the library could use BlockToMCWString ().
It's all really easy once you understand Data Representationn. It's IMPOSSIBLE until then. What does that suggest to you, Dave? I mean "Bill".