Jump to: navigation, search

The C Programming Language, 2nd Edition, by Kernighan and Ritchie
Exercise 4.09 on page 79

Our getch and ungetch do not handle a pushed-back EOF correctly. Decide what their properties ought to be if an EOF is pushed back, then implement your design.



Solution by Franz Fritsche

(Comment: The solution is virtually identical with the solution given by Tondo/Gimpel in their C Answer Book. Alas, what can I do?)

/* K&R Exercise 4-9 */
/* Franz Fritsche */

#include <stdio.h>

#define BUFSIZE 100

int buf[BUFSIZE];     /* buffer for ungetch */
int bufp = 0;         /* next free position in buf */

int getch(void)  /* get a (possibly pushed-back) character */
{
    return (bufp > 0) ? buf[--bufp] : getchar();
}

void ungetch(int c)   /* push character back on input */
{
    if (bufp >= BUFSIZE)
        printf("ungetch: too many characters\n");
    else
        buf[bufp++] = c;
}

Solution by Jesus Alvarez (Category 0)

#include <stdio.h>
#include <string.h>

int    getch    (void);
void   ungetch  (int);

/*
 * In the case that EOF is pushed back to ungetch(), the program will simply
 * continue execution as it normally would. Ignoring the EOF.
 */
int main()
{
        char c;

        /* Prematurely send EOF. */
        ungetch(EOF);

        while ((c = getch()) != EOF) {
                putchar(c);
        };

        return 0;
}

#define BUFSIZE 100
char buf[BUFSIZE];      /* Buffer for ungetch. */
int bufp = 0;           /* Next free position in buf. */

int getch(void)
{
        return (bufp > 0) ? buf[--bufp] : getchar();
}

void ungetch(int c)
{
        if (bufp >= BUFSIZE) {
                printf("Ungetch: Too many characters.\n");
        /*
         * The check for EOF must be made here. If EOF is found, it is ignored.
         */
        } else if (c != EOF) {
                buf[bufp++] = c;
        }
}


Solution by menonsahab

/* The reason why the code in K&R can't handle EOF is because it is defined as follows:
#define EOF -1
i.e. its value is negative and a char array can't hold a negative value.
Change the buffer type to int and the problem is solved. */

#include <stdio.h>
#define BUFSIZE 100

int buf[BUFSIZE];
int bufp = 0;

int getch(void)
{
	return bufp > 0 ? buf[--bufp] : getchar();
}

void ungetch(int c)
{
	if(bufp >= BUFSIZE)
		printf("error: stack is full, can't execute ungetch()\n");
	else
		buf[bufp++] = c;
}

Solution by anonymous

This builds off of Exercise 4-8's small test program. All I needed to do to handle an EOF being pushed back was to add an if statement in the ungetch function. I interrupted the exercise as the need to prevent an EOF from being pushed back, rather than the need to store it. However, you could just change the buffer to type int instead of char if you wanted to store it.

#include <stdio.h>

/*
    Exercise 4-9. Our getch and ungetch do not handle a pushed-back EOF correctly. Decide what their properties ought to be if an EOF is pushed back, then implement your design.
*/

int buf = '\0'; // char "buffer" for ungetch. ungetch only handles a single char in the buffer, so no need for the array previously used

int getch(void);
void ungetch(int c);

int main()
{
    ungetch('a');
    printf("%c", getch());
    ungetch(EOF);
    printf("%c", getch());
    return 0;
}

// if buf has char, return it. Otherwise return getchar()
int getch(void)
{
    int c;
    if (buf != '\0')
    {
        c = buf;
        buf = '\0';
        return c;
    }
    return getchar();
}

// sets buf to c
void ungetch(int c)
{
    if (c != EOF)
        buf = c;
}
Personal tools