Skip to main content

The ctype library are functions related to operations on the character data type. Most functions in ctype library are is**something** type functions. These functions allow you to check if a character is a particular has a particular property. For example suppose you want to test if a variable named x was an stored an alphabetic (a to z in any casing) character you could use: isalpha(x). The function returns a truthy (non-zero) value if x is alphabetic, falsey (zero) if it is alphabetic. When testing always test against 0.

	isalpha(x) == 0
isalpha(x) != 0

Aside from the functions that test for whether the character is a certain type of character, the ctype library also tests allows has two functions that returns the upper/lower case version of an alphabetic character. These are the toupper() and tolower() functions.

The interesting thing about toupper() and tolower() is that it is safe to use it with any characters even non-alphabetic ones. This is because the function returns the original characters if the characters are not applicable.

For example, the in the following code snippet, we have a string where we will convert all alphabetic characters to upper case while leaving numeric characters alone.

int i;
char robot[5] = "r2d2";

for(i = 0;robot[i]!='\0';i++){
robot[i] = toupper(robot[i]);
}

//this will print:
//R2D2
printf("%s\n",robot);

:::caution(toupper() and tolower() returns, they do not convert!)

It is really important to note how the pass-by-value nature of functions work with these library functions. toupper() and tolower() accept a character as an argument. C's parameter passing mechanism is pass-by-value. This means that the characters passed to the function are duplicated for the function as its parameters. Any modification to those variables are never reflected back to the calling variables. Thus, the variable that is passed to the function will never change. Therefore, it is important to capture the return value to store what it is that you need.

char lowerA = 'a';

//upperA will hold 'A' after this line runs
char upperA = toupper(lowerA);

//this next line will print:
//lowerA is still a, but upperA is A\n
printf("lowerA is still %c, but upperA is %c\n", lowerA, upperA);

:::

Here is a table showing the ctype library functions and what they check.

ctype.h Library Functions in C

FunctionPurposeExpected BehaviorExample
isalpha()Check if alphabeticReturns truthy (non-zero) if character is a letter (A-Z, a-z)isalpha('A') returns non-zero (truthy)
isdigit()Check if digitReturns non-zero (truthy) if character is a digit (0-9)isdigit('5') returns non-zero (truthy)
isalnum()Check if alphanumericReturns non-zero (truthy) if character is a letter or digitisalnum('A') returns non-zero (truthy)
isspace()Check if whitespaceReturns non-zero (truthy) if character is whitespace (space, tab, newline, etc.)isspace(' ') returns non-zero (truthy)
isupper()Check if uppercaseReturns non-zero (truthy) if character is uppercase letterisupper('A') returns non-zero (truthy)
islower()Check if lowercaseReturns non-zero (truthy) if character is lowercase letterislower('a') returns non-zero (truthy)
isprint()Check if printableReturns non-zero (truthy) if character is printable (including space)isprint('A') returns non-zero (truthy)
isgraph()Check if graphicalReturns non-zero (truthy) if character is printable but not spaceisgraph('A') returns non-zero (truthy)
ispunct()Check if punctuationReturns non-zero (truthy) if character is punctuationispunct('!') returns non-zero (truthy)
iscntrl()Check if controlReturns non-zero (truthy) if character is a control characteriscntrl('\n') returns non-zero (truthy)
isxdigit()Check if hex digitReturns non-zero (truthy) if character is hexadecimal digit (0-9, A-F, a-f)isxdigit('F') returns non-zero (truthy)
toupper()Convert to uppercaseReturns uppercase equivalent of character, or unchanged if not lowercasetoupper('a') returns 'A'
tolower()Convert to lowercaseReturns lowercase equivalent of character, or unchanged if not uppercasetolower('A') returns 'a'