NEW C PRIMER PLUS SECOND EDITION by Waite & Prata
CHAPTER 8 NOTES by Linda Buck
Copyright (C) 1993 by The Waite Group
Copyright (C) 1997 by Linda Buck


 1. Buffers
    -------
    Definition:
    Buffer - An area of temporary storage.

    Types of I/O Buffering:
    (1) Unbuffered
        No buffer.  Each character is immediately available.
        Word processors usually use unbuffered input/output.
    (2) Line Buffered
        Buffer is flushed when a newline character is encountered.
        Keyboard input/output is usually line buffered.
    (3) Fully Buffered
        Buffer is flushed when it is full.
        File input/output is usually fully buffered.

 2. Example 8.1
    -----------
    Problem:
    Write a program that reads and echos text.  Use # as the
    terminating character.

    Program:
    /* echo1.c -- echos input */
    #include <stdio.h>
    int main(void)
    {
      char ch;

      printf("Please enter some text terminated by #.\n");
      while ((ch = getchar()) != '#')
        putchar(ch);
      return 0;
    }

    Screen - Unbuffered I/O:
    Output: Please enter some text terminated by #.
    In&Out: aabb
    Output:
    In&Out: ccdd
    Output:
    Input:  #

    Screen - Line Buffered I/O:
    Output: Please enter some text terminated by #.
    Input:  ab
    Output: ab
    Input:  cd
    Output: cd
    Input:  #

    Screen - Fully Buffered I/O:
    Output: Please enter some text terminated by #.
    Input:  ab
    Input:  cd
    Input:  #
    Output: ab
    Output: cd

 3. Example 8.2
    -----------
    Program #1:
    /* buffer1.c -- keyboard buffering */
    #include <stdio.h>
    int main(void)
    {
      char ch;

      printf("Please enter some text terminated by #.\n");
      while ((ch = getchar()) != '#')
      {
        if (ch == '\n')
          printf("ch = '\\n'\n");
        else
          printf("ch = '%c'\n", ch);
      }
      return 0;
    }

    Screen #1:
    Output: Please enter some text terminated by #.
    Input:  ab
    Output: ch = 'a'
    Output: ch = 'b'
    Output: ch = '\n'
    Input:  cd
    Output: ch = 'c'
    Output: ch = 'd'
    Output: ch = '\n'
    Input:  #

    Program #2:
    /* buffer2.c -- keyboard buffering */
    int main(void)
    {
      char ch;
      int status, num;

      printf("Please enter a list of integers.  Type q to quit.\n");
      while (scanf("%d", &num) == 1)
        printf("num = %d\n", num);

      /* 'q' still in input buffer */
      printf("Please enter an integer.\n");
      status = scanf("%d", &num);
      printf("status = %d, num = %d\n", status, num);

      /* get 'q' out of input buffer */
      ch = getchar();
      printf("ch = '%c'\n", ch);
      printf("Please enter an integer.\n");
      status = scanf("%d", &num);
      printf("status = %d, num = %d\n", status, num);
      return 0;
    }

    Screen #2:
    Output: Please enter a list of integers.  Type q to quit.
    Input:  2 4 q
    Output: num = 2
    Output: num = 4
    Output: Please enter an integer.
    Output: status = 0, num = 4
    Output: ch = 'q'
    Output: Please enter an integer.
    Input:  6
    Output: status = 1, num = 6

 4. Terminating Input
    -----------------
    Definitions:
    File - An area of memory in which information is stored.
    Stream - An idealized flow of data to which the actual input or
             output is mapped.

    Standard Input/Output:
    (1) C treats input and output devices the same as it treats regular
        files on storage devices.
    (2) Keyboard input is represented by a stream called stdin.
        Screen output is represented by a stream called stdout.
    (3) The getchar() and scanf() functions deal with stdin.
        The putchar() and printf() functions deal with stdout.

    End-of-File:
    (1) The keyboard end-of-file character is typed as follows.
            DOS: [Ctrl-Z]
            UNIX: [Ctrl-D] at the beginning of a line
    (2) (a) getchar()
            1) The return value for getchar() when it detects end-of-
               file is EOF.
            2) The return value for getchar() is type int to allow for
               EOF.
        (b) scanf()
            1) The return value for scanf() when it detects EOF for the
               first item is EOF.
            2) The return value for scanf() when it detects end-of-file
               after the first item is the number of items read before
               encountering end-of-file.
    (3) Typically, EOF is defined in the stdio.h file as follows.
            #define EOF (-1)

 5. Example 8.3
    -----------
    Problem:
    Modify Example 8.1 to use EOF as the terminating character.

    Program:
    /* echo2.c -- echos input */
    #include <stdio.h>
    int main(void)
    {
      int ch;

      printf("Please enter some text terminated by EOF.\n");
      while ((ch = getchar()) != EOF)
        putchar(ch);
      return 0;
    }

    Screen:
    Output: Please enter some text terminated by EOF.
    Input:  ab
    Output: ab
    Input:  cd
    Output: cd
    Input:  [Ctrl-Z] (Unix: [Ctrl-D])

 6. Redirection
    -----------
    (1) Redirecting input enables a program to use a file instead of the
        keyboard for input.
    (2) Redirecting output enables a program to use a file instead of
        the screen for output.

    System Commands:
    (1) Redirecting stdin from a file: <
            prog < file1
    (2) Redirecting stdout to a file: >
            prog > file2
    (3) Combined redirection:
            prog < file1 > file2
                    or
            prog > file2 < file1

    Note:
    (1) If the output file already exists it is erased and a new file is
        created.
    (2) Don't use the same filename for both input and output in one
        command.

 7. Example 8.4
    -----------
    (1) prog < file1
        ------------
        MS-DOS Program: echo2.exe
        UNIX Program:   a.out

        Input File: letters1
        abcdefghijklmnopqrstuvwxyz

        MS-DOS Command: echo2 < letters1
        UNIX Command:   a.out < letters1

        Screen Output:
        abcdefghijklmnopqrstuvwxyz
    
    (2) prog > file2
        ------------
        MS-DOS Program: echo2.exe
        UNIX Program:   a.out

        MS-DOS Command: echo2 > letters2
        UNIX Command:   a.out > letters2

        Screen Input:
        abcdefghijklmnopqrstuvwxyz
        [Ctrl-Z] (Unix: [Ctrl-D])

        Output File: letters2
        abcdefghijklmnopqrstuvwxyz
        
        MS-DOS Command (check contents of letters2 file): type letters2
        UNIX Command (check contents of letters2 file): pg letters2

        Screen Output:
        abcdefghijklmnopqrstuvwxyz

    (3) prog < file1 > file2
        --------------------
        MS-DOS Program: echo2.exe
        UNIX Program:   a.out

        Input File: letters1
        abcdefghijklmnopqrstuvwxyz

        MS-DOS Command: echo2 < letters1 > letters2
        UNIX Command:   a.out < letters1 > letters2

        Output File: letters2
        abcdefghijklmnopqrstuvwxyz

        MS-DOS Command (check contents of letters2 file): type letters2
        UNIX Command (check contents of letters2 file):   pg letters2

        Screen Output:
        abcdefghijklmnopqrstuvwxyz

 8. Friendly User Interfaces
    ------------------------
    (1) Be sure your program handles the newline character correctly.
    (2) Be careful when using both getchar() (or scanf() with %c) to
        read input a character at a time and scanf() to read numbers or
        strings.  This mixture can create problems because getchar()
        (or scanf() with %c) reads every character, including spaces,
        tabs, and newlines, whereas scanf(), when reading numbers or
        strings, skips over spaces, tabs, and newlines.
    (3) Try to anticipate ways in which users will fail to follow
        instructions and then design your program to handle these user
        failures gracefully.

 9. Example 8.5
    -----------
    Problem:
    Write a program that processes a yes or no question.

    Incorrect Program:
    /* yesno1.c -- processes a yes or no question */
    #include <stdio.h>
    int main(void)
    {
      int ch;

      while (1)
      {
        /* prompt user for answer */
        printf("Y/N?\n");

        /* get answer and handle quit case */
        if ((ch = getchar()) == EOF)
          break;

        /* process answer */
        if (ch == 'Y' || ch == 'y')
          printf("Process y answer.\n");
        else if (ch == 'N' || ch == 'n')
          printf("Process n answer.\n");
        else
          printf("Error: invalid answer.\n");
      }
      return 0;
    }

    Incorrect Screen:
    Output: Y/N?
    Input:  Y
    Output: Process y answer.
    Output: Y/N?
    Output: Error: invalid answer.
    Output: Y/N?
    Input:  no
    Output: Process n answer.
    Output: Y/N?
    Outupt: Error: invalid answer.
    Output: Y/N?
    Output: Error: invalid answer.
    Output: Y/N?
    Input:  quit
    Output: Error: invalid answer.
    Output: Y/N?
    Output: Error: invalid answer.
    Output: Y/N?
    Output: Error: invalid answer.
    Output: Y/N?
    Output: Error: invalid answer.
    Output: Y/N?
    Output: Error: invalid answer.
    Output: Y/N?
    Input:  [Ctrl-Z] (Unix: [Ctrl-D])

    Incorrect Comment:
    (1) (a) Does not handle whitespace between input cycles correctly.
        (b) Does not handle extra characters between input cycles
            correctly.
    (2) (a) Quits after EOF.

    Correct Program:
    /* yesno2.c -- processes a yes or no question */
    #include <stdio.h>
    int main(void)
    {
      int ch;
 
      while (1)
      {
        /* prompt user for answer */
        printf("Y/N?\n");

        /* get answer and handle quit case */
        if ((ch = getchar()) == EOF)
          break;

        /* clear input buffer */
        if (ch != '\n')
          while (getchar() != '\n');

        /* process answer */
        if (ch == 'Y' || ch == 'y')
          printf("Process yes answer.\n");
        else if (ch == 'N' || ch == 'n')
          printf("Process no answer.\n");
        else
          printf("Error: invalid answer.\n");
      } 
      return 0;
    }

    Correct Screen:
    Output: Y/N?
    Input:  Y
    Output: Process yes answer.
    Output: Y/N?
    Input:  no
    Output: Process no answer.
    Output: Y/N?
    Input:  quit
    Output: Error: invalid answer.
    Output: Y/N?
    Input:  [Ctrl-Z] (Unix: [Ctrl-D])

    Correct Comment:
    (1) (a) Handles whitespace between input cycles correctly.
        (b) Handles extra characters between input cycles correctly.
    (2) (a) Quits after EOF.

