Lab: Implement strlen and strcpy from scratch
Build your own versions of strlen, strcpy, strcmp, and strcat using raw pointer manipulation — cementing everything from the Pointers module.
The best way to understand C's string library is to implement it yourself. In this lab you will write my_strlen, my_strcpy, my_strcmp, and my_strcat using nothing but pointer arithmetic and dereferences — no standard library functions for the core logic.
Goal
Create mystring.c with these four functions:
size_t my_strlen(const char *s);
char *my_strcpy(char *dst, const char *src);
int my_strcmp(const char *a, const char *b);
char *my_strcat(char *dst, const char *src);Test each in main against the standard library version to verify they produce the same results.
Hints
my_strlen: Walk a pointer forward from s until it hits '\0'. The distance travelled is the length.
my_strcpy: Walk src forward, copying each character to dst, until you copy the '\0'. Return the original dst.
my_strcmp: Walk both strings simultaneously. Stop when the characters differ or both hit '\0'. Return the difference of the diverging characters (cast to unsigned char).
my_strcat: Advance dst past its null terminator, then run my_strcpy from that point.
Worked solution
#include <stdio.h>
#include <string.h>
size_t my_strlen(const char *s) {
const char *start = s;
while (*s) { s++; }
return (size_t)(s - start);
}
char *my_strcpy(char *dst, const char *src) {
char *ret = dst;
while ((*dst++ = *src++) != '\0') { /* empty body */ }
return ret;
}
int my_strcmp(const char *a, const char *b) {
while (*a && (*a == *b)) {
a++;
b++;
}
return (int)(unsigned char)*a - (int)(unsigned char)*b;
}
char *my_strcat(char *dst, const char *src) {
char *ret = dst;
while (*dst) { dst++; } /* advance to null terminator */
my_strcpy(dst, src); /* copy src starting there */
return ret;
}
int main(void) {
/* Test my_strlen */
printf("my_strlen tests:\n");
printf(" \"\" = %zu (expected %zu)\n", my_strlen(""), strlen(""));
printf(" \"Hello\" = %zu (expected %zu)\n", my_strlen("Hello"), strlen("Hello"));
/* Test my_strcpy */
char buf[20];
my_strcpy(buf, "Hello");
printf("\nmy_strcpy: \"%s\" (expected \"Hello\")\n", buf);
/* Test my_strcmp */
printf("\nmy_strcmp tests:\n");
printf(" (\"abc\", \"abc\") = %d (expected 0)\n", my_strcmp("abc", "abc"));
printf(" (\"abc\", \"abd\") = %d (expected <0)\n", my_strcmp("abc", "abd") < 0 ? -1 : 1);
printf(" (\"b\", \"a\") = %d (expected >0)\n", my_strcmp("b", "a") > 0 ? 1 : -1);
/* Test my_strcat */
char s[30] = "Hello";
my_strcat(s, ", World!");
printf("\nmy_strcat: \"%s\" (expected \"Hello, World!\")\n", s);
return 0;
}The *dst++ = *src++ idiom
The assignment *dst++ = *src++ does four things in one expression:
- Read the character at
*src. - Write it to
*dst. - Increment
src(post-increment: happens after the value is read). - Increment
dst(post-increment: happens after the value is written).
The loop condition checks whether the character just written was '\0' — if it was, the loop exits (after writing the null terminator). This idiom is so common in C string code that you will see it in the standard library's implementation.
Extension: my_strncpy and my_strncat
Implement the "safe" versions:
char *my_strncpy(char *dst, const char *src, size_t n);
char *my_strncat(char *dst, const char *src, size_t n);Remember: strncpy pads with null bytes if src is shorter than n, but does NOT null-terminate if src is longer. strncat always null-terminates.
What you practised
- Pointer traversal and arithmetic
- The
*p++idiom for combined read/advance - Returning pointers from functions (the original
dst) - The difference between
strcmpresult0vs positive vs negative
The next module is Memory management — malloc, calloc, realloc, and free, and what happens when you get them wrong.
Common pointer bugs
Identify and understand the most dangerous pointer bugs in C — null dereference, dangling pointers, double free, wild pointers, and off-by-one out-of-bounds accesses.
Stack vs. heap
Understand the two memory regions every C program uses — the stack for local variables and the heap for dynamic allocation — and when to use each.