#define MAX 100
int *p;
int *tos;
int *bos;
void push(int i);
int pop(void);
int main ()
{
int a,b;
char s[80];
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");
char *endptr;
do {
printf("> ");
scanf("%s", s);
int val = strtol(s, &endptr, 10);
if (*endptr == '\0')
{
//printf("Got only the integer: %d\n", val);
}
else{ printf("operator: %s\n", endptr);
printf("Got the integer: %d\n", val);
}
/* tests */
switch(*endptr) {
case 'i':
printf("(Integer Mode)\n");
break;
case 'f':
printf("(Floating Point Mode)\n");
break;
case '+':
a = pop开发者_C百科();
b = pop();
printf("%d\n",a);
printf("%d\n",b);
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');
//end do while loop
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;
}
I think my switch statement is incorrect. I use strtol
to parse the integer and I can see that it's working:
2+
operator: + got the integer: 2
but if I try this:
1
2+
I get:
operator: +
Got the integer: 2 1 0 1
I should have gotten a 2 instead of the 0 and a 3 instead of the sum of 1. Any ideas?
You need to check if the endptr
is the same as the input pointer, to determine if no conversion took place:
if(endptr == s)
{
/* no integer found */
}
It looks like the integer on the same line as the operator doesn't get pushed onto the stack, only the single value appears to be pushed. Also, no need to call atoi() when pushing the found integer, use val since it's the result of strtol().
The easy fix is to move the default behavior out of the switch, push(val) prior to the switch statement and removing the default should do the trick.
Incase of the +, *, / cases, just do one pop and use val directly instead of the second pop. I guess that will make your code work.
I think you should include all of the code in your switch if you want us to check it for you.
You should probably show all of the code full stop. What does p point to, for e.g.?
Edit: following Patrick's extra code
Hi Patrick,
You never actually use your val variable. I suspect this is not what you want. You're getting the behaviour you see because (presumably) your stack is initialised to zeros and so your '+' is adding 1 to 0 and then pushing 1 back onto the stack. I'm not sure you're using strtol correctly.
Cheers, Dan
The following code appears to mostly do as I think you expect it to do:
#include <stdio.h>
#include <stdlib.h>
#define MAX 100
int *p;
int *tos;
int *bos;
void push(int i);
int pop(void);
int main ()
{
int a,b;
char s[80];
p = (int *) calloc(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");
char *endptr;
p++;
do {
printf("> ");
scanf("%s", s);
int val = strtol(s, &endptr, 10);
if (*endptr == '\0')
{
//printf("Got only the integer: %d\n", val);
}
else{ printf("operator: %s\n", endptr);
printf("Got the integer: %d\n", val);
}
/* tests */
if( endptr != s )
{
push(val);
}
switch(*endptr) {
case 'i':
printf("(Integer Mode)\n");
break;
case 'f':
printf("(Floating Point Mode)\n");
break;
case '+':
a = pop();
b = pop();
printf("%d\n",a);
printf("%d\n",b);
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;
}
} while (*s != 'q');
//end do while loop
return 0;
}
// Put an element on the stack
void push (int i)
{
if (p > bos){
printf("Stack Full\n");
return;
}
*p = i;
printf("pushed %d\n", *p);
p++;
}
// Get the element from the top of the stack
int pop (void)
{
p--;
if(p < tos) {
printf("Stack Underflow\n");
return 0;
}
printf("popped %d\n", *p);
return *p;
}
The funciton strol you used is okay. But the pramenter is risk. The syntax of strol is
`long int strtol (const char* str, char** endptr, int base);
with endptr is value that set by the function to the next character in str after the numerical value. You have to reset endptr pointer to NULL or the begining of str
do
{
printf("> ");
scanf("%s", s);
endptr = &s[0];
int val = strtol(s, &endptr, 10);
}
精彩评论