10. Example 8.6
    -----------
    Problem:
    Write a program that has the user pick a number between 1 and 100
    and then have the computer try to guess it.  Use a binary search
    algorithm.

    Binary Search Algorithm:
    loop until done:
    (1) guess = (high+low)/2
    (2) (a) pick == guess
            done
        (b) pick < guess
            high = guess-1
        (c) pick > guess
            low = guess+1

    Program:
    /* guess.c -- guesses a number */
    #include <stdio.h>
    #define LOW    1
    #define HIGH 100
    int main(void)
    { 
      int ch;
      int low = LOW, high = HIGH, guess;

      printf("Pick an integer from %d to %d.\n", LOW, HIGH);
      printf("I will try to guess it.\n");
      while (1)
      {
        /* calculate guess */
        guess = (high+low)/2;

        /* print guess and prompt user for answer */
        printf("Is my guess %d (c/h/l)?\n", guess);

        /* get answer and handle quit case */
        if ((ch = getchar()) == EOF)
          break;

        /* clear input buffer */
        if (ch != '\n')
          while (getchar() != '\n');

        /* process answer */
        if (ch == 'C' || ch == 'c')
        {
          printf("I knew I could do it!\n");
          break;
        }
        else if (ch == 'H' || ch == 'h')
          high = guess-1;
        else if (ch == 'L' || ch == 'l')
          low = guess+1;
        else
          printf("Error: invalid answer.\n");
      }
      return 0;
    }

    Trace:
    Let the user pick 34.
    (1) low = 1
        high = 100
        guess = (high+low)/2 = (100+1)/2 = 101/2 = 50
        (pick?guess) = (34<50)
        high = guess-1 = 50-1 = 49
    (2) low = 1
        high = 49
        guess = (high+low)/2 = (49+1)/2 = 50/2 = 25
        (pick?guess) = (34>25)
        low = guess+1 = 25+1 = 26
    (3) low = 26
        high = 49
        guess = (high+low)/2 = (49+26)/2 = 75/2 = 37
        (pick?guess) = (34<37)
        high = guess-1 = 37-1 = 36
    (4) low = 26
        high = 37
        guess = (high+low)/2 = (37+26)/2 = 63/2 = 31
        (pick?guess) = (34>31)
        low = guess+1 = 31+1 = 32
    (5) low = 32
        high = 37
        guess = (high+low)/2 = (37+32)/2 = 69/2 = 34
        (pick?guess) = (34==34)
        done

    Screen:
    Output: Pick an integer from 1 to 100.
    Output: I will try to guess it.
    Output: Is my guess 50 (c/h/l)?
    Input:  h
    Output: Is my guess 25 (c/h/l)?
    Input:  l
    Output: Is my guess 37 (c/h/l)?
    Input:  high
    Output: Is my guess 31 (c/h/l)?
    Input:  low
    Output: Is my guess 34 (c/h/l)?
    Input:  yes
    Output: Error: invalid answer.
    Output: Is my guess 34 (c/h/l)?
    Input:  c
    Output: I knew I could do it!

