C program, Stack Calculator [closed] - c

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.
Can someone please take a look at my code below and help me out. Ive been trying to fix this for hours but i cant figure out what's wrong. It's a program written in C that is supposed to take the operations of a stack calculator and store the operands of a mathematical expression. When an operation is performed, the last two values on the stack are removed and used as the operands, then the result of the operation is placed on the stack. However, I'm not getting the right numbers. Please take a look at my code. I know it's long, but I appreciate it. Thanks.
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#define SIZE 10
#define MAXINPUT 255
void printStack(int stack[], int tos)
{
if (isEmpty(tos))
{
printf("Stack is empty\n");
printf("---------------------------------------\n");
return;
}
printf("Stack: ");
while (tos < SIZE)
{
printf("[%d] " , stack[tos]);
tos++;
}
printf("\n---------------------------------------\n");
}
int top (int stack[], int tos)
{
if(isEmpty(tos))
return;
return stack [tos];
}
int isEmpty(int tos)
{
if (tos < 0)
return 1;
}
int isFull (int tos)
{
if(tos >= SIZE - 1)
return 1;
}
void push(int val, int stack [], int *tos)
{
if(isFull(*tos))
return;
(*tos)++;
stack[*tos] = val;
}
int pop (int stack [], int *tos)
{
if(isEmpty(*tos))
return;
int val = stack[*tos];
(*tos)--;
return val;
}
void clear(int *tos)
{
*tos = -1;
}
int getInput (char *input)
{
printf("+------------------------------{Choose an option}------------------------------+\n");
printf("| (q) : quit the program. |\n"
"| (integer value) : an integer value (either positive or negative) to push |\n"
"| (c) : clear the stack |\n"
"| (=) : display top value on the stack |\n"
"| (+) : addition |\n"
"| (-) : subtraction |\n"
"| (*) : multiplication |\n"
"| (/) : division - integer division only |\n"
"| (%) : modulus - remainder from an integer division |\n"
"| (^) : exponentiation (x raised to the power of y) |\n"
"+------------------------------------------------------------------------------+\n");
printf("Input: ");
gets(input);
if(strcmp(input, "q") == 0)
{
printf("Exiting...\n");
return 0;
}
return 1;
}
int isNum(char *input)
{
int i;
for(i = 0; i < strlen(input); i++)
{
if(!isdigit(input[i]))
return 0;
}
return 1;
}
int hasTwo(tos)
{
if((SIZE - tos) >= 2)
return 1;
printf("\nStack size is 1, must have 2 or more\n");
return 0;
}
void mathOp (char op, int stack[], int *tos)
{
if(!isEmpty(*tos))
return;
if(!hasTwo(*tos))
return;
int right = pop(stack, tos);
int left = pop(stack, tos);
switch(op)
{
case '+':
push((left + right), stack, tos);
break;
case '-':
push((left - right), stack, tos);
break;
case '*':
push((left * right), stack, tos);
break;
case '/':
push((left/right), stack, tos);
break;
case '%':
push((left % right), stack, tos);
break;
case '^':
push(pow(left, right), stack, tos);
break;
}
}
int main(int argc, char **argv)
{
int verbose = 0;
int debugMode = 0;
if (argc == 2 && argv[1][0] == '-' && argv[1][1] == 'd')
{
debugMode = 1;
if (strcmp("-dv", argv[1]) == 0)
{
verbose = 1;
}
}
int stack[SIZE];
int tos = -1;
char input[MAXINPUT];
while (getInput(input))
{
int result = 0;
if (strcmp(input, "c") == 0)
clear(&tos);
else if (strcmp(input, "=") == 0)
{
result = top(stack, tos);
printf("Top of Stack is [%d]\n", result);
}
else if (isNum(input))
push(atoi(input), stack, &tos);
else if(strcmp(input, "+") == 0 ||
strcmp(input, "-") == 0 ||
strcmp(input, "*") == 0 ||
strcmp(input, "/") == 0 ||
strcmp(input, "%") == 0 ||
strcmp(input, "^") == 0 ) mathOp(input[0], stack, &tos);
else
printf("Invalid input\n");
if (debugMode)
printStack(stack, tos);
}
return 0;
}

You have a lot of problems in this code. Compile with -Wall (or equivalent setting) to find that isEmpty and isFull and top and pop don't (always) properly return a value.
Every function that needs to return something, must end in a return statement. There is no 'default return value' of some sorts in C.
So as an example:
int isFull (int tos)
{
if(tos >= SIZE - 1)
return 1;
return 0; // <-- not full, you probably want to return 0
}
ps. You need to use %% for a literal % in the help text.
edit to fix everything:
printStack is badly broken, you need to loop from 0 to tos, not from tos to SIZE.
hasTwo needs to test if tos>=1.
mathOp needs to test first if(isEmpty(*tos)), remove the ! which says not "if not empty".
Then it should work.

