Chapter 4
attr.c
attr.c
/* File: attr.c
This program reads characters until end of file. It prints the
attributes of each character including the ASCII value.
*/
#include <stdio.h>
int print_reps( char ch );
main()
{ char ch;
int flag;
printf("***Character Attributes***\n\n");
printf("Type text, terminate with EOF \n");
flag = scanf("%c", &ch); /* read the first char */
while (flag != EOF) {
if (ch >= 'a' && ch <= 'z') { /* lower case letter? */
print_reps(ch);
printf("lower case letter\n");
}
else if (ch >= 'A' && ch <= 'Z') { /* upper case letter? */
print_reps(ch);
printf("an upper case letter\n");
}
else if (ch >= '0' && ch <= '9') { /* digit character? */
print_reps(ch);
printf("a digit symbol\n");
}
else if (ch == '.' || ch == ',' || ch == ';' || ch == ':' ||
ch == '?' || ch == '!') { /* punctuation? */
print_reps(ch);
printf("a punctuation symbol\n");
}
else if (ch == ' ') { /* space? */
print_reps(ch);
printf("a space character\n");
}
else if (ch < 32 || ch == 127) { /* control character? */
print_reps(ch);
printf("a control character\n");
}
else { /* must be a special symbol */
print_reps(ch);
printf("a special symbol\n");
}
flag = scanf("%c", &ch); /* read the next char */
} /* end of while loop */
} /* end of program */
int print_reps( char ch)
{
printf("%c, ASCII value decimal %d, octal %o, hexadecimal %x: ",
ch,ch,ch,ch);
}
attr2.c
attr2.c
/* File: attr2.c
This program reads characters until end of file. It prints the
attributes of each character including the ASCII value.
*/
#include <stdio.h>
#include "category.h"
main()
{ char ch;
int flag;
printf("***Character Attributes***\n\n");
printf("Type text, terminate with EOF \n");
flag = scanf("%c", &ch); /* read the first char */
while (flag != EOF) {
if( IS_LOWER(ch) ) print_category(LOWER, ch);
else if( IS_UPPER(ch) ) print_category(UPPER, ch);
else if( IS_DIGIT(ch) ) print_category(DIGIT, ch);
else if( IS_PUNCT(ch) ) print_category(PUNCT, ch);
else if( IS_SPACE(ch) ) print_category(SPACE, ch);
else if( IS_CONTROL(ch) ) print_category(CONTROL, ch);
else print_category(SPECIAL, ch);
flag = scanf("%c", &ch); /* read the next char */
} /* end of while loop */
} /* end of program */
int print_category( int cat, char ch)
{
printf("%c, ASCII value decimal %d, octal %o, hexadecimal %x: ",
ch,ch,ch,ch);
if( cat == LOWER ) printf("lower case letter\n");
else if( cat == UPPER ) printf("an upper case letter\n");
else if( cat == DIGIT ) printf("a digit symbol\n");
else if( cat == PUNCT ) printf("a punctuation symbol\n");
else if( cat == SPACE ) printf("a space character\n");
else if( cat == CONTROL ) printf("a control character\n");
else printf("a special symbol\n");
}
category.h
category.h
/* File: category.h
This file contains macros defining character categories and
character comparison macros.
*/
int print_category( int cat, char ch);
/* THIS HEADER FILE IS LEFT AS AN EXERCISE */
chrutil.c
chrutil.c
/* File: chrutil.c */
/* This file contains various utility functions for processing characters */
#include <stdio.h>
#include "tfdef.h"
#include "chrutil.h"
/* Function converts ch to an integer if it is a digit. Otherwise, it
prints an error message.
*/
int dig_to_int(char ch)
{
if (IS_DIGIT(ch))
return ch - '0';
printf("ERROR:dig_to_int: %c is not a digit\n", ch);
return ERROR;
}
/* Function converts a positive integer less than 10 to a corresponding
digit character.
*/
char int_to_dig(int n)
{
if (n >= 0 && n < 10)
return n + '0';
printf("ERROR:int_to_dig: %d is not in the range 0 to 9\n", n);
return NULL;
}
/* Function reads the next integer from the input */
int getint()
{ int n = 0;
int got_dig = FALSE;
signed char ch;
ch = getchar(); /* read next char */
while (IS_WHITE_SPACE(ch)) /* skip white space */
ch = getchar();
while (IS_DIGIT(ch)) { /* repeat as long as ch is a digit */
n = n * 10 + dig_to_int(ch); /* accumulate value in n */
got_dig = TRUE;
#ifdef DEBUG
printf("debug:getint: ch = %c\n", ch); /* debug statement */
printf("debug:getint: n = %d\n", n); /* debug statement */
#endif
ch = getchar(); /* read next char */
}
if(ch == EOF) return EOF; /* test for end of file */
if(!got_dig) return ERROR; /* test for no digits read */
return n; /* otherwise return the result */
}
/* Function tests if c is an alphabetic letter. */
int letterp(char c)
{
if (IS_LOWER(c) || IS_UPPER(c))
return TRUE;
return FALSE;
}
/* Function returns TRUE if c is a delimiter, i.e., it is a white space
or a punctuation. Otherwise, it returns FALSE.
*/
int delimitp(char c)
{
if (whitep(c) || punctp(c))
return TRUE;
return FALSE;
}
/* Function returns TRUE if c is white space; returns FALSE otherwise. */
int whitep(char c)
{
if (c == '\n' || c == '\t' || c == ' ')
return TRUE;
return FALSE;
}
/* Function returns TRUE if c is a punctuation; returns FALSE otherwise. */
int punctp(char c)
{
if (c == '.' || c == ',' || c == ';' || c == ':'
|| c == '?' || c == '!')
return TRUE;
return FALSE;
}
/* Function checks if c is a vowel. */
int vowelp(char c)
{
switch(c) {
case 'a':
case 'A':
case 'e':
case 'E':
case 'i':
case 'I':
case 'o':
case 'O':
case 'u':
case 'U': return TRUE;
default: return FALSE;
}
}
/* Function tests if c is printable. */
int illegal(char c)
{
if (IS_PRINT(c) || IS_WHITE_SPACE(c))
return FALSE;
return TRUE;
}
chrutil.h
chrutil.h
/* File: chrutil.h */
/* This file contains various macros and prototypes for character processing */
#define ERROR -2
#define IS_DIGIT(c) ((c) >= '0' && (c) <= '9')
#define IS_LOWER(c) ((c) >= 'a' && (c) <= 'z')
#define IS_UPPER(c) ((c) >= 'A' && (c) <= 'Z')
#define IS_WHITE_SPACE(c) ((c) == ' ' || (c) == '\t' || (c) == '\n')
#define IS_PRINT(c) ((c) >= 32 && (c) < 127)
#define LOWER 0
#define UPPER 1
#define DIGIT 2
#define PUNCT 3
#define SPACE 4
#define CONTROL 5
#define SPECIAL 6
int dig_to_int(char ch);
char int_to_dig(int n);
char uppercase(char ch);
int getint();
int delimitp(char c);
int whitep(char c);
int punctp(char c);
int vowelp(char c);
int letterp(char c);
int illegal(char c); /* Tests if c is legal. */
cnt.c
cnt.c
/* Program File: cnt.c
Other Source Files: chrutil.c
Header Files: tfdef.h, chrutil.h
This program reads standard input characters and counts the number
of lines, words, and characters. All characters are counted including
the newline and other control characters, if any.
*/
#include <stdio.h>
#include "tfdef.h"
#include "chrutil.h"
main()
{ signed char ch;
int inword, /* flag for in a word */
lns, wds, chrs; /* Counters for lines, words, chars. */
printf("***Line, Word, Character Count Program***\n\n");
printf("Type characters, EOF to quit\n");
lns = wds = chrs = 0; /* initialize counters to 0 */
inword = FALSE; /* set inword flag to False */
while ((ch = getchar()) != EOF) { /* repeat while not EOF */
chrs = chrs + 1; /* increment chrs */
if (ch == '\n') /* if newline char */
lns = lns + 1; /* increment lns */
/* if not inword and not a delimiter */
if (!inword && !delimitp(ch)) { /* if not in word and not delim., */
inword = TRUE; /* set inword to True */
wds = wds + 1; /* increment wds */
}
else if (inword && delimitp(ch)) /* if in word and a delimiter*/
inword = FALSE; /* set inword to False */
} /* end of while loop */
printf("Lines = %d, Words = %d, Characters = %d\n",
lns, wds, chrs);
} /* end of program */
copy0.c
copy0.c
/* File: copy0.c
Programmer:
Date:
This program reads a stream of characters, one character at
a time, and echoes each to the output until EOF.
*/
#include <stdio.h>
main()
{ char ch; /* declaration for a character object ch */
int flag; /* flag stores the number of items read by scanf() */
printf("***Copy Program***\n\n");
printf("Type text, terminate with EOF\n");
flag = scanf("%c", &ch); /* read the first char */
while (flag != EOF) { /* repeat while not EOF */
printf("%c", ch); /* print the last char read */
flag = scanf("%c", &ch); /* read the next char, update flag */
} /* flag is EOF, ch may be unchanged */
}
copy1.c
copy1.c
/* File: copy1.c
Programmer:
Date:
This program reads a stream of characters until end of file. Each
character read is converted to its upper case version and printed
out.
*/
#include <stdio.h>
#define IS_LOWER(c) ((c) >= 'a' && (c) <= 'z')
#define TO_UPPER(c) ((c) - 'a' + 'A')
char uppercase(char ch);
main()
{ signed char ch;
printf("***Copy Program - Upper Case***\n\n");
printf("Type text, terminate with EOF\n");
while ((ch = getchar()) != EOF)
putchar (uppercase(ch)); /* print value of uppercase(ch) */
}
/* Function returns a lower case letter to an upper case. It returns
all other characters unchanged.
*/
char uppercase(char c)
{
if ( IS_LOWER(c) ) /* if c is a lower case letter */
return TO_UPPER(c); /* convert to upper case and return */
/* otherwise, */
return c; /* return c unchanged */
}
copychr.c
copychr.c
/* File: copychr.c
Program copies standard input to standard output.
*/
#include <stdio.h>
main()
{ signed char c;
printf("***File Copy Program***\n\n");
printf("Type text, EOF to quit\n");
c = getchar();
while (c != EOF) {
putchar(c);
c = getchar();
}
}
encrypt.c
encrypt.c
/* File: encrypt.c
Other Source Files: chrutil.c
Header Files: chrutil.h
This program encrypts text by converting each letter to the next letter
in the alphabet. The last letter of the alphabet is changed to the first
letter.
*/
#include <stdio.h>
#include "chrutil.h"
void print_next(char c);
main()
{ signed char c;
printf("***Text Encryption***\n\n");
printf("Type text, EOF to quit\n");
while ((c = getchar()) != EOF) {
if (letterp(c))
print_next(c);
else
putchar(c);
}
}
/* Prints the next higher letter to c. Alphabet is assumed circular. */
void print_next(char c)
{
switch(c) {
case 'z': printf("%c", 'a');
break;
case 'Z': printf("%c", 'A');
break;
default: printf("%c", c + 1);
}
}
encrypt2.c
encrypt2.c
/* File: encrypt2.c
Other Source Files: chrutil.c
Header Files: chrutil.h
This program encrypts text by converting each letter to the next letter
in the alphabet. Illegal characters are ignored.
*/
#include <stdio.h>
#include "chrutil.h"
void print_next(char c);
main()
{ signed char c;
printf("***Text Encryption Ignoring Illegal Characters***\n\n");
printf("Type text, EOF to quit\n");
while ((c = getchar()) != EOF) { /* while there are chars to process */
if (illegal(c)) continue; /* ignore illegal characters */
if (letterp(c)) /* encrypt letters */
print_next(c);
else
putchar(c); /* print all others as is */
}
}
/* Prints the next higher letter to c. Alphabet is assumed circular. */
void print_next(char c)
{
switch(c) {
case 'z': printf("%c", 'a');
break;
case 'Z': printf("%c", 'A');
break;
default: printf("%c", c + 1);
}
}
menu.c
menu.c
/* File: menu.c
An example of a menu driven program. The main() driver prints the menu,
reads the selected item, and performs an appropriate task. */
#include <stdio.h>
#include "payroll.h"
main()
{ signed char c;
int id;
float hours_worked, rate_of_pay, pay;
printf("***Pay Calculation: Menu Driven***\n\n"); /* print title */
print_menu(); /* Display the menu to the user */
while ((c = getchar()) != EOF) { /* get user selection */
switch(c) { /* select an appropriate path */
case 'g': /* should be a function get_data() */
case 'G': printf("Id number: ");
scanf("%d", &id);
printf("Type Hours worked and rate of pay\n");
scanf("%f %f", &hours_worked, &rate_of_pay);
break;
case 'd':
case 'D': display_data(id, hours_worked, rate_of_pay);
break;
case 'm':
case 'M': modify_data();
break;
case 'c':
case 'C': pay = calc_pay(hours_worked, rate_of_pay);
break;
case 'p':
case 'P': display_data(id, hours_worked, rate_of_pay);
print_pay(pay);
break;
case 'h':
case 'H': print_menu();
break;
case 'q':
case 'Q': exit(0);
default: printf("Invalid selection\n");
print_menu();
} /* end of switch */
while ((c = getchar()) != '\n'); /* flush the buffer */
} /* end of while loop */
} /* end of program */
mix0.c
mix0.c
/* File: mix0.c
This program shows problems reading character data when it follows
numeric data.
*/
#include <stdio.h>
#define DEBUG
main()
{ char ch;
int flag, n;
printf("***Numeric and Character Data***\n\n");
printf("Type an integer\n");
while ((flag = scanf("%d", &n)) != EOF) { /* continue until EOF */
printf("n = %d\n", n); /* print n */
printf("Do you wish to continue? (Y/N): "); /* prompt */
scanf("%c", &ch); /* read a character, */
#ifdef DEBUG
printf("debug:%c in input stream\n", ch); /* type its value */
#endif
if (ch == 'y') /* if char is 'y' */
printf("Type an integer\n"); /* prompt */
else /* otherwise, */
break; /* terminate loop */
}
}
mix1.c
mix1.c
/* File: mix1.c
This program shows how character data might be read correctly when it
follows numeric data. It assumes only one white space character
terminates numeric data. This character is suppressed.
*/
#include <stdio.h>
#define DEBUG
main()
{ char ch;
int flag, n;
printf("***Numeric and Character Data***\n\n");
printf("Type an integer\n");
while ((flag = scanf("%d", &n)) != EOF) {
printf("n = %d\n", n);
printf("Do you wish to continue? (Y/N): ");
scanf("%*c%c", &ch); /* suppress a character, read another */
#ifdef DEBUG
printf("debug:%c in input stream\n", ch);
#endif
if (ch == 'y')
printf("Type an integer\n");
else
break;
}
}
mix2.c
mix2.c
/* File: mix2.c
This program shows how character data can be read correctly when it
follows numeric data even if several white space characters follow
numeric data.
*/
#include <stdio.h>
#define DEBUG
main()
{ char ch;
int flag, n;
printf("***Numeric and Character Data***\n\n");
printf("Type an integer\n");
while ((flag = scanf("%d", &n)) != EOF) {
printf("n = %d\n", n);
/* flush white space characters in a line; stop when newline read */
while (getchar() != '\n');
printf("Do you wish to continue? (Y/N): ");
scanf("%c", &ch);
#ifdef DEBUG
printf("debug:%c in input stream\n", ch);
#endif
if (ch == 'y')
printf("Type an integer\n");
else
break;
}
}
payroll.c
payroll.c
/* File: payroll.c */
/* Prints the menu. */
void print_menu(void)
{ /* print the menu */
printf("Select:\n");
printf("\tG(et Data\n");
printf("\tD(isplay Data\n");
printf("\tM(odify Data\n");
printf("\tC(alculate Pay\n");
printf("\tP(rint Pay\n");
printf("\tH(elp\n");
printf("\tQ(uit\n");
}
/* Displays input data, Id number, hours worked, and rate of pay. */
void display_data(int id, float hrs, float rate)
{
printf("Id Number %d\n", id);
printf("Hours worked %f\n", hrs);
printf("Rate of pay %f\n", rate);
}
/* Calculates pay as hrs * rate */
/* a very simple version of calc_pay. Out previous implementation
could be used here instead.
*/
float calc_pay(float hrs, float rate)
{
return hrs * rate;
}
/* Modifies input data. */
void modify_data(void)
{
printf("Modify Data not implemented yet\n");
}
/* Prints pay */
void print_pay(float pay)
{
printf("Total pay = %f\n", pay);
}
payroll.h
payroll.h
/* File: payroll.h */
/* prototypes for functions in payroll.c */
/* Prints the menu. */
void print_menu(void);
/* Displays input data, Id number, hours worked, and rate of pay. */
void display_data(int id, float hrs, float rate);
/* Calculates pay as hrs * rate */
float calc_pay(float hrs, float rate);
/* Modifies input data. */
void modify_data(void);
/* Prints pay */
void print_pay(float pay);
scan0.c
scan0.c
/* File: scan0.c
This program shows problems with scanf() when wrong data is entered.
*/
#include <stdio.h>
main()
{ int cnt, n;
printf("***Numeric and Character Data***\n\n");
printf("Type integers, EOF to quit: ");
cnt = 0;
while ((scanf("%d", &n) != EOF) && (cnt < 4)) {
printf("n = %d\n", n);
cnt = cnt + 1;
printf("Type an integer, EOF to quit: ");
}
}
scan1.c
scan1.c
/* File: scan1.c
This program shows how to handle mistyped numeric data by flushing
erroneous characters.
*/
#include <stdio.h>
#define DEBUG
main()
{ char ch;
int flag, n;
printf("***Mistyped Numeric Data: Flush characters***\n\n");
printf("Type integers, EOF to quit\n");
while ((flag = scanf("%d", &n)) != EOF) {
if (flag != 1) {
ch = getchar(); /* flush one character */
#ifdef DEBUG
printf("debug:%c in input stream, discarding\n", ch);
#endif
}
else printf("n = %d\n", n);
printf("Type an integer, EOF to quit\n");
}
}
tfdef.c
tfdef.c
/* File: tfdef.h */
#define TRUE 1
#define FALSE 0
wds.c
wds.c
/* Program File: wds.c
Other Source Files: chrutil.c
Header Files: tfdef.h, chrutil.h
This program reads standard input characters and prints each word on a
separate line. It also counts the number of lines, words, and characters.
All characters are counted including the newline and other control
characters, if any.
*/
#include <stdio.h>
#include "tfdef.h"
#include "chrutil.h"
main()
{ signed char ch;
int inword, /* flag for in a word */
lns, wds, chrs; /* Counters for lines, words, chars. */
printf("***Line, Word, Character Count Program***\n\n");
printf("Type characters, EOF to quit\n");
lns = wds = chrs = 0; /* initialize counters to 0 */
inword = FALSE; /* set inword flag to False */
while ((ch = getchar()) != EOF) { /* repeat while not EOF */
chrs = chrs + 1; /* increment chrs */
if (ch == '\n') /* if newline char */
lns = lns + 1; /* increment lns */
/* if not inword and not a delimiter */
if (!inword && !delimitp(ch)) { /* if not in word and not delim. */
inword = TRUE; /* set inword to True */
wds = wds + 1; /* increment wds */
}
else if (inword && delimitp(ch)) { /* if in word and a delimiter*/
inword = FALSE; /* set inword to False */
putchar('\n'); /* end word with a newline */
}
if (inword) /* if in a word */
putchar(ch); /* print the character */
} /* end of while loop */
printf("Lines = %d, Words = %d, Characters = %d\n",
lns, wds, chrs);
} /* end of program */
words.c
words.c
/* File: words.c
Other Source Files: chrutil.c
Header Files: tfdef.h, chrutil.h
This program reads text and extracts words until end of file. Only
printable characters are allowed in a word. Upon encountering a control
character, a message is printed and the program is aborted.
*/
#include <stdio.h>
#include "tfdef.h"
#include "chrutil.h" /* includes prototypes for delimitp(), printp() */
main()
{ signed char ch;
printf("***Words: Non-Printable Character Aborts***\n\n");
printf("Type text, EOF to quit\n");
while ((ch = getchar()) != EOF) { /* while characters remain to be read */
while (delimitp(ch)) /* skip over leading delimiters */
ch = getchar();
while (!delimitp(ch) && printp(ch)) { /* process a word */
putchar(ch); /* print ch */
ch = getchar(); /* read the next char */
}
if (ch == EOF) /* if end of file, terminate */
break;
if (illegal(ch)) {/* if a control char, print msg and abort */
printf("\nAborting - Control character present: ASCII %d\n",ch);
break;
}
printf("\n"); /* terminate word with newline */
}
}