11. Example 8.7
    -----------
    Problem:
    Write a program that reads a character and an integer.

    Incorrect Program:
    /* charint1.c -- reads a character and an integer */
    #include <stdio.h>
    int main(void)
    {
      char ch;
      int num;

      printf("This program reads a character and an integer.\n");
      while (1)
      {
        /* prompt user for input */
        printf("\nPlease enter a character and an integer.  Type "
          "EOF to quit.\n");

        /* get input and handle quit case */
        if (scanf("%c %d", &ch, &num) != 2)
          break;

        /* echo input */
        printf("ch = '%c', num = %d\n", ch, num);
      }
      return 0;
    }

    Incorrect Screen:
    Output: This program reads a character and an integer.
    Output:
    Output: Please enter a character and an integer.  Type EOF to quit.
    Input:  a 15
    Output: ch = 'a', num = 15
    Output:
    Output: Please enter a character and an integer.  Type EOF to quit.
    Input:  b 25

    Incorrect Comment:
    (1) (a) Does not handle whitespace between input cycles correctly.
        (b) Does not handle extra characters between input cycles
            correctly.
    (2) (a) Treats q as a valid character and waits for you to enter an
            integer.
        (b) Quits after invalid numeric input.
        (c) Quits after EOF.
    
    Correct Program:
    /* charint2.c -- reads a character and an integer */
    #include <stdio.h>
    int main(void)
    {
      char ch;
      int num;

      printf("This program reads a character and an integer.\n");
      while (1)
      {
        /* prompt user for input */
        printf("\nPlease enter a character and an integer.  Type "
          "EOF to quit.\n");

        /* get input and handle quit case */
        if (scanf("%c %d", &ch, &num) != 2)
          break;

        /* clear input buffer */
        while (getchar() != '\n');

        /* echo input */
        printf("ch = '%c', num = %d\n", ch, num);
      }
      return 0;
    }

    Correct Screen:
    Output: This program reads a character and an integer.
    Output:
    Output: Please enter a character and an integer.  Type EOF to quit.
    Input:  a 15
    Output: ch = 'a', num = 15
    Output:
    Output: Please enter a character and an integer.  Type EOF to quit.
    Input:  b 25
    Output: ch = 'b', num = 25
    Output:
    Output: Please enter a character and an integer.  Type EOF to quit.
    Input:  [Ctrl-Z] (Unix: [Ctrl-D])

    Correct Comment:
    (1) (a) Handles whitespace between input cycles correctly.
        (b) Handles extra characters between input cycles correctly.
    (2) (a) Treats q as a valid character and waits for you to enter an
            integer.
        (b) Quits after invalid numeric input.
        (c) Quits after EOF.

