Thread: pushback question (reverse polish calculator)

  1. #1
    Registered User
    Join Date
    Jul 2009
    Location
    Croatia
    Posts
    272

    pushback question (reverse polish calculator)

    This is the code for reverse polish calculator. I know how it works, but im confused by this exercise related to it:

    "Suppose that there will never be more then one char of pushback. Modify getch and ungetch accordingly".

    Isnt that actually true, that there will never be more then one character of pushback? Ungetch is used only in getop function and after the pushback the function returns a value to main. So basicaly, never can it happen that more then 1 character is pushed back, yet the code in the book is written in a way that pushback characters are being stored in an array?

    I also have one question: How to fix ungetch and getch so they handle EOF's correctly? Is it enough to just add a check in getch() if the readed char is EOF, and if so, return EOF value in main which then terminates the while loop?


    (the code is seperated into 5 source files, so you can easily see all the functions)
    Code:
    #include "calc.h"
    
    #define MAXOP 100
    int main(int argc, char *argv[])
    {
        
        int type;
        double op2;
        char s[MAXOP];
        
        while((type = getop(s)) != EOF)
        {
           switch(type) {
             case NUMBER:
                  push(atof(s));
                  break;
             case '+':
                  push(pop() + pop());
                  break;
             case '*':
                  push(pop() * pop());
                  break;
             case '-':
                  op2 = pop();
                  push(pop() - op2);
                  break;
             case '/':
                  if((op2 = pop()) != 0)
                    push(pop() / op2);
                  else 
                    printf("zero divisor\n");
                  break;
             case '\n':
                  printf("\t%g\n", pop());
                  break;
             default:
                  printf("unknown command\n");
                  break;
           }
        }
    
        
         getchar();
         return 0;
    }
    Code:
    #include <ctype.h> /* isdigit */
    #include "calc.h"
    
    /* get a operand or operator */
    int getop(char s[])
    {
        int i, c;
        
        while((s[0] = c = getch()) == ' ' || c == '\t')
              ;
              
        s[1] = '\0'; 
        
        if(!isdigit(c) && c!='.')
          return c;
        
        i = 0;
        if(isdigit(c))
          while(isdigit(s[++i] = c = getch()))
                 ;
        
        if(c == '.')
          while(isdigit(s[++i] = c = getch()))
               ;
        
        s[i] = '\0';
        if(c!=EOF)
          ungetch(c);
        
        return NUMBER;
    }
    Code:
    #include "calc.h"
    #define MAXVAL 100
    
    double val[MAXVAL];
    int sp = 0;
    
    void push(double c)
    {
         if(sp < MAXVAL)
           val[sp++] = c;
         else
           printf("stack full\n");
    }
    
    double pop()
    {
         if(sp > 0)
           return val[--sp];
         else {
           printf("stack empty\n");
           return 0.0;
         }
    }
    Code:
    #include "calc.h"
    #define MAXBUF 100
    
    int buf[MAXBUF];
    int bufp = 0;
    
    int getch()
    {
        return (bufp > 0) ? buf[--bufp] : getchar();
    }
    
    void ungetch(int c) //stores the temp char
    {
         if(bufp >= MAXBUF)
            printf("ungetch: too many characters\n");
         else
            buf[bufp++] = c;
    }
    Code:
    /* headers */
    #include <stdio.h>
    #include <stdlib.h>
    
    #define NUMBER '0'
    int getop(char []);
    
    void push(double);
    double pop();
    
    int getch();
    void ungetch(int);

  2. #2
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    Right now the ungetch() can remember up to 100 characters. That's obviously unnecessary if you can assume that you'll never pushback more than 1 character. You could modify it to just be something like:
    Code:
    #include "calc.h"
    
    int pushback = EOF;
    
    int getch()
    {
        int temp = pushback;
    
        pushback = EOF;
    
       return (temp == EOF) ? getchar() : temp;
    }
    
    void ungetch(int c) //stores the temp char
    {
         pushback = c;
    }
    EOF looks like it should already be handled correctly. getch() will return it to getop() which will return it here:
    Code:
        if(!isdigit(c) && c!='.')
          return c;
    If you understand what you're doing, you're not learning anything.

  3. #3
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Quote Originally Posted by Tool View Post
    This is the code for reverse polish calculator. I know how it works, but im confused by this exercise related to it:

    "Suppose that there will never be more then one char of pushback. Modify getch and ungetch accordingly".

    Isnt that actually true, that there will never be more then one character of pushback?
    Yep!
    Quote Originally Posted by Tool View Post
    Ungetch is used only in getop function and after the pushback the function returns a value to main. So basicaly, never can it happen that more then 1 character is pushed back, yet the code in the book is written in a way that pushback characters are being stored in an array?
    That's a question for the makers of C (K&R) to understand exactly what they had in mind while creating their magnum opus
    Quote Originally Posted by Tool View Post
    I also have one question: How to fix ungetch and getch so they handle EOF's correctly? Is it enough to just add a check in getch() if the readed char is EOF, and if so, return EOF value in main which then terminates the while loop?
    In this case only getop() needs to change to pushback c irrespective of its value.
    Last edited by itCbitC; 12-29-2009 at 11:03 AM.

  4. #4
    Registered User
    Join Date
    Jul 2009
    Location
    Croatia
    Posts
    272
    EOF looks like it should already be handled correctly. getch() will return it to getop() which will return it here:
    It wont cause EOF has allready been getchared and nowhere stored! Next getch call will try reading a char after EOF signal!

    In this case only getop() needs to change to pushback c irrespective of its value.
    You mean deleting the if(c!= EOF).

    But then ill have to edit getch(). I was thinking about something like this:

    Code:
    #include "calc.h"
    
    int buf = EOF;
    
    int getch()
    {
        int temp;
        
        if(buf == 1) return EOF;
        if(buf == EOF)
        {
          temp = getchar();
        }
        else
        {
          temp = buf;
          buf = EOF;
        }
        
        return temp;
    }
    
    void ungetch(int c) //stores the temp char
    {
         if(c == EOF)
         {
           buf = 1;
           return;
         }
         
         buf = c;
    }
    Last edited by Tool; 12-29-2009 at 11:49 AM.

  5. #5
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Quote Originally Posted by Tool View Post
    You mean deleting the if(c!= EOF).
    Yep!
    Quote Originally Posted by Tool View Post
    But then ill have to edit getch().
    If you use the source given in the "Bible", array buf[MAXBUF] is of type char but you have it of type int, and that's all that's needed. But testing for EOF in ungetch() doesn't make any sense when EOF isn't even being pushed back.
    Quote Originally Posted by Tool View Post
    I was thinking about something like this:

    Code:
    #include "calc.h"
    
    int buf = EOF;
    
    int getch()
    {
        int temp;
        
        if(buf == 1) return EOF;
        if(buf == EOF)
        {
          temp = getchar();
        }
        else
        {
          temp = buf;
          buf = EOF;
        }
        
        return temp;
    }
    
    void ungetch(int c) //stores the temp char
    {
         if(c == EOF)
         {
           buf = 1;
           return;
         }
         
         buf = c;
    }
    This will work only if you're actually pushing back an EOF, but are you?

  6. #6
    Registered User
    Join Date
    Jul 2009
    Location
    Croatia
    Posts
    272
    This will work only if you're actually pushing back an EOF, but are you?
    Yeah, i edited getop:

    Code:
    #include <ctype.h> /* isdigit */
    #include "calc.h"
    
    /* get a operand or operator */
    int getop(char s[])
    {
        int i, c;
        
        while((s[0] = c = getch()) == ' ' || c == '\t')
              ;
              
        s[1] = '\0'; 
        
        if(!isdigit(c) && c!='.')
          return c;
        
        i = 0;
        if(isdigit(c))
          while(isdigit(s[++i] = c = getch()))
                 ;
        
        if(c == '.')
          while(isdigit(s[++i] = c = getch()))
               ;
        
        s[i] = '\0';
        
        ungetch(c);
        return NUMBER;
    }
    Along with

    Code:
    #include "calc.h"
    
    int buf = EOF;
    
    int getch()
    {
        int temp;
        
        if(buf == 1) return EOF;
    
        if(buf == EOF)
        {
          temp = getchar();
        }
        else
        {
          temp = buf;
          buf = EOF;
        }
        
        return temp;
    }
    
    void ungetch(int c) //stores the temp char
    {
         if(c == EOF)
         {
           buf = 1;
           return;
         }
         
         buf = c;
    }
    Should work allright?

    If you use the source given in the "Bible", array buf[MAXBUF] is of type char but you have it of type int, and that's all that's needed.
    Whats the difference? Char cant support ascii larger then 127, so i used int instead, shouldnt it be int?
    Last edited by Tool; 12-29-2009 at 12:29 PM.

  7. #7
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    So what happens if the pushed back character is a 1 instead of EOF?
    The way it is written curently, the code will return EOF if buf equals 1.

  8. #8
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Quote Originally Posted by Tool View Post
    Whats the difference? Char cant support ascii larger then 127, so i used int instead, shouldnt it be int?
    Yep! but only after modifying the original source, but you started off on the right track so no change needed.

  9. #9
    Registered User
    Join Date
    Jul 2009
    Location
    Croatia
    Posts
    272
    A big OH! I totally forgot about that.

    I guess seting buf to -2 after EOF should work then, and seems the most appropriate since -1 is in buf by default.

    Code:
    #include "calc.h"
    
    int buf = EOF;
    
    int getch()
    {
        int temp;
        
        if(buf == -2) return EOF;
        
        if(buf == EOF)
        {
          temp = getchar();
        }
        else
        {
          temp = buf;
          buf = EOF;
        }
        
        return temp;
    }
    
    void ungetch(int c) //stores the temp char
    {
         if(c == EOF)
         {
           buf = -2;
           return;
         }
         
         buf = c;
    }
    Now theres just one more thing im sort of unsure about.

    "Add commands for handling variables. Its easy to provide 26 variables with single letter names.".

    Does this mean i should add a possibility of adding values to diffrent one letter variables and then storing them throughout the execution of the program?

    So for example, if i enter

    5 a =

    in the calculator, should that assign 5 to a, which after that i can use as

    a 10 +

    will get me 15?
    Last edited by Tool; 12-29-2009 at 02:38 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. another exercise question
    By luigi40 in forum C# Programming
    Replies: 3
    Last Post: 11-28-2005, 03:52 PM
  2. I'm not ask for ENTIRE program, only 1 Question !
    By Th3-SeA in forum C Programming
    Replies: 10
    Last Post: 10-01-2003, 12:33 PM
  3. Reverse() question?
    By correlcj in forum C++ Programming
    Replies: 9
    Last Post: 08-06-2002, 06:02 PM
  4. about reverse date(the 1st one is a wrong question)
    By Unregistered in forum C++ Programming
    Replies: 1
    Last Post: 03-08-2002, 03:51 PM
  5. what does this warningmean???
    By kreyes in forum C Programming
    Replies: 5
    Last Post: 03-04-2002, 07:53 AM