I was on here a while a go with a similar problem but I think with the wrong question. To give a bit of background, I a tasked with creating a C program to solve a postfix expression in the form
8 7 - 9 * =
What I think my problem is, is that my prof gave as some incorrect stack code. I say this because I am constantly getting the stack overflow (lol) error and my stack is nowhere near full. If it helps I'm using visual studio 2005. Here's my code:
#include <stdio.h>
` #include <stdlib.h>
#define STACK_SIZE 20
typedef int Bit;
Bit contents[STACK_SIZE];
int top = 0;
void make_empty(void);
int is_empty(void);
int is_full(void);
void push(Bit i);
int pop(void);
void stack_overflow(void);
void stack_underflow(void);
int main(void) {
Bit bit;
char operation;
int operand;
Bit current;
int result;
while(scanf("%d",¤t)!= '=')
{
push(current);
}
scanf("%c", &operation);
while(operation != '=')
{
scanf("%d", &operand);
printf("%d\n",top);
//Pushes any number into the stack
if(operand==1||operand==2||operand==3||operand==4||operand==5||operand==6||operand==7||operand==8||operand==9||operand==0)
{
printf("entered number loop\n");
bit = operand;
if(top==20)
{
stack_overflow();
}
push(&bit);
}
//Performs subtraction operation
else if(operation == '-')
{
printf("entered minus loop\n");
if(top==1)
{
stack_underflow();
}
result = pop() - pop();
bit = result;
if(top==20)
{
stack_overflow();
}
push(&bit);
}
//Performs addition operation
else if(operation == '+')
{
if(top==1)
{
stack_underflow();
}
result = pop() + pop();
bit = result;
if(top==20)
{
stack_overflow();
}
push(&bit);
}
//Performs multiplication operation
else if(operation == '*')
{
if(top==1)
{
stack_underflow();
}
result = pop() * pop();
bit = result;
if(top==20)
{
stack_overflow();
}
push(&bit);
}
//Performs division operation
else if(operation == '/')
{
if(top==1)
{
stack_underflow();
}
result = pop() / pop();
bit = result;
if(top==20)
{
stack_overflow();
}
push(&bit);
}
else if(operation == '=')
{
if(top==0)
{
stack_underflow();
}
printf("%d\n",pop());
break;
}
}
return 0;
}
void make_empty(void) {
top = 0;
}
int is_empty(void) {
return top == 0;
}
int is_full(void) {
return top == STACK_SIZE;
}
void push(Bit i) {
if (is_full())
stack_overflow();
else
contents[top++] = i;
}
int pop(void) {
if (is_empty())
stack_underflow();
else
return contents[top--];
}
void stack_overflow(void) {
printf("Error: stack overflow!\n");
exit(EXIT_FAILURE);
}
void stack_underflow(void) {
printf("Error: stack underflow!\n");
exit(EXIT_FAILURE);
}
Now I realize that my code is a little barbaric right now and for that I apologize. That being said, any help or input at all would be greatly appreciated and thank you all in advance.
Ok, so after taking everything into account, I think I'm getting close. Everything going into the stack properly and everything is being read properly. However, my new implementation includes making everything a character and then converting the integers when they need to be used. Here is my source code once again:
#include <stdio.h>
#include <stdlib.h>
#define STACK_SIZE 20
typedef int Bit;
char contents[STACK_SIZE];
int top = 0;
void make_empty(void);
int is_empty(void);
int is_full(void);
void push(char i);
char pop(void);
void stack_overflow(void);
void stack_underflow(void);
int main(void) {
char current = 'a';
char result = 'a';
char operation = 'a';
char char1;
char char2;
int number1;
int number2;
scanf("%c", ¤t);
//While program successfully scanned a number
while(current != '=')
{
//Performs subtraction operation
if(current == '-')
{
printf("entered if 2\n");
char1 = pop();
number1 = char1 - '0';
printf("%d\n", number1);
char2 = pop();
number2 = char2 - '0';
printf("%d\n", number2);
result = number1 - number2;
push(result);
}
//Performs addition operation
else if(current == '+')
{
printf("entered if 2\n");
char1 = pop();
number1 = char1 - '0';
printf("%d\n", number1);
char2 = pop();
number2 = char2 - '0';
printf("%d\n", number2);
result = number1 + number2;
push(result);
}
//Performs multiplication operation
else if(current == '*')
{
printf("entered if 2\n");
char1 = pop();
number1 = char1 - '0';
printf("%d\n", number1);
char2 = pop();
number2 = char2 - '0';
printf("%d\n", number2);
result = number1 * number2;
push(result);
}
//Performs division operation
else if(current == '/')
{
printf("entered if 2\n");
char1 = pop();
number1 = char1 - '0';
printf("%d\n", number1);
char2 = pop();
number2 = char2 - '0';
printf("%d\n", number2);
result = number1 / number2;
push(result);
}
else
{
push(current);
printf("%c\n", current);
}
scanf(" %c", ¤t);
}
//Prints result
printf("%c\n",pop());
return 0;
}
void make_empty(void) {
top = 0;
}
int is_empty(void) {
return top == 0;
}
int is_full(void) {
return top == STACK_SIZE;
}
void push(char i) {
if (is_full())
stack_overflow();
else
contents[top++] = i;
}
char pop(void) {
if (is_empty())
stack_underflow();
else
return contents[top--];
}
void stack_overflow(void) {
printf("Error: stack overflow!\n");
exit(EXIT_FAILURE);
}
void stack_underflow(void) {
printf("Error: stack underflow!\n");
exit(EXIT_FAILURE);
}
Please keep in mind that I have been playing around with it quite a bit, so there are random printfs and useless variables all for debugging purposes. Whenever I run it (with example input 3 5 + =) I get:
So again, please excuse my some what messy code as I am quite new to C but any help would be great!
This is an endless loop:
while(scanf("%d",¤t)!= '=') { push(current); }
scanf returns the number of fields read successfully. In your case this can be 0 or 1. You are comparing it to '=' which is ASCII 61. So the '"!=" is always true and you never come past this loop.
BTW, if you look at how push is implemented you see that the check for "stack overflow" is done using the is_full() function. is_full() is comparing top against STACK_SIZE. You are comparing top==20. You better should use is_full. This is more abstract and would work even if someone changed STACK_SIZE. You could even omit your checks for top==20 and top==0 because the only thing you do is call stack_underflow/stack_overflow, which is already done by the pop/push functions.
I don't see any problem with the stack. But there are at least two problems in your main.
push(&bit);
push accepts a Bit, not a Bit *. You should get a warning here, which you probably have ignored. Do not ignore the warnings.
while(scanf("%d",¤t)!= '=')
This is definitely wrong. scanf retuns the number of successful input.
operand==1||operand==2||operand==3||operand==4||operand==5||operand==6||operand==7||operand==8||operand==9||operand==0
Though this is not a bug, why should you write like this? You can easily replace with:
operand >= 0 && operand <= 9
And there might be many more problems.
You have a problem with the following line:
while(scanf("%d",¤t)!= '=')
The scanf function returns the number of items scanned, not the item. And scanning for %d will attempt to get an integer, not a character.
I think you should be looking more into something like:
while (scanf("%d",¤t) == 1)
push(current);
which will push integers on to the stack until it can no longer scan one (i.e., you get an operation).
This is almost certainly your problem since that particular scanf will generally only return 0 or 1, meaning it will never be equal to = (which is hex 0x3d or decimal 61 if you're using ASCII). It could return EOF in some cases but that still won't give you a value of 61.
The fact that it will never return 61 means that it will simply keep looping, pushing the value of current on to your stack until it overflows, which is the behaviour you're seeing.
Related
The user enters a string with an operation such as 4*5+2/3 and the code is supposed to make an expression tree out of it and the calculate said expression tree. I am having a problem where the program is making the expression tree with the decimal values of the ascii table instead of the actual numbers.
For example instead of 4*5+2/3, the program is storing and using 52 42 53 43 50 47 51 for the calculations. My desired run screen would be:
1 //this is the number of strings
4*5+2/3 //this is the string itself
20 //this is the result
However what I am getting is:
1 //this is the number of strings
4*5+2/3 //this is the string itself
2756 //this is the result
That is because the code is doing 52*53+50/51(because it is using the ascii values) and not 4*5+2/3.
I believe the reason for this is because I am storing 4*5+2/3 in a string of char and not in an array of int. I do not know if this is the case and would like some help.
You will not be able to run the following code as it is not complete but the whole program is five files and I do not know if I should put all of it here. I am new to both trees and StackOverflow.
This is my Make Expression Tree function and my Calculate Expression Tree function:
BTreeNode* MakeExpTree(char* exp, int len)
{
Stack stack;
BTreeNode * node, *right_node, *left_node;
InitStack(&stack);
for(int i = 0; i < len; i++){
if('0' <= exp[i] && exp[i] <= '9'){
node = CreateNode(exp[i]);
}
else{
right_node = PeekNode(&stack), Pop(&stack);
left_node = PeekNode(&stack), Pop(&stack);
node = CreateNode(exp[i]);
CreateRightSubtree(node, right_node);
CreateLeftSubtree(node, left_node);
}
PushNode(&stack, node);
}
return PeekNode(&stack);
}
int CalculateExpTree(BTreeNode* root)
{
int ret, op1, op2;
if(root == NULL){
return 0;
}
if(root->left_child == NULL && root->right_child == NULL){
return root->item;
}
op1 = CalculateExpTree(root->left_child);
op2 = CalculateExpTree(root->right_child);
switch(root->item){
case '+':
ret = op1 + op2;
break;
case '-':
ret = op1 - op2;
break;
case '*':
ret = op1 * op2;
break;
case '/':
ret = op1 / op2;
break;
case '#':
ret = op1 * pow( 2, op2);
break;
case '#':
ret = op1 / pow( 2, op2);
break;
}
return ret;
}
This is how I store the string from stdin in main function:
int main()
{
int num_exp, result, len = 0;
char input[10];
char IDK[129];
fgets(input, 9, stdin); //user enters number of strings
int m = sscanf(input, "%d", &num_exp);
char string[100][129] = { 0 };
char postfix[100][129] = { 0 };
for(int i = 0; i < num_exp; i++){
fgets(IDK, 129, stdin); //user enters string
int mm = sscanf(IDK, "%s", string[i]); //is this where the problem lies?
} //should I not be storing it in a char string?
for(int x = 0; x < num_exp; x++){
InfixToPostfix(string[x], postfix[x]); //converts strings from infix to postfix
}
BTreeNode* tree;
for(int k = 0; k < 129; k++){ //calculates length of string
if(postfix[0][k] == '\0'){
break;
}
len++;
}
tree = MakeExpTree(postfix[0], len); //makes expression tree
result = CalculateExpTree(tree); //calculates expression tree
//or is the problem in this function?
printf("%d \n", result);
return 0;
}
I am not understanding clearly what you are doing and it would help my learning too if you shared from what source are you learning these (we can chat in chat room) but I also tried to do similar thing and in my style it works partially (that is, sometimes when I insert larger number the answer is wrong but for small numbers generally correct).So you might get some help form my style of this code that calculates given string (A little help for me also would be appreciated commenters!!). My code:
#include <stdio.h>
#include <string.h>
#include "stackforcalc.h"
int isOperand(char b){
if(b>='0' && b<='9'){
return 1;
}else{
return 0;
}
}
int isOperator(char b){
if(b=='+' || b=='-' || b=='*' || b=='/'){
return 1;
}
return 0;
}
int getwt(char b){
int g=-1;
switch (b)
{
case '+':
case '-':
g=1;
break;
case '/':
case '*':
g=28787868;
break;
}
return g;
}
int higherprecedence(char a,char b){
int c=getwt(a);
int d=getwt(b);
return (c>=d)?1:0;
}
int infToPost(char *b,char *str){
int j=0;
for(int i=0;i<strlen(b);i++){
if(b[i]== ' ' || b[i]== ',' ){
continue;
}
else if(isOperator(b[i])){
str[j]=' ';
j++;
while(!empty() && gettop() != '(' && higherprecedence(gettop(),b[i])){
str[j]=gettop();
j++;
pop();
}
push(b[i]);
}
else if(isOperand(b[i])){
str[j]=b[i];
j++;
}
else if(b[i]=='('){
push(b[i]);
}
else if(b[i] ==')'){
while(!empty() && gettop() != '('){
str[i]=gettop();
j++;
pop();
}
pop();
}
}
while(!empty()){
str[j]=gettop();
j++;
pop();
}
}
int Evaluate(int t,char y,int r){
int ty;
switch(y){
case '+':
ty=t+r;
break;
case '-':
ty=r-t; //I inverted these.
break;
case '*':
ty=r*t;
break;
case '/': //I inverted these because
ty=r/t; //even though I did t/r it performed r/t.
break; //may be somewhere before the numbers were swapped
default:
ty=-1;
break;
}
return ty;
}
int calculatepostfix(char *c){
for(int i=0;i<strlen(c);i++){
if(c[i]==' ' || c[i]==','){
continue;
}
else if(isOperator(c[i])){
int op1=gettop2();
pop2();
int op2=gettop2();
pop2();
int oper=Evaluate(op1,c[i],op2);
push2(oper);
}
else if(isOperand(c[i])){
int res=0;
while(i<strlen(c) && isOperand(c[i])){
res=(res*10)+(c[i]-'0');
i++;
}
i--;
push2(res);
}
}
return gettop2();
}
int main(){
char b[65];
printf("\n \n**-- Calculator --**\n");
printf("Enter expression: ");
fgets(b,sizeof(b),stdin);
char str[50];
infToPost(b,str);
int tt =calculatepostfix(str);
printf("Your answer is: %d",tt);
}
The code in "stackforcalc.h" is
#ifndef stacycalc
#define stacycalc
#define maxsize 50
char a[maxsize];
int top=-1;
int abc[maxsize];
int to=-1;
void push2(int re){ abc[++to]=re; }
void push(char b){ a[++top]=b; }
void pop2(){ to--; }
void pop(){ top--;}
int gettop2(){ return (to==-1)?-1:abc[to]; }
char gettop(){ return (top==-1)?0:a[top]; }
int empty(){ return (top==-1)?1:0; }
#endif
That is because the code is doing 52*53+50/51 (because it is using the ascii values) and not 4*5+2/3.
Yes.
I believe the reason for this is because I am storing 4*5+2/3 in a string of char and not in an array of int.
No.
In C, int is just a bigger char. There's nothing magical about them; they both hold numbers.
There are a variety of ways to derive the integer value from an ASCII character. If you have exactly one character and don't want to use a library, you can "mask off" the bits: since the ASCII range for digits is 0x30 - 0x39,
static char string[] = "4";
int value = string[0] & 0x0F;
does the trick. For more complex operations, my favorite is sscanf(3), but many use atoi(3) or various flavors of strtol(3).
What I'm trying to obtain is a calculator that will take infix notation, ignore insignificant whitespace characters like " " or '#', then convert that infix notaion into postfix notation and do simple calculations like addition, subtraction etc. So far the code is taking input in infix notation trimming it in a way that ignores insignificant whitespace characters and outputs the postfix notation.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>;
#include <ctype.h>;
#define MAX_LENGTH 100
//Functions
void push(char x);
char pop();
void trimString(char string[], char newString[]);
void inputToRPN(char trimmedExp[], char rpnExp[]);
int calculateRPN(char rpnExp[]);
char stack[MAX_LENGTH];
char resStack[MAX_LENGTH];
int top = -1;
int resTop = -1;
int index = 0;
int main() {
int res;
char exp[MAX_LENGTH] = "10 +2";
char trimmedExpression[MAX_LENGTH];
char rpnExpression[MAX_LENGTH];
// Input commented out as per suggestion in comments
//printf("Enter expression : ");
//fgets(exp, 100, stdin);
printf("Infix expression: %s \n", exp);
trimString(exp, trimmedExpression);
printf("\n");
inputToRPN(trimmedExpression, rpnExpression);
res = calculateRPN(rpnExpression);
//printf("Result of calculation: %d", res);
return 0;
}
void push(char x) {
stack[++top] = x;
}
char pop() {
if (top == -1)
return -1;
else
return stack[top--];
}
int priority(char x) {
if (x == '(')
return 0;
if (x == '+' || x == '-')
return 1;
if (x == '*' || x == '/')
return 2;
return 0;
}
void trimString(char string[], char newString[]) {
int i = 0, j = 0;
while (string[i] != '\0' && string[i] != 10) {
// Range of significant characters
if (string[i] >= '(' && string[i] <= '9') {
newString[j] = string[i];
i++, j++;
}
else {
i++;
}
}
newString[j] = 0;
}
void inputToRPN(char trimmedExp[], char rpnExp[]) {
char* e, x;
e = trimmedExp;
while (*e != '\0') {
// Add to RPN if character is alphanumeric
if (isalnum(*e)) {
rpnExp[index] = *e;
index++;
}
// Add to stack if is an open brace
else if (*e == '(')
push(*e);
// Add all operators to the expression until finding open braces
else if (*e == ')') {
while ((x = pop()) != '(') {
rpnExp[index] = x;
index++;
}
}
// If none of the above, that is an operator - check it's priority.
// If it's priority is less that that of the one on top of the stack add the operator from the top of the stack to the expression; untill it's priority is higher.
// At the end add current operator to the stack.
else {
while (priority(stack[top]) >= priority(*e)) {
rpnExp[index] = pop();
index++;
}
push(*e);
}
e++;
}
while (top != -1) {
rpnExp[index] = pop();
index++;
}
// Terminating character at the end of the string
rpnExp[index] = 0;
}
void pushRes(char x) {
printf("pushing: %c \n", x);
resStack[++resTop] = x;
}
char popRes() {
printf("poping \n");
if (resTop == -1)
return -1;
else
return resStack[resTop--];
}
int isValidOperator(char c) {
if (c == '/' || c == '*' || c == '+' || c == '-')
return 1;
else
return 0;
}
int calculateRPN(char rpnExp[]) {
// Doesnt do anything yet, just prints out the compiled reverse polish notation
char* c;
int result = 0;
c = rpnExp;
printf("Postfix expression: %s", rpnExp);
return result;
}
The problem I've stumbled upon is when the infix input has multiple digits say 10+2 the code will treat each digit individually. Therefore the whole expression will be invalid when calculating result. I'm almost certain the issue lies in this line of code:
// Add to RPN if character is alphanumeric
if (isalnum(*e)) {
rpnExp[index] = *e;
index++;
}
Despite that I've got no idea how should i treat multiple digits while adding them to the expression, since the input is in form of character and there can be N amount of digits that have coresponding ascii values which range from 0-9. Looking forward to your answears.
Edit: made it so the code compiles and the input is hard coded.
Okay, so thanks to Bodos suggestions I've fixed the issue. Adding one while loop in this section:
if (isalnum(*e)) {
rpnExp[index] = *e;
index++;
}
enabled me to add one character after every number (including the N digit ones).
Thanks to which I was later able to perform calculations in calculateRPN function that would eventually lead to correct answear.
The issue has been resolved.
I made a program calculating postfix equations but something is going wrong when entering the while loop and I don't know why.
I tried to see what is going wrong, so I put a printf statement over each step in order to find the problem. My pointer t gets the value of the first address in my table exp. Here is where things goes wrong.
Before entering the while loop ,to see if *t contains a digit or not, the value is as expected. After entering the loop it becomes random numbers but always end in the value -1 for a reason I don't know and this messes up my entire program. What am I doing wrong?
#include "MyStack.h"
int main(){
int i = 0, *t, exp[N], stack[N];
char c;
int n1, n2, obj;
printf ("Give postfix formula for evaluation:");
while((c = getchar()) != '\n'){
exp[i] = c - 48;
printf("%d\n", exp[i]);
i++;
}
t = exp;
printf("\nValue of pointer t %d\n",*t);
while(*t != '\n'){
printf("\nValue of pointer t after entering the loop %d\n",*t);
if(isdigit(*t)){
obj = *t - 48;
printf("%d\n", obj);
push(stack, t, obj);
}
else{
n1 = pop(stack, t);
n2 = pop(stack, t);
switch(*t){
case '+': push(stack, t, n1 + n2); break;
case '-': push(stack, t, n1 - n2); break;
case '*': push(stack, t, n1 * n2); break;
case '/': {
if(n1 == 0){
printf("Division with 0 is not eligible\n");
break;
}
else push(stack, t, n2 / n1); break;
}
}
}
}
for (i=0;i<N;i++)
printf ("%d\n",exp[i]);
printf("\nThe result of expression %s = %d\n\n",exp,pop(stack, t));
return 0;
}
void push(int stack [], int *t, int obj)
{
if ((*t) == (N - 1))
{
printf("Stack overflow...\n");
getch();
abort();
}
else stack[++(*t)] = obj;
}
int pop(int stack[], int *t)
{
int r;
if ((*t) < 0)
{
printf("Stack empty...\n");
printf("Error in expression\n");
getch();
abort();
}
else r = stack[(*t)--];
return (r);
}
"MyStack.h" contains the libraries I need and the declaration of functions pop and push. Ideally, *t should contain the first digit, then pushing it into stack and then keep on pushing in the next digits until *t points to an operator. There it should pop out the last 2 digits pushed from the stack, do the operation and return the result in the ```stuck``.
But instead this happens http://prntscr.com/nrf7b9
As you can see although it gets the correct value it keeps on looping and changing values till it becomes -1 then proceeding to isdigit function.
I have a problem with converting a string like "(5+2)*3" to be able to evaluate to be 21.
Here is my code:
char inp[10];
printf("Write it: ");
scanf("%s", inp);
printf("Okay, computing!\n");
printf("INPUT: %s \n", inp);
printf("It's %d \n", (int)inp);
I would like to get a number at the end.
This code is working:
printf("19+31 is '''%d'''", 19+31);
And i need to use the second argument - the 19+31 - to be my input.
The first code outputs this:
Write it: 4+4
Okay, computing!
INPUT: 4+4
It's 329554704
You can't do this directly. C has no built-in way to evaluate expressions which are entered (as an arbitrary string) at run time. But that's exactly what you need here.
Writing an expression evaluator is a very interesting exercise -- but probably not for your first (or even second) C program.
Here is a tiny example to give you a feel for it:
#include <stdio.h>
#include <stdlib.h>
int eval(char *);
int main()
{
char expr[100];
int x;
printf("Type an expression:\n");
fgets(expr, sizeof(expr), stdin);
x = eval(expr);
printf("Answer: %d\n", x);
}
int eval(char *str)
{
char *p;
int lhs, rhs;
char op;
int r = 0;
lhs = strtol(str, &p, 10);
while(*p == ' ') p++;
op = *p++;
rhs = strtol(p, &p, 10);
switch(op) {
case '+': r = lhs + rhs; break;
case '-': r = lhs - rhs; break;
case '*': r = lhs * rhs; break;
case '/': r = lhs / rhs; break;
}
return r;
}
This works, but it's terribly limited: it handles only simple two-term expressions a+b, a-b, a*b, and a/b. (What's worse, there's no obvious way to extend it to handle fully-general expressions with parentheses and more than two terms. Handling fully-general expressions will require a completely different, more sophisticated approach.)
Addendum: Here's a -- didactically challenged -- example of that "more sophisticated approach":
#include <stdio.h>
#include <ctype.h>
int e0(char *);
int e1(char **);
int e2(char **);
int e3(char **);
void w(char **);
void q();
int main()
{
char b[100];
while(fgets(b, sizeof(b), stdin))
printf("%d\n",e0(b));
}
int e0(char *s)
{
return e1(&s);
}
int e1(char **s)
{
int r = e2(s);
while(1) {
w(s);
switch(*(*s)++) {
case '+': r += e2(s); break;
case '-': r -= e2(s); break;
default: (*s)--; return r;
}
}
}
int e2(char **s)
{
int r = e3(s);
while(1) {
w(s);
switch(*(*s)++) {
case '*': r *= e3(s); break;
case '/': r /= e3(s); break;
default: (*s)--; return r;
}
}
}
int e3(char **s)
{
int c;
w(s);
c = *(*s)++;
if(isdigit(c)) {
c -= '0';
while(isdigit(**s)) c = 10 *c + *(*s)++ - '0';
return c;
} else if(c == '-') {
return -e3(s);
} else if(c == '(') {
int r = e1(s);
w(s);
if(*(*s)++ != ')') {
q();
(*s)--;
}
return r;
} else {
q();
return 0;
}
}
void w(char **s)
{
while(**s == ' ' || **s == '\t' || **s == '\n') (*s)++;
}
void q()
{
fprintf(stderr, "?\n");
}
This works, and you're welcome to compile it and play with it. It's an unsophisticated implementation of a recursive descent parser for simple expressions involving integers, +, -, *, /, parentheses, and unary -. It can handle things like 1+2*3, (1+2)*3, and 1----2----3. (That last example is legal under this parser, though not in C.)
I called it "didactically challenged" because it's not designed for teaching -- it's a cleanup of an ill-inspired attempt I made many years ago to squeeze the code down to a bare minimum, resulting in something that was practically an IOCCC entry.
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
The code below is my subprogram to do reverse polish notation calculations... basically +, -, *, and /. Everything works in the program except when I try to add 2.5 and 2.5 the program gives me 4.0... I think I have an idea why, but I'm not sure how to fix it... Right now I am reading all the numbers and operators in from command line as required by this assignment, then taking that string and using sscanf to get the numbers out of it... I am thinking that somehow the array that contains the three characters '2', '.', and '5', is not being totally converted to a float... instead i think just the '2' is. Could someone please take a look at my code and either confirm or deny this, and possibly tell me how to fix it so that i get the proper answer? Thank you in advance for any help!
float
fsm (char mystring[])
{
int i = -1, j, k = 0, state = 0;
float num1, num2, ans;
char temp[10];
c_stack top;
c_init_stack (&top);
while (1)
{
switch (state)
{
case 0:
i++;
if ((mystring[i]) == ' ')
{
state = 0;
}
else if ((isdigit (mystring[i])) || (mystring[i] == '.'))
{
state = 1;
}
else if ((mystring[i]) == '\0')
{
state = 3;
}
else
{
state = 4;
}
break;
case 1:
temp[k] = mystring[i];
k++;
i++;
if ((isdigit (mystring[i])) || (mystring[i] == '.'))
{
state = 1;
}
else
{
state = 2;
}
break;
case 2:
temp[k] = '\0';
sscanf (temp, "%f", &num1);
c_push (&top, num1);
i--;
k = 0;
state = 0;
break;
case 3:
ans = c_pop (&top);
if (c_is_empty (top))
return ans;
else
{
printf ("There are still items on the stack\n");
exit (0);
case 4:
num2 = c_pop (&top);
num1 = c_pop (&top);
if (mystring[i] == '+'){
ans = num1 + num2;
return ans;
}
else if (mystring[i] == '-'){
ans = num1 - num2;
return ans;
}
else if (mystring[i] == '*'){
ans = num1 * num2;
return ans;
}
else if (mystring[i] == '/'){
if (num2){
ans = num1 / num2;
return ans;
}
else{
printf ("Error: cannot divide by 0\n");
exit (0);
}
}
c_push (&top, ans);
state = 0;
break;
}
}
}
}
Here is my main program:
#include <stdio.h>
#include <stdlib.h>
#include "boolean.h"
#include "c_stack.h"
#include <string.h>
int main(int argc, char *argv[])
{
char mystring[100];
int i;
sscanf("", "%s", mystring);
for (i=1; i<argc; i++){
strcat(mystring, argv[i]);
strcat(mystring, " ");
}
printf("%.2f\n", fsm(mystring));
}
and here is the header file with prototypes and the definition for c_stack:
#include "boolean.h"
#ifndef CSTACK_H
#define CSTACK_H
typedef struct c_stacknode{
char data;
struct c_stacknode *next;
} *c_stack;
#endif
void c_init_stack(c_stack *);
boolean c_is_full(void);
boolean c_is_empty(c_stack);
void c_push(c_stack *,char);
char c_pop(c_stack *);
void print_c_stack(c_stack);
boolean is_open(char);
boolean is_brother(char, char);
float fsm(char[]);
in response to sixlettervariables:
Part of the assignment is to take an existing string with numbers and decimals in the array and use them to create a float which is what I am doing in these lines of code:
case 1:
temp[k] = mystring[i];
k++;
i++;
if ((isdigit (mystring[i])) || (mystring[i] == '.')) {
state = 1; } else {
state = 2;
}
break;
case 2:
temp[k] = '\0';
sscanf (temp, "%f", &num1);
c_push (&top, num1);
i--;
k = 0;
state = 0;
break;
Your stack stores char data:
typedef struct c_stacknode{
char data;
struct c_stacknode *next;
} *c_stack;
char, by definition, does not store floating point data. Instead, an integer conversion occurs when you call c_push, truncating 2.5 to 2.
You need to update your definition of struct c_stacknode, and its family of related methods, to support float data.
Could you also share the definition of c_stack? It looks like it's a stack of integer type, rounding any floating point input down. That way, 2.5 + 2.5 == 4.
if you define your variables as
int x=2.5;
and
int y=2.5;
An later you make something like
if((x+y)==4.0)
It will be true.
The engine will transform the floats numbers into integers. I guess you are doing something like this.
Look for the variables definitions.