12. Example 8.8
    -----------
    Problem:
    Write a program that reads a character, a number of rows, and a
    number of columns.  Print the character using the number of rows and
    columns.

    Program:
    /* rect.c -- prints a character using a number of rows and
                 columns */
    #include <stdio.h>
    #define MAXCOLS 80
    int main(void)
    {
      char ch;
      int rows, cols;
      int row, col;

      printf("This program prints a character using a number of\n");
      printf("rows and columns.\n");
      while (1)
      {
        /* prompt user for input */
        printf("\nPlease enter a character, a number of rows, and a\n");
        printf("number of columns.  Type EOF to quit.\n");

        /* get input and handle quit case */
        if (scanf("%c %d %d", &ch, &rows, &cols) != 3)
          break;

        /* clear input buffer */
        while (getchar() != '\n');

        /* handle invalid input */
        if (rows < 1 || cols < 1 || cols > MAXCOLS)
        {
          printf("Error: invalid input.\n");
          continue;
        }

        /* print character using number of rows and columns */
        for (row = 1; row <= rows; row++)
        {
          for (col = 1; col <= cols; col++)
            putchar(ch);
          putchar('\n');
        }
      }
      return 0;
    }

    Screen:
    Output: This program prints a character using a number of
    Output: rows and columns.
    Output:
    Output: Please enter a character, a number of rows, and a
    Output: number of columns.  Type EOF to quit.
    Input:  a 2 3
    Output: aaa
    Output: aaa
    Output:
    Output: Please enter a character, a number of rows, and a
    Output: number of columns.  Type EOF to quit.
    Input:  b 5 90
    Output: Error: invalid input.
    Output:
    Output: Please enter a character, a number of rows, and a
    Output: number of columns.  Type EOF to quit.
    Input:  b 5 4
    Output: bbbb
    Output: bbbb
    Output: bbbb
    Output: bbbb
    Output: bbbb
    Output:
    Output: Please enter a character, a number of rows, and a
    Output: number of columns.  Type EOF to quit.
    Input:  [Ctrl-Z] (Unix: [Ctrl-D])
	
13. Example 8.9
    -----------
    Problem:
    Write a program that reads a lowercase letter with retry after
    invalid input.

    Program:
    /* lowlet.c -- reads a lowercase letter with retry after invalid
                   input */
    #include <stdio.h>
    int main(void)
    {
      int letter;

      printf("This program reads a lowercase letter with retry\n");
      printf("after invalid input.\n");

      while (1)
      {
        /* prompt user for lowercase letter */
        printf("\nPlease enter a lowercase letter.  Type EOF to "
          "quit.\n");

        /* get valid lowercase letter loop */
        while (1)
        {
          /* get lowercase letter and handle quit case */
          if ((letter = getchar()) == EOF)
            break;

          /* clear input buffer */
          if (letter != '\n');
            while (getchar() != '\n');

          /* handle valid lowercase letter */
          if (letter >= 'a' && letter <= 'z')
            break;

          /* handle invalid lowercase letter */
          printf("Error: invalid lowercase letter.  Please retry.\n");
        }

        /* finish quit case */
        if (letter == EOF)
          break;

        /* echo valid lowercase letter */
        printf("lowercase letter = '%c'\n", letter);
      }
      return 0;
    }

    Screen:
    Output: This program reads a lowercase letter with retry
    Output: after invalid input.
    Output:
    Output: Please enter a lowercase letter.  Type EOF to quit.
    Input:  a
    Output: lowercase letter = 'a'
    Output:
    Output: Please enter a lowercase letter.  Type EOF to quit.
    Input:  b
    Output: lowercase letter = 'b'
    Output:
    Output: Please enter a lowercase letter.  Type EOF to quit.
    Input:  c
    Output: lowercase letter = 'c'
    Output:
    Output: Please enter a lowercase letter.  Type EOF to quit.
    Input:  abc
    Output: lowercase letter = 'a'
    Output:
    Output: Please enter a lowercase letter.  Type EOF to quit.
    Input:  XYZ
    Output: Error: invalid lowercase letter.  Please retry.
    Input:  d
    Output: lowercase letter = 'd'
    Output:
    Output: Please enter a lowercase letter.  Type EOF to quit.
    Input:  [Ctrl-Z] (Unix: [Ctrl-D])

    Comment:
    (1) (a) Handles whitespace between input cycles correctly.
        (b) Handles extra characters between input cycles correctly.
    (2) (a) Lets user retry after invalid input.
        (b) Quits after EOF.

