Program in c regarding balance of parenthesis using stack not working - c

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...

Related

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.

Operators not inserting in the stack in C while trying to convert an infix expression to a postfix one

I am trying to implement an infix-to-postfix conversion program. On executing the code I get to see only alpha-numeric characters. Arithmetic operators are not printing. Upon debugging, I found the operators are not inserting in the stack. I couldn't find out the reason behind this.
Any help is appreciated.
#include<stdio.h>
#include <ctype.h>
#define MAX 50
char st[MAX];
int top = -1;
void push(char);
char pop();
int priority(char);
int main()
{
int i=0;
char x,s[50];
printf("Enter infix expression: ");
gets(s);
while(s[i]!='\0')
{
if(isalnum(s[i]))
printf("%c",s[i]);
else if(s[i] == '(')
push(s[i]);
else if(s[i] == ')')
{
while((x=pop())!='(')
printf("%c",x);
}
else
{
while(priority(st[top])>=priority(s[i]))
printf("%c",pop());
push(st[i]);
}
i++;
}
while(top!=-1)
printf("%c",pop());
}
void push(char x)
{
st[++top] = x;
}
char pop()
{
if(top == -1)
return -1;
else
return (st[top--]);
}
int priority(char x)
{
if(x == '(')
return 0;
if(x == '+' || x == '-')
return 1;
if(x == '*' || x == '/' || x == '%')
return 2;
}
As you correctly detected on your debugging session, you don't see operators in your postfix expression because you never push() them to your stack.
In fact
in the first if you check for alphanumeric characters
in the following else if you check for opening parenthesis
in the second else if you check for closing parenthesis
in the final else you manage pops from stack... but you didn't push anything! (1)
What you need to fix is the last else, where you have at least two distinct problems:
You access st[top] without checking top value. You need to manage the case in which top = -1, that would lead to out of bounds access of the stack array and to undefined behavior. I think that in that scenario you just need to push the operator
You push in the stack st[i]. Probably you meant s[i]
In this way the while analysing the expression becomes
while(s[i]!='\0')
{
if(isalnum(s[i]))
printf("%c ",s[i]);
else if(s[i] == '(' )
push(s[i]);
else if(s[i] == ')')
{
while((x=pop())!='(')
printf("%c ",x);
}
else
{
if( top != -1 )
{
while(priority(st[top])>=priority(s[i]))
printf("%c ",pop());
}
push(s[i]);
}
i++;
}
Input:
4*6+3
Output:
4 6 * 3 +
(I added a further space after each %c in printfs in order to improve output readability).
Note: You still have to fix some problems in operators priority management.

fixing an error i cannot spot in main() in C (stuck for hours on it - short program)

