Count Vowels in a Character Array Using Pointers in C
Step-by-step C program to count vowels in a character array using pointer arithmetic. Algorithm, traced output, case-insensitive variant, and complexity analysis.
A pointer-based vowel counter visits each character in a string exactly once, checks whether it is a vowel, and increments a counter. It runs in O(n) time and O(1) auxiliary space.
This specific pattern shows up frequently in placement coding rounds at mid-tier IT companies: given a character array, return the vowel count using pointer traversal rather than array indexing. The two approaches produce identical results, but pointer traversal is the variant that tests whether you understand C memory addressing, not just loop syntax.
What the Problem Asks
The task: read a character array, traverse it using a pointer, and report the count of vowel characters (a, e, i, o, u, including both uppercase and lowercase variants).
Consider the string "FACE Prep". Its characters, excluding the space, are F, A, C, E, P, r, e, p.
- Vowels: A, E, e — 3
- Consonants: F, C, P, r, p — 5
The space character is neither a vowel nor a consonant and should not be counted in either group.
How Pointer Arithmetic Traverses a String
In C, a string is a contiguous sequence of char values ending with a null terminator '\0'. When you declare char str[] = "FACE Prep", the characters are stored at consecutive memory addresses.
A char * pointer stores the address of a single byte. Setting char *ptr = str copies the address of str[0] into ptr. From there, two pointer operations drive the loop:
*ptr— dereference: reads the character at the current address.ptr++— increment: moves the pointer forward by one byte (one character).
The loop ends when *ptr == '\0', the null terminator. This is the standard idiom for null-terminated string traversal in C, and it is covered in detail in the GeeksforGeeks pointer-to-array guide.
One important distinction: ptr++ does not modify the original string. It advances the pointer variable itself, leaving the array data untouched.
C Program: Count Vowels Using a Pointer
#include <stdio.h>
#include <ctype.h>
int countVowels(char *str) {
int count = 0;
char *ptr = str;
while (*ptr != '\0') {
char lower = tolower((unsigned char)*ptr);
if (lower == 'a' || lower == 'e' || lower == 'i'
|| lower == 'o' || lower == 'u') {
count++;
}
ptr++;
}
return count;
}
int main(void) {
char str[] = "FACE Prep";
printf("Vowels: %d\n", countVowels(str));
return 0;
}
Output:
Vowels: 3
How the code works
The function receives a char * (the address of the first character).
char *ptr = strcopies that address into the local pointer variable.tolower((unsigned char)*ptr)folds the character to lowercase before the vowel check. The cast tounsigned charis required becausetoloweris defined for values in the range ofunsigned charplusEOF; passing a plaincharwith a high-bit value can produce undefined behaviour on platforms wherecharis signed. The cppreference tolower documentation covers the exact specification.- After each check,
ptr++moves to the next character. - The loop exits when the null terminator is reached.
ctype.h is the only header beyond stdio.h that this program needs.
Extending the Count to Consonants
Adding a consonant counter requires one additional rule: a character counts as a consonant only if it is an alphabetic character and not a vowel. The isalpha function from ctype.h handles the letter guard.
#include <stdio.h>
#include <ctype.h>
void countVowelsConsonants(char *str, int *vowels, int *consonants) {
char *ptr = str;
*vowels = 0;
*consonants = 0;
while (*ptr != '\0') {
char lower = tolower((unsigned char)*ptr);
if (lower == 'a' || lower == 'e' || lower == 'i'
|| lower == 'o' || lower == 'u') {
(*vowels)++;
} else if (isalpha((unsigned char)*ptr)) {
(*consonants)++;
}
ptr++;
}
}
int main(void) {
char str[] = "FACE Prep";
int v = 0, c = 0;
countVowelsConsonants(str, &v, &c);
printf("Vowels: %d, Consonants: %d\n", v, c);
return 0;
}
Output:
Vowels: 3, Consonants: 5
Trace through “FACE Prep”
- ptr points to ‘F’:
isalpha= true, not a vowel; consonants = 1 - ptr points to ‘A’:
tolowergives ‘a’, vowel; vowels = 1 - ptr points to ‘C’: consonant; consonants = 2
- ptr points to ‘E’: vowel; vowels = 2
- ptr points to ’ ’:
isalpha= false; skipped - ptr points to ‘P’: consonant; consonants = 3
- ptr points to ‘r’: consonant; consonants = 4
- ptr points to ‘e’: vowel; vowels = 3
- ptr points to ‘p’: consonant; consonants = 5
- ptr points to
'\0': loop exits
Final result: vowels = 3, consonants = 5.
Complexity and Common Errors
Time and space complexity
The pointer visits each character exactly once. For a string of length n:
- Time complexity: O(n)
- Auxiliary space: O(1) — only the pointer variable and the two counters are allocated; their size does not change with input length.
For more on how to derive auxiliary versus total space, see the space complexity guide with worked examples.
The “iterate, check, accumulate” structure here is identical to the sum of digits program, just operating on characters rather than decimal digits.
Three common errors
- Forgetting the null terminator check. Using
while (*ptr)is idiomatic shorthand forwhile (*ptr != '\0')and works correctly because'\0'is the only character with an integer value of zero. Both forms are safe. - Skipping the
unsigned charcast fortolower. Passing a plainchartotolowerwhencharis signed (the default on many compilers) triggers undefined behaviour for characters above the ASCII 127 range. Always cast:tolower((unsigned char)*ptr). - Counting non-letters as consonants. Without the
isalphaguard, spaces, digits, and punctuation all fall into the else branch and inflate the consonant count. The extended program above and the array modification technique using pointers both rely on similar pointer-plus-guard logic.
Pointer traversal on character arrays sits at the boundary between “knows C syntax” and “understands memory.” The core pattern (dereference, check, increment, stop at null) is the same one used inside strlen, strcpy, and most standard C string functions. Once it clicks, reading library source code becomes straightforward.
If you want to apply that same precision to building with LLMs (parsing JSON outputs, writing prompts as structured strings, calling APIs from C or Python), TinkerLLM at ₹299 lets you ship something real before committing to a longer programme.
Primary sources
Frequently asked questions
What is a character pointer in C?
A character pointer (char *) stores the memory address of a char variable or the first element of a char array. When you write char *ptr = str, ptr holds the address of str[0]. Incrementing ptr with ptr++ moves it to the next byte in memory, which is the next character in a contiguous char array.
How do I count both uppercase and lowercase vowels correctly?
Pass each character through tolower() before comparing. tolower('A') returns 'a', so a single comparison against the five lowercase vowels covers the full alphabet. Include ctype.h for tolower().
Does the program count spaces as consonants?
Only if you write the consonant branch as the else of the vowel check without a letter guard. Add isalpha(*ptr) before the vowel/consonant split to ensure spaces, digits, and punctuation are excluded from both counts.
Can I do this using array indexing instead of a pointer?
Yes. Replace the pointer loop with a for loop using an integer index: for (int i = 0; str[i] != '\0'; i++). The logic inside is identical. Pointer traversal is equivalent to indexed access; the two compile to nearly the same machine code on modern compilers.
What is the time complexity of this vowel-count program?
O(n), where n is the length of the string. The pointer visits each character exactly once. Auxiliary space is O(1), since only a fixed number of counter and pointer variables are allocated regardless of input size.
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)