Part of C in 100s

C in 100 Seconds: Strings | Episode 11

Celest KimCelest Kim

Video: C in 100 Seconds: strlen strcpy strcmp — Strings in C | Episode 11 by Taught by Celeste AI - AI Coding Coach

Take the quiz on the full lesson page
Test what you've read · interactive walkthrough

C Strings: strlen, strcpy, strcmp

A C string is a char[] (or char*) ending in '\0'. strlen counts bytes before \0. strcpy copies. strcmp compares. All from <string.h>.

C doesn't have a real string type. Strings are arrays of char with a sentinel null terminator. Every "string function" is just a loop over a char array.

The basic shape

#include <stdio.h>
#include <string.h>

int main() {
  char name[] = "Alice";
  printf("Name: %s\n", name);
  printf("Length: %lu\n", strlen(name));

  char copy[20];
  strcpy(copy, name);
  printf("Copy: %s\n", copy);

  printf("Equal? %d\n", strcmp(name, copy) == 0);
  printf("Compare: %d\n", strcmp("apple", "banana"));

  return 0;
}

Output:

Name: Alice
Length: 5
Copy: Alice
Equal? 1
Compare: -1

What "Alice" really is

char name[] = "Alice";

This declares name as a char array of size 6:

name[0] = 'A'
name[1] = 'l'
name[2] = 'i'
name[3] = 'c'
name[4] = 'e'
name[5] = '\0'   // null terminator

The '\0' is a single byte with value 0. It marks the end of the string. Every C string function knows to stop when it sees \0.

sizeof(name) is 6 (5 chars + terminator). strlen(name) is 5 (chars excluding terminator).

strlen

size_t strlen(const char *s);

Walks the string until it hits \0, returns the count.

strlen("Alice")   // 5
strlen("")        // 0
strlen("hi\nworld")   // 8 (\n is one byte)

strlen is O(n). For a string used in a hot loop, cache the length:

size_t len = strlen(name);
for (size_t i = 0; i < len; i++) { ... }   // good

for (size_t i = 0; i < strlen(name); i++) { ... }  // O(n²) — recomputes each iteration!

strcpy

char *strcpy(char *dest, const char *src);

Copies src (including its \0) into dest. Returns dest.

char copy[20];
strcpy(copy, "Hello");
// copy = "Hello\0..."

dest must have enough space. If src is longer than dest's capacity, strcpy writes past the end → buffer overflow. Catastrophic; classic security bug.

For safer copying, use strncpy(dest, src, n) (limits to n bytes) or — better — snprintf(dest, n, "%s", src):

char copy[20];
snprintf(copy, sizeof(copy), "%s", source);
// always null-terminated, never overflows

strncpy has its own quirk: doesn't always null-terminate if n characters fit without space for \0. snprintf always terminates.

strcmp

int strcmp(const char *a, const char *b);

Compares lexicographically.

  • Returns 0 if equal.
  • Negative if a < b (in dictionary order).
  • Positive if a > b.
strcmp("apple", "apple")   // 0
strcmp("apple", "banana")  // negative (a < b)
strcmp("banana", "apple")  // positive
strcmp("Apple", "apple")   // negative ('A' = 65 < 'a' = 97)

The exact value isn't standardized — could be -1, -27, etc. Just check the sign.

For "is this string equal to that one":

if (strcmp(s1, s2) == 0) { ... }   // equal

Don't write if (s1 == s2) — that compares pointer addresses.

strcmp vs strncmp

strncmp(a, b, n) compares at most n characters. Useful for prefix matching:

if (strncmp(line, "GET ", 4) == 0) {
  // HTTP GET request
}

Reading user input

char buf[100];
scanf("%s", buf);    // reads one whitespace-separated word

Episode 12 covers scanf properly. For now: %s reads a word; the buffer must be large enough.

String literals are read-only

char *s = "hello";
s[0] = 'H';     // SEGFAULT! Modifying read-only memory.

String literals ("...") live in read-only memory. Modifying them is undefined behavior — usually a crash.

For mutable strings, declare an array:

char s[] = "hello";   // s is an array; modifying s[0] is fine
s[0] = 'H';

The difference: char *s = "..." is a pointer to literal memory. char s[] = "..." copies the literal into a local array.

Concatenation: strcat

char buf[20] = "Hello, ";
strcat(buf, "World!");
printf("%s\n", buf);   // "Hello, World!"

strcat(dest, src) appends src to dest. dest must have enough room for the original + new + \0. Same overflow risk as strcpy. Use strncat or snprintf for safety.

Common operations summary

Function Purpose
strlen(s) Length excluding \0
strcpy(dest, src) Copy (unsafe — no length check)
strncpy(dest, src, n) Copy at most n bytes (may not null-terminate)
snprintf(dest, n, ...) Safe alternative to strcpy/strcat
strcat(dest, src) Concatenate (unsafe)
strncat(dest, src, n) Concatenate at most n bytes
strcmp(a, b) Compare (0 = equal)
strncmp(a, b, n) Compare first n bytes
strchr(s, c) Find first char (returns pointer or NULL)
strstr(s, sub) Find substring
strdup(s) Allocate and copy (frees with free)

Most of these are episode 32. The ones in this lesson — strlen, strcpy, strcmp — are the foundational three.

Common mistakes

Buffer overflow. strcpy(small, "very long string") writes past small. Always check sizes; prefer snprintf.

Modifying string literals. char *s = "hi"; s[0] = 'H'; crashes. Use char s[] = "hi" instead.

Comparing with ==. Compares pointers. Use strcmp(a, b) == 0.

Forgetting \0. Constructing a string manually: char s[5] = {'h','e','l','l','o'} has no terminator — strlen runs off the end.

strlen in a loop condition. for (i = 0; i < strlen(s); i++) re-walks the string each iteration. Cache the length once.

Mixing strncpy and expectations. strncpy doesn't always null-terminate. snprintf is safer.

What's next

Episode 12: scanf — reading from the user. Format-specifier-driven input. Reads ints, floats, strings (with caveats).

Recap

C strings = char[] ending in '\0'. strlen counts up to (excluding) the terminator. strcpy(dest, src) copies — unsafe; prefer snprintf or strncpy. strcmp(a, b) compares; 0 means equal. String literals are read-only — modifying via char *p = "..." crashes; use char s[] = "..." for mutable. Always size your buffers; bounds aren't checked.

Next episode: scanf.

Ready? Take the quiz on the full lesson page →
Test what you've learned. Watch the lesson and try the interactive quiz on the same page.