-
Book Overview & Buying
-
Table Of Contents
-
Feedback & Rating

Linux System Programming Techniques
By :

In this recipe, we'll learn how to write a program in C that reads from standard input. Doing so enables your programs to take input from other programs via a pipe, making them easier to use as a filter, thus making them more useful in the long run.
You'll need the GCC compiler and preferably the Bash shell for this recipe, although it should work with any shell.
To fully understand the program that we are about to write, you should look at an ASCII table, an example of which can be found at the following URL: https://github.com/PacktPublishing/Linux-System-Programming-Techniques/blob/master/ch2/ascii-table.md.
In this recipe, we will write a program that takes single words as input, converts their cases (uppercase into lower and lowercase into upper), and prints the result to standard output. Let's get started:
case-changer.c
. In this program, we use fgets()
to read characters from stdin. We then use a for
loop to loop over the input, character by character. Before we start the next loop with the next line of input, we must zero out the arrays using memset()
:#include <stdio.h> #include <string.h> int main(void) { char c[20] = { 0 }; char newcase[20] = { 0 }; int i; while(fgets(c, sizeof(c), stdin) != NULL) { for(i=0; i<=sizeof(c); i++) { /* Upper case to lower case */ if ( (c[i] >= 65) && (c[i] <= 90) ) { newcase[i] = c[i] + 32; } /* Lower case to upper case */ if ( (c[i] >= 97 && c[i] <= 122) ) { newcase[i] = c[i] - 32; } } printf("%s\n", newcase); /* zero out the arrays so there are no left-overs in the next run */ memset(c, 0, sizeof(c)); memset(newcase, 0, sizeof(newcase)); } return 0; }
$> gcc case-changer.c -o case-changer
$> ./case-changer hello HELLO AbCdEf aBcDeF
ls
:$> ls / | head -n 5 | ./case-changer BIN BOOT DEV ETC HOME
$> man ls | egrep '^[A-Z]+$' | ./case-changer name synopsis description author copyrigh
First, we created two character arrays of 20 bytes each and initialize them to 0.
Then, we used fgets()
, wrapped in a while
loop, to read characters from standard input. The fgets()
function reads characters until it reaches a newline character or an End Of File (EOF). The characters that are read are stored in the c
array, and also returned.
To read more input—that is, more than one word—we continue reading input with the help of the while
loop. The while
loop won't finish until we either press Ctrl + D or the input stream is empty.
The fgets()
function returns the character read on success and NULL
on error or when an EOF occurs while no characters have been read (that is, no more input). Let's break down the fgets()
function so that we can understand it better:
fgets(c, sizeof(c), stdin)
The first argument, c
, is where we store the data. In this case, it's our character array.
The second argument, sizeof(c)
, is the maximum size we want to read. The fgets()
function is safe here; it reads one less than the size we specify. In our case, it will only read 19 characters, leaving room for the null character.
The final and third argument, stdin
, is the stream we want to read from—in our case, standard input.
Inside the while
loop is where the case conversions are happening, character by character in the for
loop. In the first if
statement, we check if the current character is an uppercase one. If it is, then we add 32 to the character. For example, if the character is A, then it's represented by 65 in the ASCII table. When we add 32, we get 97, which is a. The same goes for the entire alphabet. It's always 32 characters apart between the uppercase and lowercase versions.
The next if
statement does the reverse. If the character is a lowercase one, we subtract 32 and get the uppercase version.
Since we are only checking characters between 65 and 90, and 97 and 122, all other characters are ignored.
Once we printed the result on the screen, we reset the character arrays to all zeros with memset()
. If we don't do this, we will have leftover characters in the next run.
We tried the program by running it interactively and typing words into it. Each time we hit the Enter key, the word is transformed; the uppercase letters will become lowercase and vice versa.
Then, we piped data to it from the ls
command. That output got converted into uppercase letters.
Then, we tried to pipe it uppercase words from the manual page (the headings). All the headings in a manual page are uppercase and start at the beginning of the line. This is what we "grep" for with egrep
, and then pipe to our case-changer
program.
For more information about fgets()
, see the manual page, man 3 fgets
.
You can write a small program to print a minimum ASCII table for the letters a-z and A-Z. This small program also demonstrates that each character is represented by a number:
ascii-table.c
#include <stdio.h> int main(void) { char c; for (c = 65; c<=90; c++) { printf("%c = %d ", c, c); /* upper case */ printf("%c = %d\n", c+32, c+32); /* lower case */ } return 0; }