Skip to content
FollowtheDamnCode

Reference: ctype.h

Testing and converting single characters.

3 minute read

Big idea

<ctype.h> answers questions about single characters — is it a letter? a digit? a space? — and converts between upper and lower case. It's how you check and clean up text one character at a time.

The rule for every function here

Each one takes an int that must be EOF or a value an unsigned char can hold. Plain char can be negative (for accented or non-English characters), and passing a negative value is undefined behaviour. So when the character comes from a string, cast it:

if (isdigit((unsigned char) s[i])) …

The "is" functions return non-zero for true (not necessarily 1) and 0 for false — test them with if, don't compare them to 1.

Classifying characters

FunctionTrue forExample
isalpha(c)a letter, A–Z or a–zisalpha('q')
isdigit(c)a decimal digit 0–9isdigit('7')
isalnum(c)a letter or a digitisalnum('x'), isalnum('3')
isspace(c)space, \t, \n, \r, \v, \fisspace('\n')
isupper(c)an uppercase letterisupper('Q')
islower(c)a lowercase letterislower('q')
ispunct(c)printable, but not a letter, digit, or spaceispunct('!')
isxdigit(c)a hex digit: 0–9, a–f, A–Fisxdigit('b')
isprint(c)printable, including spaceisprint(' ')
iscntrl(c)a control character like \n or \tiscntrl('\t')

Converting case

toupper / tolower

int toupper(int c);
int tolower(int c);

Return the other-case version of a letter; any other character comes back unchanged.

  • Gotcha: they return the new character — they don't change anything in place. Write s[i] = toupper((unsigned char) s[i]);.
  • Example: toupper('a') → 'A', toupper('3') → '3'

Digit values

ctype.h tells you whether something is a digit; to get its value, subtract '0':

int d = c - '0';      /* '7' - '0' == 7 */

This works because the digits '0' to '9' are always consecutive.

Counting character kinds and fixing case
#include <stdio.h>
#include <ctype.h>

int main(void) {
    char s[] = "Hello, World 2026!";
    int letters = 0, digits = 0, spaces = 0, other = 0;
    for (int i = 0; s[i] != '\0'; i++) {
        unsigned char c = (unsigned char) s[i];
        if (isalpha(c)) letters++;
        else if (isdigit(c)) digits++;
        else if (isspace(c)) spaces++;
        else other++;
    }
    printf("letters=%d digits=%d spaces=%d other=%d\n", letters, digits, spaces, other);

    for (int i = 0; s[i] != '\0'; i++) {
        s[i] = (char) toupper((unsigned char) s[i]);
    }
    printf("%s\n", s);

    int value = 0;
    const char *num = "4096";
    for (int i = 0; isdigit((unsigned char) num[i]); i++) {
        value = value * 10 + (num[i] - '0');
    }
    printf("%d\n", value + 1);
    return 0;
}
output
letters=10 digits=4 spaces=2 other=2
HELLO, WORLD 2026!
4097

Run and edit it in the app.

After char c = 'b'; toupper(c); what is c?

Key terms

  • Character class — A group like letters, digits, or whitespace.
  • Whitespace — Space, tab, newline, and a few other "blank" characters.
  • Locale — The language setting that can widen what counts as a letter; by default it's plain English letters.

Check yourself

Why cast to unsigned char before calling isdigit(s[i])?

What is '7' - '0' ?