Jump to: navigation, search

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

Suppose there will never be more than one character of pushback. Modify getch and ungetch accordingly.



Warning: the answers on these pages are crowdsourced, open to anybody to provide/edit after free sign-up, have not all been vetted, might not be correct, let alone optimal, and should not be assumed to be.

Solution by Steven Huang

/* K&R Exercise 4-8 */
/* Steven Huang */

#include <stdio.h>

int buf = EOF; /* buffer for ungetch */

int getch(void) /* get a (possibly pushed back) character */
{
  int temp;

  if (buf != EOF) {
    temp = buf;
    buf = EOF;
  } else {
    temp = getchar();
  }
  return temp;                          
}
 
void ungetch(int c) /* push character back on input */
{
  if(buf != EOF)
    printf("ungetch: too many characters\n");
  else       
    buf = c;
}
 
int main(void)
{
  int c;

  while ((c = getch()) != EOF) {
    if (c == '/') {
      putchar(c);
      if ((c = getch()) == '*') { 
        ungetch('!');
      }         
    } 
    putchar(c);               
  }
  return 0;
}

Solution by Jesus Alvarez (Category 0)

/* K&R Exercise 4-8 */
/* Jesus Alvarez    */
#include <stdio.h>
#include <string.h>
#include <ctype.h>

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

int main()
{
        char c;

        /*
         * The purpose of getch() and ungetch() is to read characters from
         * getchar() while isdigit or isaplha is true. Once isdigit/isalpha is
         * not true, then reading has gone too far, and it must be pushed back
         * onto the stack for later precessing.
         */
        while ((c = getch()) != EOF) {
                if (isdigit(c)) {
                        /*
                         * Read until !isdigit(), meaning we have read one
                         * character too far.
                         */
                        putchar(c);
                        while(isdigit(c = getch())) {
                                putchar(c);
                        }
                        if (c != EOF) {
                                /* Send it back to the stack for future
                                 * processing. */
                                ungetch(c);
                        }
                } else {
                        /* All other characters. */
                        putchar(c);
                }
        }
        return 0;
}

int  buf = -2;       /* Buffer for getch() */

int getch(void)
{
        int tmp;
        if (buf > -2) {
                tmp = buf;
                buf = -2;
                return tmp;
        }
        return getchar();
}

void ungetch(int c)
{
        if (buf > -2) {
                printf("Ungetch: Too many characters.\n");
        } else {
                buf = c;
        }
}


Solution by menonsahab

/* There are many ways to do this. But the easiest way is to limit the BUFSIZE to 1. No additional code necessary.
Everything remains exactly the same as in K&R. I'm skipping the main() function for brevity. */

#include <stdio.h>
#define BUFSIZE 1

char 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

I made a small test program for this modification since I noticed exercise 4-10 requests for getch and ungetch to be removed. Also, exercise 4-9 builds off of only getch and ungetch so this will also be sufficient for that one.

#include <stdio.h>

/*
    Exercise 4-8. Suppose that there will never be more than one character of pushback. Modify getch and ungetch accordingly
*/

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());
    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)
{
    buf = c;
}
Personal tools