Check if a Character is a Vowel or Consonant in C
Three C programs classify any character as a vowel, consonant, or non-alphabet input using if-else with tolower(), switch-case, and a strchr() lookup table.
Classifying a character as a vowel, consonant, or non-alphabet symbol in C requires two steps: normalise the case with tolower(), then test the result against the five vowels.
This article shows three complete programs for that test, walks through the output for representative inputs, and covers the non-alphabet edge case that first-draft solutions routinely miss.
What the Program Must Classify
English has five vowels: a, e, i, o, u. All other letters are consonants. English has 26 letters in total; 5 are vowels, leaving 21 consonants. Characters outside the alphabet (digits like ‘5’, symbols like ’#’, whitespace) are neither vowels nor consonants.
A correct program handles all three categories. The common mistake in first-draft solutions is treating the else branch as “consonant” when it should be “consonant only if the input is actually a letter”. Without that guard, typing ‘5’ at the prompt produces “5 is a consonant”, which is wrong.
The two-step pattern fixes this:
- Step 1: convert the input to lowercase with
tolower(). - Step 2: test the lowercased character against the vowel set, then use
isalpha()to confirm any non-vowel result is actually a letter before calling it a consonant.
In C, every character is stored as a small integer. The char type is typically one byte wide, and the ASCII values for lowercase letters run from 97 (‘a’) to 122 (‘z’). Uppercase letters run from 65 (‘A’) to 90 (‘Z’). Digits (‘0’ to ‘9’) have ASCII values 48 through 57, which fall outside both letter ranges, so isalpha() returns 0 for all of them. Symbols and whitespace also fall outside both letter ranges.
Both tolower() and isalpha() are in <ctype.h>. The C standard specifies that tolower() takes an int argument representable as unsigned char or EOF. Passing a plain char directly is safe on most platforms, but the technically correct form is tolower((unsigned char)ch), which avoids undefined behaviour on platforms where char is signed and values above 127 can be negative.
This type of basic decision-making program appears in the C-language MCQ sections of TCS NQT, AMCAT, and campus aptitude rounds. It tests whether a candidate understands case normalisation and edge-case handling, not just the syntax of if-else. See the C coding placement questions article for the pointer and memory questions that appear alongside these.
Method 1: if-else with tolower()
The if-else approach is the most explicit: each branch states exactly what it is testing.
#include <stdio.h>
#include <ctype.h> /* tolower, isalpha */
void classify(char ch) {
char lower = (char)tolower((unsigned char)ch);
if (lower == 'a' || lower == 'e' || lower == 'i' ||
lower == 'o' || lower == 'u') {
printf("'%c' is a vowel.\n", ch);
} else if (isalpha((unsigned char)ch)) {
printf("'%c' is a consonant.\n", ch);
} else {
printf("'%c' is not an alphabet character.\n", ch);
}
}
int main(void) {
char ch;
printf("Enter a character: ");
scanf(" %c", &ch);
classify(ch);
return 0;
}
Tracing Method 1
Three representative inputs, derived from first principles:
Input: ‘A’
tolower((unsigned char)'A')returns ‘a’ (ASCII 65 mapped to 97).lower == 'a'evaluates to true.- Output:
'A' is a vowel.
Input: ‘b’
tolower((unsigned char)'b')returns ‘b’ (already lowercase, unchanged).- ‘b’ is not equal to any of the five vowel characters.
isalpha((unsigned char)'b')returns a non-zero value (‘b’ is a letter).- Output:
'b' is a consonant.
Input: ‘5’
tolower((unsigned char)'5')returns ‘5’ (digits are unchanged by tolower).- ‘5’ is not a vowel.
isalpha((unsigned char)'5')returns 0 (digits are not letters).- Output:
'5' is not an alphabet character.
The else if (isalpha(...)) check is what separates a complete solution from a partial one. Removing it causes ‘5’, ’#’, and space to print as consonants.
Method 2: switch-case with tolower()
The switch-case version labels the vowel cases explicitly and uses fall-through: five case labels share a single printf.
#include <stdio.h>
#include <ctype.h> /* tolower, isalpha */
void classify_switch(char ch) {
char lower = (char)tolower((unsigned char)ch);
switch (lower) {
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
printf("'%c' is a vowel.\n", ch);
break;
default:
if (isalpha((unsigned char)ch)) {
printf("'%c' is a consonant.\n", ch);
} else {
printf("'%c' is not an alphabet character.\n", ch);
}
}
}
int main(void) {
char ch;
printf("Enter a character: ");
scanf(" %c", &ch);
classify_switch(ch);
return 0;
}
Tracing Method 2
Input: ‘E’
tolower((unsigned char)'E')returns ‘e’.switch ('e')matchescase 'e', falls through to the sharedprintf.- Output:
'E' is a vowel.
Input: ’#’
tolower((unsigned char)'#')returns ’#’ (symbol, unchanged).switch ('#')reaches thedefaultbranch.isalpha((unsigned char)'#')returns 0.- Output:
'#' is not an alphabet character.
Note that the isalpha() call inside default: is still necessary. Without it, the default branch prints “consonant” for every non-vowel, including digits and symbols.
The fall-through syntax is one of the few places where C’s switch-case behaviour is intentional rather than a mistake. Placement MCQs sometimes test whether candidates know that omitting break between cases produces this cascade.
Method 3: strchr() Lookup Table
The strchr() function searches a string for the first occurrence of a character and returns a pointer to it, or NULL if not found. That makes “is this character in the vowel set?” a one-liner.
#include <stdio.h>
#include <string.h> /* strchr */
#include <ctype.h> /* tolower, isalpha */
void classify_lookup(char ch) {
char lower = (char)tolower((unsigned char)ch);
const char *vowels = "aeiou";
if (strchr(vowels, lower) != NULL) {
printf("'%c' is a vowel.\n", ch);
} else if (isalpha((unsigned char)ch)) {
printf("'%c' is a consonant.\n", ch);
} else {
printf("'%c' is not an alphabet character.\n", ch);
}
}
int main(void) {
char ch;
printf("Enter a character: ");
scanf(" %c", &ch);
classify_lookup(ch);
return 0;
}
Tracing Method 3
Input: ‘O’
tolower((unsigned char)'O')returns ‘o’.strchr("aeiou", 'o')returns a non-NULL pointer (finds ‘o’ at index 3).- Output:
'O' is a vowel.
Input: ‘z’
tolower((unsigned char)'z')returns ‘z’.strchr("aeiou", 'z')returns NULL (‘z’ is not in the string).isalpha((unsigned char)'z')returns non-zero.- Output:
'z' is a consonant.
Input: ’ ’ (space)
tolower((unsigned char)' ')returns ’ ’ (space, unchanged).strchr("aeiou", ' ')returns NULL.isalpha((unsigned char)' ')returns 0.- Output:
' ' is not an alphabet character.
The string "aeiou" acts as a lookup table. Adding or removing characters from it changes which inputs the function classifies as vowels, without touching any of the control-flow logic. That property makes strchr() a natural choice when the character set might evolve.
The strchr() approach scales cleanly if the comparison set ever expands. Switching from English vowels to a different character set means changing only the string literal.
Comparison of the Three Methods
| Method | Headers required | Vowel test | Non-alphabet guard | Best suited for |
|---|---|---|---|---|
| if-else | <ctype.h> | Five equality checks with || | isalpha() | First introduction to C conditionals |
| switch-case | <ctype.h> | Five fall-through case labels | isalpha() inside default: | Clearly enumerated discrete cases |
| strchr() | <ctype.h>, <string.h> | Single strchr() call | isalpha() | Minimal code; easier to extend the character set |
All three produce identical output. None is meaningfully faster than the others for a five-character set. The difference is how the code reads.
For a beginner choosing between these methods: start with if-else because the logic reads left to right and every branch is visible. Move to switch-case once the if-else version is clear, because fall-through cases are a C idiom worth understanding. Use strchr() when you want compact code or when the vowel set might change. All three share the same guard pattern, so the transition between them is straightforward.
A note on non-alphabet handling: the table shows isalpha() in every method’s guard column because all three programs use the same guard logic. Some textbook examples skip this entirely and treat the else or default: branch as “consonant”. That produces wrong output for digits, symbols, and whitespace. AMCAT and TCS NQT MCQs sometimes use exactly that bug as a wrong-answer trap: the question shows code that mis-labels ‘3’ as a consonant and asks what the output is.
For more C programs that mix loop logic with character operations, the Pascal’s triangle in C article shows how nested loops and integer arithmetic produce formatted output from structured rules.
The tolower() normalisation step in all three methods is a small example of a broader pattern: reduce variation before testing. Text preprocessors in natural language processing pipelines do the same thing at larger scale, lowercasing and stripping punctuation before any downstream classification. If that pipeline side of things interests you, TinkerLLM puts a live LLM API in your hands for ₹299. The tolower-then-classify structure you just traced is the micro-scale version of what runs inside a tokenizer.
Primary sources
Frequently asked questions
Why use tolower() before checking for vowels in C?
tolower() normalises uppercase letters like A, E, I, O, U to their lowercase equivalents before comparison. Without it, you need ten equality checks instead of five, one for each upper and lower case vowel. Using tolower() keeps the logic concise and less error-prone.
What does strchr() return if the character is not in the string?
strchr() returns NULL if the character is not found in the string. A non-NULL return means the character exists at the returned position. Always compare the return value against NULL explicitly in the if-condition.
How do I handle digits and symbols in a vowel-consonant program in C?
Use isalpha() from ctype.h to check whether the character is a letter before classifying it as a vowel or consonant. If isalpha() returns zero, the character is a digit, symbol, or whitespace and belongs in the non-alphabet branch.
Is switch-case faster than if-else for a vowel check in C?
For five known values, a modern compiler typically generates equivalent machine code for both. Switch-case is preferred when the cases are clearly enumerated; if-else is natural when the branches involve range checks like isalpha.
What header files are needed for tolower(), isalpha(), and strchr() in C?
tolower() and isalpha() are declared in ctype.h. strchr() is declared in string.h. Include both headers as needed, or the compiler will not resolve the function declarations.
A self-paced playground for building with LLMs.
TinkerLLM is FACE Prep's sister property. A guided environment for shipping real LLM applications, the kind of project that earns a paragraph on your resume, not a line.
Try TinkerLLM (₹299 launch)