Beginner · Strings in C · topic 19 of 60 · 25 min
Characters and <ctype.h>
Explanation
Characters are numbers
char c = 'A';
printf("%c %d\n", c, c); /* A 65 */
printf("%c\n", c + 2); /* C */
printf("%d\n", '7' - '0'); /* 7: the digit's value */
printf("%c\n", 'a' + ('Z' - 'A'));/* z */| Characters | ASCII codes |
|---|---|
| '0' to '9' | 48 to 57 |
| 'A' to 'Z' | 65 to 90 |
| 'a' to 'z' | 97 to 122 (lower case = upper case + 32) |
| ' ' (space) | 32 |
| '\n' (newline) | 10 |
| '\0' (terminator) | 0 |
Digits and letters are each in consecutive blocks in ASCII, which is why c - '0' and c - 'A' work. ASCII covers English only; Indian scripts are stored as multi-byte UTF-8 sequences, which plain char functions do not understand (each Devanagari character is several bytes).
<ctype.h> functions
#include <ctype.h>
int vowels = 0, digits = 0, spaces = 0;
const char *text = "Order 42 shipped to Asha";
for (const char *p = text; *p; p++) {
unsigned char ch = (unsigned char) *p;
if (isdigit(ch)) digits++;
else if (isspace(ch)) spaces++;
else if (strchr("aeiou", tolower(ch))) vowels++;
}
printf("%d vowels, %d digits, %d spaces\n", vowels, digits, spaces); /* 7 vowels, 2 digits, 4 spaces */| Function | True for |
|---|---|
| isalpha(c) | letters |
| isdigit(c) | '0'..'9' |
| isalnum(c) | letters or digits |
| isspace(c) | space, '\t', '\n', '\r', '\v', '\f' |
| isupper / islower | upper- / lower-case letters |
| ispunct(c) | punctuation |
| toupper / tolower | return the converted character |
A Caesar cipher
void caesar(char *s, int shift) {
shift = ((shift % 26) + 26) % 26; /* handle negative shifts */
for (; *s; s++) {
unsigned char ch = (unsigned char) *s;
if (isupper(ch)) *s = (char)('A' + (ch - 'A' + shift) % 26);
else if (islower(ch)) *s = (char)('a' + (ch - 'a' + shift) % 26);
}
}
/* "Chai, 2 cups" with shift 3 → "Fkdl, 2 fxsv" */Upper-case a string in place
void to_upper(char *s) {
for (size_t i = 0; s[i] != '\0'; i++) s[i] = (char) toupper((unsigned char) s[i]);
}Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
Characters and <ctype.h> · 1/6
In this lesson you will work with individual characters.
Prefer a video by a teacher? Find free videos on “c ctype.h isdigit isalpha toupper ascii char arithmetic” on YouTube ↗
In real life: Validating a vehicle number plate
A parking app checks that a number plate typed by the attendant has the common Indian format: two letters (state), two digits (district), one or two letters, then four digits, like MH12AB1234. Simple ctype checks catch most typos before the plate is saved.
int looks_like_plate(const char *p) {
size_t n = strlen(p);
if (n < 9 || n > 10) return 0;
if (!isupper((unsigned char)p[0]) || !isupper((unsigned char)p[1])) return 0;
if (!isdigit((unsigned char)p[2]) || !isdigit((unsigned char)p[3])) return 0;
for (size_t i = 4; i < n - 4; i++) if (!isupper((unsigned char)p[i])) return 0;
for (size_t i = n - 4; i < n; i++) if (!isdigit((unsigned char)p[i])) return 0;
return 1;
}
/* looks_like_plate("MH12AB1234") → 1, looks_like_plate("MH1AB1234") → 0 */Practice (0/3 done)
What does printf("%c", 'a' - 32); print?
The same Caesar cipher algorithm in JavaScript, which runs here: write caesar(text, shift) that shifts A–Z and a–z by shift places (wrapping around, negative shifts allowed) and leaves other characters unchanged. Use character codes (charCodeAt and String.fromCharCode), like C char arithmetic.
Write C functions: int count_vowels(const char *s), void to_title_case(char *s) (first letter of each word upper case, the rest lower case) and int is_valid_ifsc(const char *s) (11 characters: 4 letters, then '0', then 6 letters or digits). Test each with at least three strings.
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- Buffer overflows and safe string handlingStrings in C · same module
- The <string.h> functionsStrings in C · same module
- Strings, bytes and runesGo Programming (backend and cloud) · Collections and structs
- Scalar types: numbers, bool and charRust Programming · Types, control flow and functions
- Symmetric and asymmetric encryptionCyber Security: from zero to SOC analyst · Systems and cryptography
- String processingPython Programming · Working with data
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
What is '9' - '0'?
Answer: 9
Digits are consecutive in ASCII.
Why cast to unsigned char before isdigit(c)?
Answer: Negative char values (on signed-char platforms) are undefined behaviour for ctype functions
Bytes above 127 become negative when char is signed.
toupper('5') returns…
Answer: '5'
Non-letters are returned unchanged.
Can plain char functions process Hindi text correctly?
Answer: No: UTF-8 Devanagari uses several bytes per character
Use a Unicode-aware library for such text.
char a[] = "x", b[] = "x"; What does a == b compare?Related
What type do you get from s[0] when s is a string?Related
How many bytes does a Rust char use?Related
Answer: 4
A char is a Unicode scalar value stored in 4 bytes.
Base64-encoded text is…Related
Answer: Just encoded: anyone can decode it
Encoding changes format only; there is no key.
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- 1 more topic in “Strings in C” before its exam: Buffer overflows and safe string handling.
- Module 4 exam: Strings in C · 12 questions · 25 min, without help. 5 topics of this module still to finish first.
- Then the next module, Pointers. 60 topics left in the course before the final exam.