C in 100 Seconds: Strings | Episode 11
Video: C in 100 Seconds: strlen strcpy strcmp — Strings in C | Episode 11 by Taught by Celeste AI - AI Coding Coach
C Strings: strlen, strcpy, strcmp
A C string is a
char[](orchar*) ending in'\0'.strlencounts bytes before\0.strcpycopies.strcmpcompares. 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.