String & Character Functions
string.h and ctype.hC comes with ready-made helpers for strings in string.h and for single characters in ctype.h. They are just loops over characters — in the lab below you watch strcat find the end and copy (and overflow a small array), strcmp compare letter by letter, and toupper / isdigit work through a string.
- strcattrusts you that there is room
- strcmpreturns 0 when equal
- toupperchanges one character
Ready
Keyboard: ← → step · Space play / pause · R reset · Esc exit classroom mode
The ideas behind the lab
Exactly what you watched happen, in plain steps.
Loops you do not have to write
string.h holds functions that work on whole strings — they all walk the characters until '\0'. ctype.h holds functions that test or convert one character. None of the string functions know how big your arrays are: the destination must have enough room, or memory next to it is overwritten. That is why the "n" versions (strncpy, strncat) and snprintf, which take a size, exist.
#include <string.h>
#include <ctype.h>
char d[20];
strcpy(d, "Hello"); // d = "Hello"
strcat(d, ", C"); // d = "Hello, C"
strlen(d) // 8
strcmp(d, "Hello") // > 0 (d is longer)
toupper('a') // 'A'
isdigit('7') // true (non-zero)
| Function | What it does | Result / note |
|---|---|---|
| strlen(s) | Counts characters before '\0' | size_t; '\0' not counted |
| strcpy(d, s) | Copies s (with '\0') into d | d must be big enough |
| strncpy(d, s, n) | Copies at most n chars | May leave d without '\0' |
| strcat(d, s) | Appends s to the end of d | d needs room for both |
| strcmp(a, b) | Compares character codes | < 0, 0 or > 0 |
| strchr(s, c) / strstr(s, t) | Finds a char / a substring | Pointer to it, or NULL |
| isalpha, isdigit, isspace, isupper | Tests one character | Non-zero = true |
| toupper(c) / tolower(c) | Converts one letter | Other chars unchanged |
Copying and joining
- strcpy(d, s) copies every character of s, then '\0'.
- strcat(d, s) first finds the '\0' of d, then copies s there.
- The destination comes first, like an assignment: d = s.
- Neither checks the size of d: too little room = buffer overflow.
- Safer: snprintf(d, sizeof d, "%s%s", a, b) never writes past sizeof d.
Comparing
- strcmp walks both strings until two characters differ or both end.
- It returns 0 if equal, negative if a comes first, positive if b does.
- Test with == 0, < 0, > 0 — not with == -1 or == 1.
- It compares codes: all uppercase letters come before lowercase.
- For "same ignoring case", convert both with tolower first.
Characters with ctype.h
- isdigit(c): '0'–'9'; isalpha(c): a letter; isalnum(c): either.
- isspace(c): space, tab, newline; isupper / islower: the case.
- toupper(c) and tolower(c) return the converted char — store it: s[i] = toupper(s[i]).
- They take an int: pass (unsigned char) c for characters above 127.
- A digit's value: c - '0' ('7' - '0' is 7).
Your own strlen and strcpy, then a palindrome test
Every line, explained.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int myStrlen(const char s[])
const: the function only reads s.
{
int n = 0;
while (s[n] != '\0')
Exactly what strlen does.
n++;
return n;
}
void myStrcpy(char dest[], const char src[])
{
int i = 0;
while ((dest[i] = src[i]) != '\0')
Copy, then test: the '\0' is copied too.
i++;
}
int main(void)
{
char word[20], copy[20];
myStrcpy(word, "Level");
printf("%d\n", myStrlen(word));
Prints 5
strcpy(copy, word);
The library version.
for (int i = 0; copy[i]; i++)
copy[i] is 0 (false) at the terminator.
copy[i] = tolower(copy[i]);
copy = "level"
int n = strlen(copy), pal = 1;
for (int i = 0; i < n / 2; i++)
Compare from both ends.
if (copy[i] != copy[n - 1 - i]) pal = 0;
printf("%s\n", pal ? "palindrome" : "not a palindrome");
Prints palindrome
return 0;
}
Spot the bug
Mistakes almost every beginner makes — and how to fix them.
Destination too small
char d[6] = "Hi, "; strcat(d, "World"); // needs 10 bytes
char d[16] = "Hi, "; strcat(d, "World");
strcat writes past the end of d — a buffer overflow that silently corrupts other memory.
Arguments in the wrong order
strcpy("Hello", d); // copies INTO the literal
strcpy(d, "Hello"); // destination first
The first argument is always the destination. Writing into a string literal crashes.
Testing strcmp as true / false
if (strcmp(a, b)) // runs when they DIFFER
if (strcmp(a, b) == 0) // equal
strcmp returns 0 for equal strings, and 0 means false.
Forgetting to store toupper's result
toupper(s[i]); // s is unchanged
s[i] = toupper(s[i]);
toupper returns the new character; it cannot change its argument.
strncpy without a terminator
char d[4]; strncpy(d, "Hello", 4); // H e l l — no \0
char d[4]; strncpy(d, "Hello", 3); d[3] = '\0';
When the source is too long, strncpy does not add '\0'. Add it yourself.
Check your understanding
Answer each question — you will see the explanation straight away.
strlen("hello") returns?
'\0' is not counted.
char d[20] = "ab"; strcat(d, "cd"); — what is d?
strcat appends the source to the end of d.
What does strcmp("cat", "cat") return?
0 means the strings are equal.
Is strcmp("Zebra", "apple") negative or positive?
'Z' is 90 and 'a' is 97, so "Zebra" comes first.
What is '8' - '0'?
Digit codes are consecutive: 56 - 48 = 8.
String & Character Functions quiz
Test yourself: 10 questions, 70% to pass. Create a free account to take the quiz, save your progress and work towards the certificate.