Code of the Day
IntermediatePointers

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.

Lab · optionalCIntermediate30 min
Recommended first

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:

  1. Read the character at *src.
  2. Write it to *dst.
  3. Increment src (post-increment: happens after the value is read).
  4. 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 strcmp result 0 vs positive vs negative

The next module is Memory management — malloc, calloc, realloc, and free, and what happens when you get them wrong.

Finished reading? Mark it complete to track your progress.

On this page