Related

Program in c regarding balance of parenthesis using stack not working

I wrote this program in c to check whether the parenthesis is balanced or not using the concept of stack.
#include<stdio.h>
#include<string.h>
#define MAX 100
int top = -1;
int arr[MAX];
void push(int x)
{
if (top == (MAX - 1))
{
printf("error:stack overflow n");
return;
}
top++;
arr[top] = x;
}
void pop()
{
top--;
}
int empty()
{
if (top == -1)
{
printf("The stack is empty \n ");
return 1;
}
else{
return 0;
}
}
int main()
{
char str[30];int len;int i;int temp;
printf("Enter he expression \n ");
scanf("%d",str);
len=strlen(str);
for(i=0;i<len;i++)
{
if (str[i] == '(' || str[i] == '{' || str[i] == '[')
{
push(str[i]);
}
if (str[i] == ')' || str[i] == '}' || str[i] == ']')
{
temp=empty();
if((empty())==1)
{
printf("Unbalanced\n ");
return;
}
else if(str[i]==arr[top])
{
pop();
}
}
}
if((empty())==1)
{
printf("Balanced\n");
}
else {
printf("unbalanced\n");
}
return 0;
}
however whatever the input i give the result i am getting is
Enter he expression
{{{]])
empty happend
Balanced
i have isolated the problem where my push and pop function are not being called,and the stack is empty regardless of the input.
any idea how to fix the code?
If one wanted (, [, { to be indistinguishable, one doesn't need O(length) space. An O(1) counter of how many parentheses/braces/brackets are currently at the position of the string would do. You can do more storing the arr queue; that is, find mismatches in the types of braces. I wrote my own quick parentheses checker, and discovered:
I would say there are 4 exception conditions to a passing valid input. In addition to a passing test, I would make sure to engineer a test for all four failing tests,
stack overflow: there are too many nesting levels for the fixed-size stack;
underflow: there are too many closing braces;
mismatch: one type of brace opened, but another closed; this is entirely missing from the original code;
unclosed: there are braces left in your stack but the input has ended.
One may want to automate this process, but the input has to be abstracted. Using #include <assert.h>.
assert(check("([{}({}[])]())") != 0);
assert(check("(") == 0);
assert(check("]") == 0);
...
printf("Enter he expression \n ");
if(!fgets(str, sizeof str, stdin)) return perror("input"), EXIT_FAILURE;
printf("%s\n", check(str) ? "Balanced" : "unbalanced");
I used the queue as what one expects; this is different for every character. Instead of a series of ifs, I used a switch statement. I changed the prototype for pop() to return the former top element and push() to return a boolean that it was successful (that is, not a stack overflow.) With this, for every byte, I wrote,
expect = 0;
switch(str[i]) {
case '\0':
if(!empty()) raise unclosed;
return;
case '(': expect = ')'; break;
case '[': expect = ']'; break;
case '{': expect = '}'; break;
case ')': case ']': case '}':
if(empty()) raise underflow;
if(pop() != str[i]) raise mismatch;
default: ; /* sic, everything else ignored */
}
if(expect && !push(expect)) raise overflow;
Where raise is dependent on the specificity one requires. Immediately report? With #include <stdbool.h>, raise -> return false; return -> return true. If one wanted be more specific, maybe return an exception value, enum { okay, unclosed, underflow, mismatch, overflow }. Or use goto to have more information about the context.
There are two problems.
First one is the scan should be %s not %d.
second one you pop if(str[i] == arr[Top]) which is always false, so the stack will remain full.
The code below should work fine.
#include <stdio.h>
#include <string.h>
#define MAX 100
int top = -1;
int arr[MAX];
void push(int x)
{
if (top == (MAX - 1))
{
printf("error:stack overflow n");
return;
}
top++;
arr[top] = x;
}
void pop()
{
top--;
}
int empty()
{
if (top == -1)
{
printf("The stack is empty \n ");
return 1;
}
return 0;
}
int main()
{
char str[30];
int len;
int i;
int temp;
printf("Enter he expression \n ");
scanf("%s", str);
len = strlen(str);
for (i = 0; i < len; i++)
{
if (str[i] == '(' || str[i] == '{' || str[i] == '[')
{
push(str[i]);
continue;
}
if (str[i] == ')' || str[i] == '}' || str[i] == ']')
{
if (empty())
{
printf("Unbalanceddd\n ");
return;
}
pop();
}
}
if (empty())
{
printf("Balanced\n");
}
else
{
printf("unbalanced\n");
}
return 0;
}
Edit:
The code above is just fixing the error of stack.
The one below will check for each pair of the three.
#include <stdio.h>
#include <string.h>
#define STACK_MAX 100
int stack[STACK_MAX];
int top = -1;
void push(int x);
int pop();
int peek();
int isEmpty();
int main()
{
char str[STACK_MAX * 2];
printf("Enter he expression \n ");
scanf("%s", str);
int len = strlen(str);
for (int i = 0; i < len; i++)
{
if (str[i] == '(' || str[i] == '{' || str[i] == '[')
{
push(str[i]);
continue;
}
if (str[i] == ')' || str[i] == '}' || str[i] == ']')
{
if (isEmpty())
{
printf("unbalanced\n");
return 0;
}
const char left = peek();
const char peek[3];
sprintf(peek, "%c%c", left, str[i]);
if (!(strcmp(peek, "()") == 0 || strcmp(peek, "[]") == 0 || strcmp(peek, "{}") == 0))
break;
pop();
}
}
if (isEmpty())
{
printf("Balanced\n");
}
else
{
printf("unbalanced\n");
}
return 0;
}
// --------------------------------------
// Stack Implementation
// --------------------------------------
void push(int x)
{
if (top + 1 == STACK_MAX)
{
printf("error:stack overflow \n");
return;
}
stack[++top] = x;
}
int pop()
{
if (top == -1)
{
printf("error: stack is empty \n");
return -1;
}
return stack[top--];
}
int peek()
{
if (top == -1)
{
printf("error: stack is empty\n");
return -1;
}
return stack[top];
}
int isEmpty()
{
return top == -1;
}
A fun project!
An alternative to function calls to push/pop values off a stack is to use 32 (or 64) bits of a variable to track the 3 different pairs of parentheses/brackets...
2 bits can represent 4 values. 0b00 is not useful as it cannot be distinguished from null (data), but 0b01, 0b10 & 0b11 can be harnessed to represent the each of the three pairs of interest.
In the code below, an unsigned int is the stack. Pushing two bits onto the stack involves a left shift and and OR. Popping is first testing the stack's two LSB's against what the character stream holds as a closing bracket, then right shifting the stack.
This is limited to 16 concurrent levels of nesting on my 32 bit compiler, but could go to 32 levels on a 64 bit compiler. Practically speaking, this should serve the majority of instances.
The code does detect/prevent stack over-/under-flow and bails out when detected.
#include <stdio.h>
#include <limits.h> // to determine 32 bit v. 64 bit
#if UINT_MAX = 0xffffffff // not sure this is right...???
typedef uint32_t stk_t;
#define FULL 0xC0000000 // b31 & b30 set
#else
typedef uint64_t stk_t;
#define FULL 0xC000000000000000 // b63 & b62 set
#endif
int balChk( char *str ) {
stk_t stk = 0;
char *sel = "(){}[]";
int ret = 0;
for( char *cp = str; !ret && *cp; cp++ ) {
for( char *bp = sel; *bp && *bp != *cp; bp++ ) {} // loop
if( !*bp ) continue; // not interesting character
if( (bp-sel)%2 == 0 ) { // 0,2,4 means push
if( stk & FULL ) {
printf( "Stack full - " );
ret = -1;
}
// pushes encoded matching close ')', '}' or ']'
stk = stk<<2 | ((bp-sel)+2)>>1; // use [2,4,6]/2 = 1,2,3
}
else // 1,3,5 means pop
{
// have stk item AND two LSBs match ([1,3,5]+1)/2 = 1,2,3
// compare encoded close with "top of stack" (ie: 2 LSBs )
if( !stk || (stk&3) != (bp-sel+1)>>1 ) {
printf( !stk ? "Stack empty - " : "Unmatched '%c' - ", *cp );
ret = -1;
}
stk >>= 2;
}
}
return ret + stk; // 0 means good
}
int main() { // test a few variations
char *strs[] = {
"()", "{}", "[]", "((()))", "(([()]))",
"(((([ (((([ (((([", // 15
"(((([ (((([ (((([ [", // 16
"(((([ (((([ (((([ [{", // 17 too many for my 32bit compiler
"(((([ (((([ (((([ []{", // 16-1+1
"{ ({()}) ((())) [] }",
"{ ({()}) ((())) [] missing!",
"{ ({()}) ((())) [] }",
"{ ({()}) ((())) [] too many }}",
};
for( int i = 0; i < sizeof strs/sizeof strs[0]; i++ )
printf( "'%s' - %s\n", strs[i], balChk( strs[i] ) ? "Bad" : "Good" );
return 0;
}
Output
'()' - Good
'{}' - Good
'[]' - Good
'((()))' - Good
'(([()]))' - Good
'(((([ (((([ (((([' - Bad // but 15 passed
'(((([ (((([ (((([ [' - Bad // but 16 passed
Stack full - '(((([ (((([ (((([ [{' - Bad // 17 popped the stack
'(((([ (((([ (((([ []{' - Bad // 16 - 1 + 1 passed
'{ ({()}) ((())) [] }' - Good
'{ ({()}) ((())) [] missing!' - Bad
'{ ({()}) ((())) [] }' - Good
Stack empty - '{ ({()}) ((())) [] too many }}' - Bad // Excessive popping
All-in-all, a fun project...

infix to postfix converstion in C with multiple digits input

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.

"error: function definition is not allowed here" w/ curly brackets in C?

hello i'm trying to create an online form of one of those little paper fortune tellers. this is the WIP code and I've mostly debugged it but I keep getting these two errors
fortune.c:58:3: error: function definition is not allowed here
fortune.c:79:4: error: function definition is not allowed here
ive looked up the question a lot and it keeps telling me that you have to define your functions outside of main because they're global or whatever but i already invoked them outside of the main function and before it begins, with the first couple lines. i've also tried just putting the whole code towards the top but it looks ugly to me like that and it causes like 20 bugs. i was just relieved to get all the errors down to single digits lol.
so here's the code any help would be appreciated. this is my first time coding. brick'd
#include <stdio.h>
#include <string.h>
void fortune1(void);
void fortune2(void);
int main (void)
{
int fort;
int tune;
// get color
char color; // []?
printf("Color?\n");
scanf("%s", &color);
int count;
count = strlen(&color);
{
if(count % 2 == 0)
int num1;
printf("Number?\n");
scanf("%d", &num1);
if(num1 % 2 == 0)
{
fortune1();
}
else
{
fortune2();
}
}
{
int num2; // []?
printf("Number?\n");
scanf("%d", &num2);
if(num2 % 2 == 0)
{
fortune1();
}
else
{
fortune2();
}
}
}
// fortune1 function
void fortune1(void)
{
do
{
int fort;
printf("Fortune?\n");
scanf("%d", &fort);
} while (fort < 5 || fort > 0); //must be in range 1-4
if(fort = 1);
printf("fortune1");
if(fort = 2);
printf("fortune2");
if(fort = 3);
printf("fortune3");
if(fort = 4);
printf("fortune4");
}
// fortune2 function
void fortune2(void)
{
do
{
int tune;
printf("Fortune?\n");
scanf("%d", &tune);
} while (tune < 9 || tune > 4)
if(tune = 5);
printf("fortune5");
if(tune = 6);
printf("fortune6");
if(tune = 7);
printf("fortune7");
if(tune = 8);
printf("fortune8");
}
}
'''
#include <stdio.h>
#include <string.h>
void fortune1(void);
void fortune2(void);
int main (void)
{
int fort;
int tune;
// get color
char color[10]; // []? if you're using string, then use array
printf("Color?\n");
scanf("%s", &color);
int count;
count = strlen(color); //if u use &, you'll count the variable address
if(count % 2 == 0)
{
int num1;
printf("Number1?\n");
scanf("%d", &num1);
if(num1 % 2 == 0)
{
fortune1();
}
else
{
fortune2();
}
}
else
{
//i dunno if this part is inside if or else
int num2; // []?
printf("Number2?\n");
scanf("%d", &num2);
if(num2 % 2 == 0)
{
fortune1();
}
else
{
fortune2();
}
}
}
// fortune1 function
void fortune1(void)
{
int fort;
do
{
printf("Fortune1?\n");
scanf("%d", &fort);
} while (fort >= 5 || fort <= 0); //must be in range 1-4
// i change the condition iniside while, because if not, the code will always looping
if(fort == 1) // == not =
printf("fortune1");
if(fort == 2)
printf("fortune2");
if(fort == 3)
printf("fortune3");
if(fort == 4)
printf("fortune4");
//don't use ; after if
}
// fortune2 function
void fortune2(void)
{
int tune;
do
{
printf("Fortune2?\n");
scanf("%d", &tune);
} while (tune >= 9 || tune <= 4); //; after while in do while
if(tune == 5)
printf("fortune5");
if(tune == 6)
printf("fortune6");
if(tune == 7)
printf("fortune7");
if(tune == 8)
printf("fortune8");
}
please tell me if i'm wrong

float addition 2.5 + 2.5 = 4.0? RPN [closed]

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.

Postfix evaluation using stacks and C

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",&current)!= '=')
{
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", &current);
//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", &current);
}
//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",&current)!= '=') { 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",&current)!= '=')
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",&current)!= '=')
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",&current) == 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.

Resources