14. Example 8.10
    ------------
    Problem:
    Write a program that reads a positive integer with retry after
    invalid input.

    Program:
    /* posint.c -- reads a positive integer with retry after invalid
                   input */
    #include <stdio.h>
    int main(void)
    {
      int status, num;

      printf("This program reads a positive integer with retry\n");
      printf("after invalid input.\n");

      while (1)
      {
        /* prompt user for positive integer */
        printf("\nPlease enter a positive integer.  Type EOF to "
          "quit.\n");

        /* get valid positive integer loop */
        while (1)
        {
          /* get positive integer and handle quit case */
          if ((status = scanf("%d", &num)) == EOF)
            break;

          /* clear input buffer */
          while (getchar() != '\n');

          /* handle valid positive integer */
          if (status == 1 && num >= 0)
            break;

          /* handle invalid positive integer */
          printf("Error: invalid positive integer.  Please retry.\n");
        }

        /* finish quit case */
        if (status == EOF)
          break;

        /* echo valid positive integer */
        printf("positive integer = %d\n", num);
      }
      return 0;
    }

    Screen:
    Output: This program reads a positive integer with retry
    Output: after invalid input.
    Output:
    Output: Please enter a positive integer.  Type EOF to quit.
    Input:  1
    Output: positive integer = 1
    Output:
    Output: Please enter a positive integer.  Type EOF to quit.
    Input:  2
    Output: positive integer = 2
    Output:
    Output: Please enter a positive integer.  Type EOF to quit.
    Input:  3
    Output: positive integer = 3
    Output:
    Output: Please enter a positive integer.  Type EOF to quit.
    Input:  1abc
    Output: positive integer = 1
    Output:
    Output: Please enter a positive integer.  Type EOF to quit.
    Input:  -1
    Output: Error: invalid positive integer.  Please retry.
    Input:  xyz
    Output: Error: invalid positive integer.  Please retry.
    Input:  4
    Output: positive integer = 4
    Output:
    Output: Please enter a positive integer.  Type EOF to quit.
    Input: [Ctrl-Z] (Unix: [Ctrl-D])

    Comment:
    (1) (a) Handles whitespace between input cycles correctly.
        (b) Handles extra characters between input cycles correctly.
    (2) (a) Lets user retry after invalid input.
        (b) Quits after EOF.

15. Example 8.11
    ------------
    Problem:
    Write a general character menu program.

    Program:
    /* menu1.c -- general character menu */
    #include <stdio.h>
    #define LAST_CHOICE 'd'
    int main(void)
    {
      int choice;

      printf("This is a general character menu program.\n");

      while (1)
      {
        /* prompt user for menu choice */
        printf("\nPlease enter one of the following:\n");
        printf("a) choice a action\n");
        printf("b) choice b action\n");
        printf("c) choice c action\n");
        printf("d) quit\n");

        /* get valid menu choice loop */
        while (1)
        {
          /* get menu choice and handle EOF */
          if ((choice = getchar()) == EOF)
          {
            choice = LAST_CHOICE;
            break;
          }

          /* clear input buffer */
          if (choice != '\n')
            while (getchar() != '\n');

          /* handle valid menu choice */
          if (choice >= 'a' && choice <= LAST_CHOICE)
            break;

          /* handle invalid menu choice */
          printf("Error: invalid menu choice.  Please retry.\n");
        }

        /* handle quit case */
        if (choice == LAST_CHOICE)
          break;

        /* process valid menu choice */
        switch (choice)
        {
          case 'a':
            printf("Doing choice a action.\n");
            break;
          case 'b':
            printf("Doing choice b action.\n");
            break;
          case 'c':
            printf("Doing choice c action.\n");
            break;
        }
      }
      return 0;
    }

    Screen:
    Output: This is a general character menu program.
    Output:
    Output: Please enter one of the following:
    Output: a) choice a action
    Output: b) choice b action
    Output: c) choice c action
    Output: d) quit
    Input:  a
    Output: Doing choice a action.
    Output:
    Output: Please enter one of the following:
    Output: a) choice a action
    Output: b) choice b action
    Output: c) choice c action
    Output: d) quit
    Input:  b
    Output: Doing choice b action.
    Output:
    Output: Please enter one of the following:
    Output: a) choice a action
    Output: b) choice b action
    Output: c) choice c action
    Output: d) quit
    Input:  c
    Output: Doing choice c action.
    Output:
    Output: Please enter one of the following:
    Output: a) choice a action
    Output: b) choice b action
    Output: c) choice c action
    Output: d) quit
    Input:  abc
    Output: Doing choice a action.
    Output:
    Output: Please enter one of the following:
    Output: a) choice a action
    Output: b) choice b action
    Output: c) choice c action
    Output: d) quit
    Input:  xyz
    Output: Error: invalid menu choice.  Please retry.
    Input:  d

