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 managementmalloc, calloc, realloc, and free, and what happens when you get them wrong.

Finished reading? Mark it complete to track your progress.

On this page