Chapter 4 — Strings
In C a string is **a char array ending with `\0`**. The `\0` is what makes a "string" different from a "char array".
What you'll learn
- 1Declare and initialize strings.
- 2Use core `<string.h>` functions: `strlen`, `strcpy`, `strcmp`, `strcat`.
- 3Read a line safely with `fgets`.
- 4Avoid buffer overflows.
Core Concepts
1) Storage layout
char s[] = "abc"; // {'a', 'b', 'c', '\0'} — length 4`strlen("abc")` is 3 (excludes the `\0`); `sizeof(s)` is 4 (includes it).
2) Key `<string.h>` functions
| Function | What |
|---|---|
| `strlen(s)` | length, excluding `\0` |
| `strcpy(dst, src)` | copy — **dst must be big enough** |
| `strncpy(dst, src, n)` | bounded copy |
| `strcmp(a, b)` | 0 = equal, <0 = a<b, >0 = a>b |
| `strcat(dst, src)` | concat — same warning as `strcpy` |
| `strchr(s, c)` | find char; returns pointer or NULL |
3) Reading a line safely
char buf[100];
fgets(buf, sizeof(buf), stdin); // includes trailing '\n'Strip the `\n` if you don't want it:
buf[strcspn(buf, "\n")] = '\0';4) Why `gets` is gone
The old `gets()` had no length check and was removed from C11. **Never use it.**
5) Compare strings — don't use `==`
char a[] = "hi", b[] = "hi";
a == b; // ❌ compares pointers (different)
strcmp(a, b); // ✅ returns 0Examples
Example 1 — `ex01_basic.c`: strlen vs sizeof
char s[] = "Hello";
printf("strlen = %zu\n", strlen(s));
printf("sizeof = %zu\n", sizeof(s));**Output**
strlen = 5
sizeof = 6Key: `sizeof` includes the `\0`, `strlen` doesn't.
Example 2 — `ex02_strops.c`: copy, compare, concat
char a[20] = "Hello";
char b[] = "World";
strcat(a, ", ");
strcat(a, b);
printf("%s\n", a);
printf("cmp = %d\n", strcmp("abc", "abd"));**Output**
Hello, World
cmp = -1Key: `a` was declared with room (`[20]`) so `strcat` doesn't overflow.
Example 3 — `ex03_fgets.c`: read a name
char name[32];
printf("Name? ");
fgets(name, sizeof(name), stdin);
name[strcspn(name, "\n")] = '\0';
printf("Hi, %s!\n", name);**Output**
Name? Alice
Hi, Alice!Key: `fgets` is safe; always strip the trailing newline.
Example 4 — `ex04_count.c`: count vowels
const char *s = "Programming";
int n = 0;
for (int i = 0; s[i]; i++) {
char c = s[i];
if (c=='a'||c=='e'||c=='i'||c=='o'||c=='u'||
c=='A'||c=='E'||c=='I'||c=='O'||c=='U') n++;
}
printf("vowels = %d\n", n);**Output**
vowels = 3Key: loop condition `s[i]` stops naturally at `\0`.
Common mistakes
- **`strcpy` into a too-small buffer** — silent buffer overflow.
- **Comparing strings with `==`** — compares pointers, not content.
- **Forgetting the `\0`** — manual char arrays can be unterminated; `printf("%s")` then runs off the end.
- **`fgets` newline left behind** — strip with `strcspn`.
Recap
- A C string is bytes + `\0`. `\0` is everything.
- Always size the destination; prefer `strncpy`/`snprintf`.
- Compare with `strcmp`, not `==`.
Try it
cd src
gcc -std=c11 -Wall -o ex01 ex01_basic.c && ./ex01
gcc -std=c11 -Wall -o ex02 ex02_strops.c && ./ex02
gcc -std=c11 -Wall -o ex03 ex03_fgets.c && ./ex03 <<< Alice
gcc -std=c11 -Wall -o ex04 ex04_count.c && ./ex04💻 Examples
Compilable, runnable examples — see the output yourself.
#include <stdio.h>
#include <string.h>
int main(void) {
char s[] = "Hello, C!";
printf("string: %s\n", s);
printf(": %zu\n", strlen(s));
/* */
for (size_t i = 0; s[i] != '\0'; i++) {
printf("s[%zu] = %c ( %d)\n", i, s[i], s[i]);
}
return 0;
}
strlen = 5
sizeof = 6#include <stdio.h>
#include <string.h>
int main(void) {
char a[64] = "Hello";
char b[] = ", World!";
char c[64];
strcpy(c, a);
strcat(a, b);
printf("a = %s\n", a);
printf("c = %s\n", c);
printf("strcmp(\"abc\", \"abd\") = %d\n", strcmp("abc", "abd"));
printf("strcmp(\"abc\", \"abc\") = %d\n", strcmp("abc", "abc"));
return 0;
}
Hello, World
cmp = -1#include <stdio.h>
#include <string.h>
int main(void) {
char line[128];
printf("Sentence: ");
if (fgets(line, sizeof(line), stdin) == NULL) return 1;
line[strcspn(line, "\n")] = '\0'; /* \n */
printf("input: \"%s\"\n", line);
printf(": %zu\n", strlen(line));
return 0;
}
Name? Alice
Hi, Alice!#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main(void) {
char buf[256];
printf(" Sentence: ");
if (fgets(buf, sizeof(buf), stdin) == NULL) return 1;
buf[strcspn(buf, "\n")] = '\0';
int vowels = 0, consonants = 0;
for (size_t i = 0; buf[i] != '\0'; i++) {
char ch = (char)tolower((unsigned char)buf[i]);
if (ch >= 'a' && ch <= 'z') {
if (ch == 'a' || ch == 'e' || ch == 'i' ||
ch == 'o' || ch == 'u')
vowels++;
else
consonants++;
}
}
printf(": %d, : %d\n", vowels, consonants);
return 0;
}
vowels = 3📝 Exercises
Try them yourself first, then open the solution to compare.
Problem 1 (hw01.c)
Goal: Read a word and print it reversed (in place).
- Filename: hw01.c
▶Toggle solution
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main(void) {
char buf[256];
printf("Sentence: ");
if (fgets(buf, sizeof(buf), stdin) == NULL) return 1;
buf[strcspn(buf, "\n")] = '\0';
for (size_t i = 0; buf[i] != '\0'; i++)
buf[i] = (char)toupper((unsigned char)buf[i]);
printf("%s\n", buf);
return 0;
}
Problem 2 (hw02.c)
Goal: Read a sentence and count words (split on spaces).
- Filename: hw02.c
▶Toggle solution
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main(void) {
char buf[256];
printf("Sentence: ");
if (fgets(buf, sizeof(buf), stdin) == NULL) return 1;
buf[strcspn(buf, "\n")] = '\0';
int len = (int)strlen(buf);
int palindrome = 1;
for (int i = 0, j = len - 1; i < j; i++, j--) {
char a = (char)tolower((unsigned char)buf[i]);
char b = (char)tolower((unsigned char)buf[j]);
if (a != b) { palindrome = 0; break; }
}
printf("%s\n", palindrome ? "It is a palindrome." : "Not a palindrome.");
return 0;
}
Problem 3 (hw03.c)
Goal: Read a string and a character; print how many times the character appears.
- Filename: hw03.c
▶Toggle solution
#include <stdio.h>
#include <string.h>
int main(void) {
char buf[256];
char target;
printf("Sentence: ");
if (fgets(buf, sizeof(buf), stdin) == NULL) return 1;
buf[strcspn(buf, "\n")] = '\0';
printf("Char to find: ");
scanf(" %c", &target);
int count = 0;
for (size_t i = 0; buf[i] != '\0'; i++)
if (buf[i] == target) count++;
printf("'%c' appears %d times.\n", target, count);
return 0;
}
All lecture materials and example code are openly available on GitHub.
View on GitHub ↗