16. Example 8.12
    ------------
    Problem:
    Write a general integer menu program.

    Program:
    /* menu2.c -- general integer menu */
    #include <stdio.h>
    #define LAST_CHOICE 4
    int main(void)
    {
      int status, choice;

      printf("This is a general integer menu program.\n");

      while (1)
      {
        /* prompt user for menu choice */
        printf("\nPlease enter one of the following:\n");
        printf("1) choice 1 action\n");
        printf("2) choice 2 action\n");
        printf("3) choice 3 action\n");
        printf("4) quit\n");

        /* get valid menu choice loop */
        while (1)
        {
          /* get menu choice and handle EOF */
          if ((status = scanf("%d", &choice)) == EOF)
          {
            choice = LAST_CHOICE;
            break;
          }

          /* clear input buffer */
          while (getchar() != '\n');

          /* handle valid menu choice */
          if (status == 1 && choice >= 1 && choice <= LAST_CHOICE)
            break;

          /* handle invalid menu choice */
          printf("Error: invalid menu choice.  Please retry.\n");
        }

        /* handle quit case */
        if (choice == LAST_CHOICE)
          break;

        /* process valid menu choice */
        switch (choice)
        {
          case 1:
            printf("Doing choice 1 action.\n");
            break;
          case 2:
            printf("Doing choice 2 action.\n");
            break;
          case 3:
            printf("Doing choice 3 action.\n");
            break;
        }
      }
      return 0;
    }

    Screen:
    Output: This is a general integer menu program.
    Output:
    Output: Please enter one of the following:
    Output: 1) choice 1 action
    Output: 2) choice 2 action
    Output: 3) choice 3 action
    Output: 4) quit
    Input:  1
    Output: Doing choice 1 action.
    Output:
    Output: Please enter one of the following:
    Output: 1) choice 1 action
    Output: 2) choice 2 action
    Output: 3) choice 3 action
    Output: 4) quit
    Input:  2
    Output: Doing choice 2 action.
    Output:
    Output: Please enter one of the following:
    Output: 1) choice 1 action
    Output: 2) choice 2 action
    Output: 3) choice 3 action
    Output: 4) quit
    Input:  3
    Output: Doing choice 3 action.
    Output:
    Output: Please enter one of the following:
    Output: 1) choice 1 action
    Output: 2) choice 2 action
    Output: 3) choice 3 action
    Output: 4) quit
    Input:  1abc
    Output: Doing choice 1 action.
    Output:
    Output: Please enter one of the following:
    Output: 1) choice 1 action
    Output: 2) choice 2 action
    Output: 3) choice 3 action
    Output: 4) quit
    Input:  5
    Output: Error: invalid menu choice.  Please retry.
    Input:  xyz
    Output: Error: invalid menu choice.  Please retry.
    Input:  4