i'm having real hard time with my code, and my due date is today. i'm given an error "main.c: In function ‘main’:
main.c:186:7: error: expected declaration or statement at end of input
}".
I've been trying for hours to play with the brackets and fix it but with no luck. i'm hoping you could help me fix it, as you are far more experienced than me.
it's basically a simple program that takes input from stdin(might be from keyboard or from a file using redirection) and applies the following:
1)puts a new line between sentences.
2)doesn't print numbers.
3)if inside a bracket, then letters must be capitalized(bold).
4)put's an uppercase on a first character of a sentence.
5)if not in a bracket nor in a beginning of a sentence, then it should make it a lowercase.
notes:
a)there's no limit on the length of the input, and each sentence can be written on several lines(the input).
b)if a dot (.) is inside a brackets, it doesn't make it a new sentence(no need to write a newline).
c)if two dots are given, then it's an empty sentence and should be written like the example.
basically, i just ask you to help me fix my code so it will run, as i've already done all of that(thought of i missed something and you can help me improve it - i will be very glad!)
example:
if given input:
i love to play hockey.. I NEED TO PLAY HOCKEY.. "hockey is life 3333".
the desired output will be:
I love to play hockey.
. I need to play hockey.
.
"HOCKEY IS LIFE"
the code in "temp.h" is:
#define go 0
#define endOfASentence 1
#define isAFirstQuotation 2
#define isASecondQuotation 3
#define inAQuotation 4
#define beginningOfSentence 5
#define middleOfSentence 6
the code in main program is:
#include <stdio.h>
#include <ctype.h>
#include "letters.h"
int checkIfLetter (char a); /*checking if char is a letter */
int checkIfnumber (char a); /*checking if char is a number */
int checkIfUpperCase (char a); /*checking if char is upper case */
int checkIfLowerCase (char a); /*checking if char is lower case */
int checkIfQuotation (char a); /*check if char is a quotation */
int checkIfDot (char a); /*check if char is a dot */
int
main (int argc, const char *argv[])
{
int status = go;
char a;
int beginning = 0; /*if beginning equals 0 it's the beginning of a sentence, if it's 1 then it's the middle of it */
int secondQuote = 0; /*if second quote equals 1, then it's inside of a quotation */
while ((a = getchar ()) != EOF)
{
switch (status)
{
case go:
if (a == '.')
{
status = endOfASentence;
}
else if (a == '"' && secondQuote == '0')
{
status = isAFirstQuotation;
}
else if (a == '"' && secondQuote == '1')
{
status = isASecondQuotation;
}
else if (checkIfLetter (a) == '1' && secondQuote == '1')
{
status = inAQuotation;
}
else if (checkIfnumber (a) == '1')
{
continue;
} /*a number should not be on the output, so we just ignore it and not using it */
else if (checkIfLetter (a) == '1' && beginning == '0')
{
status = beginningOfSentence;
} /*i tried to differentiate between beginning and middle of the sentence using int beginning */
else if (checkIfLetter (a) == '1' && beginning == '1')
{
status = middleOfSentence;
}
case beginningOfSentence:
if (checkIfQuotation (a) && checkIfDot (a)
&& checkIfnumber (a) != 1)
{
if (checkIfUpperCase (a) == '1')
{
printf ("%c", toupper (a));
beginning = 1;
status = go;
}
} break; /*set to upper and return to go */
case middleOfSentence:
if (checkIfQuotation (a) && checkIfDot (a)
&& checkIfnumber (a) != 1)
{
if (checkIfLowerCase (a) == '1')
{
printf ("%c", tolower (a));
status = go;
}
} break;
case endOfASentence:
if (checkIfDot (a) == '1')
{
printf ("%c/n", a);
beginning = 0;
status = go;
}break; /*i tried to append(add) a new line after the dot and to set beginning to 0, to signify that after it's a beginning of a sentence */
case isAFirstQuotation: /*if it's a quotation, continue to the next char and make it upper case as long as it's a lower case, until you get another quotation */
while (checkIfLowerCase (a) == '1')
{
secondQuote == '1';
status = go;
}break;
case isASecondQuotation:
if (checkIfQuotation (a) == '1' && secondQuote == '1')
{
secondQuote = 0;
status = go;
}break;
case inAQuotation:
if (secondQuote == '1' && checkIfLetter (a) == '1')
{
printf ("%c", toupper (a));
status = go;
} break;
}
}
return 0;
}
int checkIfLetter (char a)
{
if (isalpha (a))
{
return 1;
}
else
{
return 0;
}
}
int checkIfnumber (char a)
{
if (isdigit (a))
{
return 1;
}
else
{
return 0;
}
}
int checkIfUpperCase (char a)
{
if (checkIfLetter (a) == '1')
{
if (isupper (a))
{
return 1;
}
else
{
return 0;
}
}
}
int checkIfLowerCase (char a)
{
if (checkIfLetter (a) == '1')
{
if (islower (a))
{
return 1;
}
else
{
return 0;
}
}
}
int checkIfQuotation (char a)
{
if (a == '"')
{
return 1;
}
else
{
return 0;
}
}
int checkIfDot (char a)
{
if (a == '.')
{
return 1;
}
else
{
return 0;
}
}
i don't know how to fix it and i've spent hours on it. would be very grateful if you could help.
i've tried to be very elaborative and to abide the rules
You can try this to see if it produces the desired results.
Characters that are not letters, space, newline or dot are rejected at the top of the while and all letters are set to lower case.
Then the choice is to print one upper case letter at the start of the sentence or all upper case inside double quotes.
There are no breaks as oneUpper needs to fall through to allUpper. allUpper needs to fall through to default.
getchar returns an int so int a instead of char a
#include <stdio.h>
#include <ctype.h>
#define oneUpper 1
#define allUpper 2
int main (int argc, const char *argv[])
{
int status = oneUpper;
int a;
while ( EOF != (a = getchar ()))
{
//discard non letter except space, newline and .
if ( !isalpha ( a) && a != ' ' && a != '\"' && a != '.') {
continue;
}
//set all to lower and let oneUpper or allUpper do the rest.
a = tolower ( a);
switch (status)
{
case oneUpper:
if ( a == ' ' || a == '\n') {
putchar ( a);//print leading space and continue
continue;
}
case allUpper:
a = toupper ( a);
default:
putchar ( a);
if ( a == '\"') {
if ( status == allUpper) {
status = 0;//turn all upper off
}
else {
status = allUpper;//turn all upper on
}
}
if ( status == oneUpper) {
status = 0;//after printing one upper turn it off
}
if ( a == '.') {
if ( status != allUpper) {
putchar ( '\n');
status = oneUpper;//after a . turn one upper on
}
}
}
}
return 0;
}

