views:

214

answers:

4

How do I read in the following input in my RPN calculator so that it will find the operator no matter what order?

2
2+
4

As of now my scanf only sees the first char in the string and I can only do this:

2
2
+
4

I'm also trying to add an option for integer vs floating point mode. (ex. when 'i' is entered, operate in floating point and vice versa.)

#include <stdio.h>
#include <stdlib.h>

#define MAX 100

int *p;
int *tos;
int *bos;

void push(int i);
int pop(void);

int main (void)
{
int a, b;
//float c, d;
char s[80];
//char op;  //declare string of 80 chars

p = (int *) malloc(MAX*sizeof(int)); //get stack memory
if (!p){
 printf("Allocation Failure\n");
 exit(1);
 }
 tos = p;
 bos = p + MAX-1;

 printf("\nRPN Calculator\n");
 printf("Enter 'i' for integer mode\n");
 printf("Enter 'f' for floating point mode\n");
 printf("Enter 'q' to quit\n");

 do {
 printf("> ");
 // gets(s);
 // scanf("%s", s);  //read integer
 scanf("%s", s);
 // switch (*s) {


 switch(*s) {
   case 'i':
       printf("(Integer Mode)\n");
   break;
   case 'f':
       printf("(Floating Point Mode)\n");
   break;
   case '+':
       a = pop();
       b = pop();
       printf("%d\n", a+b);
       push(a+b);
   break;
   case '-':
       a = pop();
       b = pop();
       printf("%d\n", b-a);
       push(b-a);
       break; 
  case '*':
       a = pop();
       b = pop();
       printf("%d\n", a*b);
       push(a*b);
  break;
  case '/':
       a = pop();
       b = pop();
       if(a == 0){
         printf("Cannot divide by zero\n");
  break;
  }
       printf("%d\n", b/a);
       push(b/a);
  break;
  case '.':
       a = pop();
       push(a);
       printf("Current value on top of stack: %d\n", a);
  break; 
  default:
       push(atoi(s));
  }

 } while (*s != 'q');

 return 0;
}


 // Put an element on the stack

 void push (int i)
 {
 if (p > bos){
   printf("Stack Full\n");
 return;
 }
  *p = i;
  p++;
 }

// Get the element from the top of the stack

int pop (void)
{
 p--;
 if(p < 0) {
    printf("Stack Underflow\n");
 return 0;
 }
 return *p;
 }
+1  A: 

Your scanf reads the whole string. It's the following switch that judges by the first character and misses that + in 2+.

To improve it you can use the strtol function. It will parse an integer out of the string and return to you the location where the integer ended - if that's still not the end of the string, there may be an operator there.

A similar function for floating point numbers is strtod.


Here's some sample code of strtol applicable to your example:

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


int main()
{
    char* input = "25+";
    char* endptr;

    int val = strtol(input, &endptr, 10);

    if (*endptr == '\0')
    {
        printf("Got only the integer: %d\n", val);
    }
    else
    {
        printf("Got an integer %d\n", val);
        printf("Leftover: %s\n", endptr);
    }


    return 0;
}
Eli Bendersky
Could you give me an example using my code? I read the syntax but I'm not familiar on how to use it. This isn't working: scanf("%s",s);n = strtol(s, 0, 10);switch(n){}
patrick
@unknown (google): updated with a code example
Eli Bendersky
Thank you for your help! Got it running correctly.
patrick
@unknown: glad I helped. Good luck
Eli Bendersky
A: 

I'm not sure if I fully understood your question, but you could iterate through the string like this:

for(i = 0; i < strlen(s); i++)
{
   // Here comes your switch section like this
   switch(s[i]) {
    .....
   }

}

Remember also to include string.h.

ah, `for(...;i<strlen(s);...)`, the sure way to make any O(N) algorithm into O(N^2) :-)
Eli Bendersky
yes, but wasn't the underlying mechanism in the original code also such? See the example of having 22 entered so that there was number 2 in first and second row.
A: 

I really didn't understand your code.

If expect the user to enter one character each time, I mean one character + enter, you should use a simple char instead of char[]. And if you pretend to use a string you should receive it and parse it pzico said. You could do something like that. The problem would be in the treatment of numbers with multiple digits, but thinking a little bit you can fix this problem. I wrote an attempt, but I'm pretty sure it's not going to work.

printf("\nRPN Calculator\n");
printf("Enter 'i' for integer mode\n");
printf("Enter 'f' for floating point mode\n");
printf("Enter 'q' to quit\n");
scanf("%c", s);

switch(*s){

case 'i':  
    printf("(Integer Mode)\n");  
break;  
case 'f':  
    printf("(Floating Point Mode)\n");  
break;  
case 'q':  
    printf("Bye Bye\n");  
    return;  
break;  

} printf("Enter the expression one character each time\n");

do {

scanf("%c", s);   
switch(s) {   
    case '+':   
        a = pop();      
        b = pop();     
        printf("%d\n", a+b);      
        push(a+b);
    break;
    case '-':
        a = pop();
        b = pop();
        printf("%d\n", b-a);
        push(b-a);
    break; 
    case '*':
        a = pop();
        b = pop();
        printf("%d\n", a*b);
        push(a*b);
    break;
    case '/':
        a = pop();
        b = pop();
        if(a == 0){
            printf("Cannot divide by zero\n");
            break;
        }
        printf("%d\n", b/a);
        push(b/a);
    break;
    case '.':
        a = pop();
        push(a);
        printf("Current value on top of stack: %d\n", a);
    break; 
    default:
        a = pop()*10+atoi(s);
        push(a);
}  

} while (s != 'q');

Another problem in your code is in your pop function. What do you want to do with this test:

if(p < 0) {
printf("Stack Underflow\n");
return 0;
}

You are expecting your pointer to reach the address 0?

Anyway I hope this is not your homework.

Rafael
Rather than default assumes a digit (try '%' for `s`), use the `isdigit()` function. Remember that the `default:` case is for anything that does not match any of the other cases in the `switch` statement. Another solution is to add case statements for each character in '0' ... '9', such as: `case '0': case '1':`
Thomas Matthews
A: 

Since you are mixing characters with numbers, you will have read the input as characters and convert to numbers as necessary. See strtoul() for converting from characters to numbers.

Drawing this as a state machine may be helpful.

Thomas Matthews