17. Example 8.13
    ------------
    Problem:
    Suppose you manage a chain of four hotels.  Each hotel charges a
    different room rate, but all the rooms in a given hotel go for the
    same rate.  For people who book multiple nights, the second night
    goes for 95 percent of the first night, the third night goes for 95
    percent of the second night, and so on.  Write a program that
    enables you to specify the hotel and the numbers of nights and gives
    you the total charge.  Use a menu that enables you to continue
    entering data until you choose to quit.

    Program:
    /* hotel.c -- calculates hotel bills */
    #include <stdio.h >

    #define LAST_CHOICE 'e'

    #define RATEA  50.00
    #define RATEB  55.00
    #define RATEC  80.00
    #define RATED 100.00

    #define DISCOUNT 0.95

    int main(void)
    {
      int choice;
      int status, nights, i;
      double rate, bill;

      printf("This program calculates hotel bills.\n");

      while (1)
      {
        /* prompt user for menu choice */
        printf("\nPlease enter one of the following:\n");
        printf("a) Fairfield Arms\n");
        printf("b) Hotel Olympic\n");
        printf("c) Chertworthy Plaza\n");
        printf("d) The Stockton\n");
        printf("e) Quit\n");

        /* get valid menu choice loop */
        while (1)
        {
          /* get menu choice and handle EOF */
          if ((choice = getchar()) == EOF)
          {
            choice = LAST_CHOICE;
            break;
          }

          /* clear input buffer */
          if (choice != '\n')
            while (getchar() != '\n');

          /* handle valid menu choice */
          if (choice >= 'a' && choice <= LAST_CHOICE)
            break;

          /* handle invalid menu choice */
          printf("Error: invalid menu choice.  Please retry.
        }

        /* handle quit case */
        if (choice == LAST_CHOICE)
          break;

        /* using menu choice, find hotel rate */
        switch (choice)
        {
          case 'a':
            rate = RATEA;
            break;
          case 'b':
            rate = RATEB;
            break;
          case 'c':
            rate = RATEC;
            break;
          case 'd':
            rate = RATED;
            break;
        }

        /* prompt user for number of nights */
        printf("Please enter number of nights.\n");

        /* get valid number of nights loop */
        while (1)
        {
          /* get number of nights and handle quit case */
          if ((status = scanf("%d", &nights)) == EOF)
            break;

          /* clear input buffer */
          while (getchar() != '\n');

          /* handle valid number of nights */
          if (status == 1 && nights >= 0)
            break;

          /* handle invalid number of nights */
          printf("Error: invalid number of nights.  Please retry.\n");
        }

        /* finish quit case */
        if (status == EOF)
          break;

        /* using hotel rate and number of nights, calculate bill */
        bill = 0.0;
        for (i = 1; i <= nights; i++)
        {
          bill += rate;
          rate *= DISCOUNT;
        }

        /* print bill */
        printf("bill = $%.2f.\n", bill);
      }
      return 0;
    }

    Screen:
    Output: This program calculates hotel bills.
    Output:
    Output: Please enter one of the following:
    Output: a) Fairfield Arms
    Output: b) Hotel Olympic
    Output: c) Chertworthy Plaza
    Output: d) The Stockton
    Output: e) Quit
    Input:  a
    Output: Please enter number of nights.
    Input:  1
    Output: bill = $50.00
    Output:
    Output: Please enter one of the following:
    Output: a) Fairfield Arms
    Output: b) Hotel Olympic
    Output: c) Chertworthy Plaza
    Output: d) The Stockton
    Output: e) Quit
    Input:  b
    Output: Please enter number of nights.
    Input:  2
    Output: bill = $107.25
    Output:
    Output: Please enter one of the following:
    Output: a) Fairfield Arms
    Output: b) Hotel Olympic
    Output: c) Chertworthy Plaza
    Output: d) The Stockton
    Output: e) Quit
    Input:  c
    Output: Please enter number of nights.
    Input:  3
    Output: bill = $228.20
    Output:
    Output: Please enter one of the following:
    Output: a) Fairfield Arms
    Output: b) Hotel Olympic
    Output: c) Chertworthy Plaza
    Output: d) The Stockton
    Output: e) Quit
    Input:  d
    Output: Please enter number of nights.
    Input:  4
    Output: bill = $370.99
    Output:
    Output: Please enter one of the following:
    Output: a) Fairfield Arms
    Output: b) Hotel Olympic
    Output: c) Chertworthy Plaza
    Output: d) The Stockton
    Output: e) Quit
    Input:  abc
    Output: Please enter number of nights.
    Input:  1
    Output: bill = $50.00
    Output:
    Output: Please enter one of the following:
    Output: a) Fairfield Arms
    Output: b) Hotel Olympic
    Output: c) Chertworthy Plaza
    Output: d) The Stockton
    Output: e) Quit
    Input:  xyz
    Output: Error: invalid menu choice.  Please retry.
    Input:  a
    Output: Please enter number of nights.
    Input:  2abc
    Output: bill = $97.50
    Output:
    Output: Please enter one of the following:
    Output: a) Fairfield Arms
    Output: b) Hotel Olympic
    Output: c) Chertworthy Plaza
    Output: d) The Stockton
    Output: e) Quit
    Input:  a
    Output: Please enter number of nights.
    Input:  -1
    Output: Error: invalid number of nights.  Please retry.
    Input:  xyz
    Output: Error: invalid number of nights.  Please retry.
    Input:  3
    Output: bill = $142.63
    Output:
    Output: Please enter one of the following:
    Output: a) Fairfield Arms
    Output: b) Hotel Olympic
    Output: c) Chertworthy Plaza
    Output: d) The Stockton
    Output: e) Quit
    Input:  e