Extracting chars from inside '(' and ')' from char array in C

I am stuck on this problem:
A user writes a math expression and the program need to extract from it all subexpressions that are inside ( ) ex. (x+2) or (x+(y-2)).
For example, if the user enters 2-(5+(x-6)-(y+9)), the program should return (x-6), (y+9), (5+(x-6)-(y+9))
This is what I've tried to do.
#include<stdio.h>
int main()
{
char a[100];
int i=0,t,j=0;
printf("enter math expression:\n");
while( (a[i++]=getchar()) != '\n' && i < 100);
a[i] = '\0';
for (i=0; a[i]!='\0'; i++)
{
if (a[i]=='(')
{ printf("found (\n");
j++;
while (a[i] !=')')
printf("%c",a[i++]);
printf("%c",a[i]);
Since you are dealing with nested expressions, you need to keep a stack around in order to match parentheses. Ideally inside the loop you should:
Whenever found a '(', push position within the string into the stack
When a ')' is found, then pop from the stack the position of the matching '('. You have start-end indexes for your expression.
Continue until string is finished
Example (x + (y+2)):
i == 0 -> '(' -> s.push(0);
i == 1 -> 'x'
i == 2 -> '+'
i == 3 -> '(' -> s.push(3);
i == 4 -> 'y'
i == 5 -> '+'
i == 6 -> '2'
i == 7 -> ')' -> s.pop() [3, 7] contains '(y + 2)'
i == 8 -> ')' -> s.pop() [0, 8] contains '(x + (y+2))'
Let, s be a cstring in this context.
Since in valid mathematical expression parenthesis are balanced, we can observe that,
s+1 is balanced if s[0] is not '('
if s[0] is '(' then we are at the start of a parenthesis'ed expression.
At the case of #1 we do not care about the first character. So, we can set s = s+1 and start over again.
At the case of #2 we have to find the matched end for the first character. So, we divide it in two part. The matched expression and the tail. Both are valid expression. So, we start with them over again.
int main()
{
char s[] = "2-(5+(x-6)-(y+9))";// s have to be modifiable.
extractAndPrint(s, 0); // we are at start and 0 indicates balanced
return 0;
}
Now,
void extractAndPrint(char *s, int found)
{
if(s[0] == 0) return;//no more honey
if(!found){ //so far balanced
if(s[0] == '(') extractAndPrint(s+1, 1);// case 2
else extractAndPrint(s+1, 0); //this is the case 1
} else {//start of a expression
char *t;
//separates the end of current expression
//and the remaining part.
mark_end(s, 0, &t);
printf("(%s)\n", s);
extractAndPrint(s, 0);//potentially contain more expression
extractAndPrint(t, 0);//check past the previous exp
}
}
I liked recursion here too. It takes less thinking for me. Can be implemented in more elegant way.
void mark_end(char *s, int c, char **t)
{
if(c == 0){
if(s[0] == ')'){
*t = s+1;
*s = '\0';
} else if(s[0] == '('){
mark_end(s+1, c+1, t);
} else {
mark_end(s+1, c, t);
}
} else {
if(s[0] == ')'){
mark_end(s+1, c-1, t);
} else if(s[0] == '('){
mark_end(s+1, c+1, t);
} else {
mark_end(s+1, c, t);
}
}
}
OUTPUT:
(5+(x-6)-(y+9))
(x-6)
(y+9)
I recommend you to use state machine, in your case this state machine should be suitable :
so your main will be a kind of a switch case, take care of writing your pop and push fuctions and represent your heap with a good structure
You should use recursion to parse the string as a tree of parenthesis. Here is an example showing how to do it :
#include <stdio.h>
#include <string.h>
#define MAX_DATA 100
int mathexp(const char *exp, int start, int end)
{
int i = start;
while(i < (start + end) && exp[i] != ')') {
if(exp[i] == '(') {
i = mathexp(exp, i + 1, end) + 1;
} else {
i++;
}
}
char subexp[i - start];
memcpy(subexp, &exp[start], i - start);
subexp[i - start] = '\0';
printf("%s\n", subexp);
return i;
}
int main(int argc, char *argv[])
{
char input[MAX_DATA];
printf("Enter a math expression: ");
fgets(input, sizeof(input), stdin);
input[strcspn(input, "\r\n")] = '\0'; // remove trailing \r\n
mathexp(input, 0, strlen(input));
return 0;
}
and when you test it, you have :
Enter a math expression: 2-(5+(x-6)-(y+9))
x-6
y+9
5+(x-6)-(y+9)
2-(5+(x-6)-(y+9))

C program, Stack Calculator [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.
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.

Resources