2009-01-24 8 views
8

¿Alguien me puede explicar el propósito de ungetch? Esto es de K & R capítulo 4 donde crea una Calculadora polaca inversa.¿Cuál es el propósito de ungetc (o ungetch de K & R)?

He ejecutado el programa sin la llamada para deshacer y en mis pruebas todavía funciona igual.

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

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

} 

(He quitado el operador ternario en getch para hacerlo más claro.)

Respuesta

26

No conozco el ejemplo específico al que se refiere (Han pasado 23 años desde que leí K & R, y esa fue la primera edición), pero a menudo, al analizar, es conveniente "echar un vistazo" a el siguiente personaje para ver si es parte de lo que está analizando actualmente. Por ejemplo, si está leyendo un número, quiere seguir leyendo los dígitos hasta que llegue a un valor que no sea un dígito. Ungetc permite que el lector de números mire al siguiente personaje sin consumirlo para que otra persona pueda leerlo. En el ejemplo de Greg Hewgill de "2 3+", el lector de números leería los 3 dígitos, luego leería el signo más y sabría que el número había finalizado, luego, desataría el signo más para que pueda leerse más tarde.

+0

Muchas gracias. Tiene mucho más sentido ahora. – Tyler

+0

Aunque podría ser sólo una semántica, ungetc le permite "empujar hacia atrás" un carácter después de leerlo para volver a leerlo en la siguiente lectura. Eso no es lo mismo que echar un vistazo, lo que implica una lectura sin consumo. –

+3

Sí, peek es equivalente a getc seguido de ungetc. –

10

intente ejecutar el programa sin espacios alrededor de operadores. No recuerdo exactamente el formato de ese ejemplo y no tengo K & R práctico, pero en lugar de usar "2 3 +" intente con "2 3+". El ungetch() se usa probablemente al analizar números, ya que el analizador de números leerá los dígitos hasta que obtenga algo que no sea un dígito. Si el no dígito es un espacio, el próximo getch() leerá el + y todo estará bien. Sin embargo, si el siguiente dígito no es +, deberá volver a colocarlo en la secuencia de entrada para que el ciclo de lectura principal pueda encontrarlo nuevamente.

Espero que esté recordando el ejemplo correctamente.

+0

Gracias que hace el truco! – Tyler

+1

¡Genial! Como es nuevo en Stack Overflow, no se olvide de "aceptar" (haga clic en la marca de verificación) en la respuesta más útil. –

4

Se usa mucho para los escáneres léxicos (la parte del compilador que divide el texto en fragmentos como nombres de variables, constantes, operadores, etc.). La función no es necesaria para el escáner, es muy conveniente.

Cuando lee un nombre de variable, por ejemplo, no sabe cuándo termina hasta que lee un carácter que no puede formar parte del nombre de la variable. Pero luego debes recordar ese personaje y encontrar la forma de comunicarlo al siguiente fragmento del lexer. Podría crear una variable global o algo así, o pasarla a la persona que llama, pero ¿cómo puede devolver otras cosas, como los códigos de error? En su lugar, debe deshacer() el carácter para volver a colocarlo en la secuencia de entrada, haga lo que necesite con su nombre de variable y retorno. Luego, cuando el lexer comienza a leer el siguiente fragmento, no tiene que buscar caracteres extra por ahí.

+0

Gracias por la respuesta. Es útil tener ejemplos de uso reales. – Tyler

-2

Tome un vistazo a este código, se entenderá:

#include <conio.h> 
#include <stdio.h> 
int main() 
{ 
    int y=0; 
    char t[10]; 
    int u=0; 
    ungetch('a'); 
    t[y++]=getch(); 
    ungetch('m'); 
    t[y++]=getch(); 
    ungetch('a'); 
    t[y++]=getch(); 
    ungetch('z'); 
    t[y++]=getch(); 
    ungetch('z'); 
    t[y++]=getch(); 
    ungetch('a'); 
    t[y++]=getch(); 
    ungetch('l'); 
    t[y++]=getch(); 
    ungetch('\0'); 
    t[y++]=getch(); 
    ungetch('\0'); 
    t[y++]=getch(); 
    ungetch('\0'); 
    t[y++]=getch(); 
    printf("%s",t); 
    return 0; 
} 
Cuestiones relacionadas