18. Example 8.14
    ------------
    Problem:
    The 1988 United States Federal Estimated Tax Schedule is the
    simplest in recent times.  It has four categories, and each category
    has two rates.  Here is a summary (dollar amounts are taxable
    income):
        Category           Tax
        Single             15% of first $17,850 plus 28% of excess
        Head of household  15% of first $23,900 plus 28% of excess
        Married, joint     15% of first $29,750 plus 28% of excess
        Married, separate  15% of first $14,875 plus 28% of excess
    For instance, a single wage earner with a taxable income of $20,000
    dollars owes 0.15x$17,850+0.28x($20,000-$17,850).  Write a program
    that lets the user specify the tax category and the taxable income
    and then calculates the tax.  Use a loop so that the user can enter
    several tax cases.

    Program:
    /* tax.c -- calculates income tax */
    #include <stdio.h>

    #define LAST_CHOICE 5

    #define LIMIT1 17850.0
    #define LIMIT2 23900.0
    #define LIMIT3 29750.0
    #define LIMIT4 14875.0

    #define RATE1 0.15
    #define RATE2 0.28

    int main(void)
    {
      int choice;
      int status;
      double limit, income, income1, income2, tax;

      printf("This program calculates income tax.\n");

      while (1)
      {
        /* prompt user for menu choice */
        printf("\nPlease enter one of the following:\n");
        printf("1) Single\n");
        printf("2) Head of household\n");
        printf("3) Married, joint\n");
        printf("4) Married, separate\n");
        printf("5) Quit\n");

        /* get valid menu choice loop */
        while (1)
        {
          /* get menu choice and handle EOF */
          if ((status = scanf("%d", &choice)) == EOF)
          {
            choice = LAST_CHOICE;
            break;
          }

          /* clear input buffer */
          while (getchar() != '\n');

          /* handle valid menu choice */
          if (status == 1 && choice >= 1 && choice <= LAST_CHOICE)
            break;

          /* handle invalid menu choice */
          printf("Error: invalid menu choice.  Please retry.\n");
        }

        /* handle quit case */
        if (choice == LAST_CHOICE)
          break;

        /* using menu choice, find limit for rates */
        switch (choice)
        {
          case 1:
            limit = LIMIT1;
            break;
          case 2:
            limit = LIMIT2;
            break;
          case 3:
            limit = LIMIT3;
            break;
          case 4:
            limit = LIMIT4;
            break;
        }

        /* prompt user for income */
        printf("Please enter income.\n");

        /* get valid income loop */
        while (1)
        {
          /* get income and handle quit case */
          if ((status = scanf("%lf", &income)) == EOF)
            break;

          /* clear input buffer */
          while (getchar() != '\n');

          /* handle valid income */
          if (status == 1 && income >= 0.0)
            break;

          /* handle invalid income */
          printf("Error: invalid income.  Please retry.\n");
        }

        /* finish quit case */
        if (status == EOF)
          break;

        /* using limit and income, find income at rate1 and income at
           rate2 */
        if (income <= limit)
        {
          income1 = income;
          income2 = 0.0;
        } 
        else
        {
          income1 = limit;
          income2 = income - limit;
        }

        /* using income1, rate1, income2, and rate2, calculate tax */
        tax = income1*RATE1 + income2*RATE2;

        /* print tax */
        printf("tax = $%.2lf\n", tax);
      }
      return 0;
    }
	
    Screen:
    Output: This program calculates income tax.
    Output:
    Output: Please enter one of the following:
    Output: 1) Single
    Output: 2) Head of household
    Output: 3) Married, joint
    Output: 4) Married, separate
    Output: 5) Quit
    Input:  1
    Output: Please enter income.
    Input:  15000
    Output: tax = $2250.00
    Output:
    Output: Please enter one of the following:
    Output: 1) Single
    Output: 2) Head of household
    Output: 3) Married, joint
    Output: 4) Married, separate
    Output: 5) Quit
    Input:  2
    Output: Please enter income.
    Input:  27500
    Output: tax = $4593.00
    Output:
    Output: Please enter one of the following:
    Output: 1) Single
    Output: 2) Head of household
    Output: 3) Married, joint
    Output: 4) Married, separate
    Output: 5) Quit
    Input:  3
    Output: Please enter income.
    Input:  25000
    Output: tax = $3750.00
    Output:
    Output: Please enter one of the following:
    Output: 1) Single
    Output: 2) Head of household
    Output: 3) Married, joint
    Output: 4) Married, separate
    Output: 5) Quit
    Input:  4
    Output: Please enter income.
    Input:  17500
    Output: tax = $2966.25
    Output:
    Output: Please enter one of the following:
    Output: 1) Single
    Output: 2) Head of household
    Output: 3) Married, joint
    Output: 4) Married, separate
    Output: 5) Quit
    Input:  1abc
    Output: Please enter income.
    Input:  15000
    Output: tax = $2250.00
    Output:
    Output: Please enter one of the following:
    Output: 1) Single
    Output: 2) Head of household
    Output: 3) Married, joint
    Output: 4) Married, separate
    Output: 5) Quit
    Input:  6
    Output: Error: invalid menu choice.  Please retry.
    Input:  xyz
    Output: Error: invalid menu choice.  Please retry.
    Input:  1
    Output: Please enter income.
    Input:  16000abc
    Output: tax = $2400.00
    Output:
    Output: Please enter one of the following:
    Output: 1) Single
    Output: 2) Head of household
    Output: 3) Married, joint
    Output: 4) Married, separate
    Output: 5) Quit
    Input:  1
    Output: Please enter income.
    Input:  -1000
    Output: Error: invalid income.  Please retry.
    Input:  xyz
    Output: Error: invalid income.  Please retry.
    Input:  17000
    Output: tax = $2550.00
    Output:
    Output: Please enter one of the following:
    Output: 1) Single
    Output: 2) Head of household
    Output: 3) Married, joint
    Output: 4) Married, separate
    Output: 5) Quit
    Input:  5
 



7



