I am trying to convert infix notation to postfix notation using stack. I have written the following code but it is giving me error:
/Users/apple/Desktop/infix.c|49|error: expected expression
and I am unable to find the error. Please help me to correct this code.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#define MAX 100
char st[MAX];
int top = -1;
void push(char st[],char);
char pop(char st[]);
void InfixtoPostfix(char source[],char target[]);
int getPriority(char);
int main(){
char infix[100],postfix[100];
printf("enter any infix expression");
fflush(stdin);
gets(infix);
strcpy(postfix,"");
InfixtoPostfix(infix,postfix);
printf("\nthe corresponding postfix expression is:");
puts(postfix);
return 0;
}
void InfixtoPostfix(char source[],char target[]){
int i=0,j=0;
char temp;
strcpy(target,"");
while(source[i]!='\0')
{
if(source[i]=='(')
{
push(st,source[i]);
i++;
}
else if(source[i]==')')
{
while((top!=-1)&&(st[top]!='('))
{
target[j]=pop(st);
j++;
}
if(top==-1)
{
printf("\nincorrect syntax");
exit(1);
}
temp=pop(st);
i++;
else if((isdigit(source[i]))||(isalpha(source[i]))
{
target[j]=source[i];
j++;
i++;
}
else if(source[i]=='+'||source[i]=='- '||source[i]=='*'||source[i]='/'||source[i]=='%d')
{
while((top!=-1)&&(st[top]!='(')&&(getPriority(st[top])>getPriority(source[i])))
{
target[j]=target[i];
i++;
}
push(st,source[i]);
i++;
}
else{
printf("\nincorrect expression");
exit(1);
}
}
while((top!=-1)&&(st[top]!='('))
{
target[j]=pop(st);
j++;
}
target[j]='\0';
}
}
int getPriority(char op)
{
if(op=='/'||op=='*'||op=='%'||op=='%')
return 1;
else if(op=='+'||op=='-')
return 0;
}
void push(char st[],char val)
{
if(top==MAX-1)
printf("overflow");
else{
top++;
st[top]=val;
}
}
char pop(char st[])
{
char val=' ';
if(top==-1)
printf("underflow");
else{
val=st[top];
top--;
}
return val;
}
Many problems, the most important one being
else if((isdigit(source[i]))||(isalpha(source[i]))
lacks a closing parentheses, your coding style makes it difficult to notice
else if ((isdigit(source[i]) != 0) || (isalpha(source[i]) != 0))
And don't use gets() it's deprecated, in your case
fgets(infix, sizeof(infix), stdin);
would work, and will have the benefit of preventing a buffer overflow.
While there are so many issues in the code,
this one here is the most horror:
if(top==-1)
{
printf("\n incorrect syntex");
exit(1);
}
temp=pop(st);
i++;
else if((isdigit(source[i]))||(isalpha(source[i]))
{
target[j]=source[i];
j++;
i++;
}
No, you are not doing that right. FWIK, C doesn't allow this:
if()
{
//some code
}
//some code
else{
//some code
}
The other issue being:
else if((isdigit(source[i]) )||(isalpha(source[i])). I would prefer it to be,
else if( (0 != isdigit(source[i])) || (0 != isalpha(source[i])) )
Or as suggested by Jonathan Leffler in a comment below: even better if you use if (isalnum(source[i])) since it checks for all alphanumeric.
Is it only me who finds the code not so readable?
Instead of if(op=='/'||op=='*'||op=='%'||op=='%') I would prefer
if((op == '/')||(op == '*')||(op == '%')) in terms of readability.
Related
What I'd like to program is having a user input a series of parentheses/braces and evaluate them whether they are nested properly or not.
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#define STACK_SIZE 100
char contents[STACK_SIZE];
int top = 0;
void make_empty(void)
{
top = 0;
}
bool is_empty(void)
{
return top == 0;
}
bool 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("Stack overflow\n");
exit(EXIT_FAILURE);
}
void stack_underflow(void)
{
printf("Stack underflow\n");
exit(EXIT_FAILURE);
}
int main(void)
{
char ch;
printf("Enter parentheses and/or braces: ");
while((ch = getchar()) != '\n')
{
if(ch == '(' || ch == '{')
push(ch);
else if(ch == ')')
{
if(pop != '(') /// compiler says it is a comparison between pointer and integer.
{
printf("not nested properly!");
exit(EXIT_FAILURE);
}
}
else if(ch == '}'){
if(pop != '{') /// compiler says it is a comparison between pointer and integer.
{
printf("not nested properly!");
exit(EXIT_FAILURE);
}
}
}
if(is_empty())
printf("Parentheses/braces are nested properly");
else
printf("not nested properly!!");
/* if the stack is empty, it is nested properly, otherwise not.*/
return 0;
}
the compiler says that the comparison between pop and '(' or '{' is comparison between pointer and integer, although I set the return type of the function 'pop' as int. Because of this when the program processed with right parenthesis or brace it always prints "not nested properly." How can I improve this?
This is just "mentioning" the function, not calling it.
The compiler sees a function pointer instead of the return value and its type.
pop != '{'
Use
pop() != '{'
in order to call the function and do the comparison of return value of type char and '{'.
/*
This is a code that changes infix notation to postfix notation.
I used FILE/IO to get infix notations and the infix.txt file looks like
3
2+4*2-1;
9+3^2^(3-1)*2;
2*((7-2)/3+4)^2%3;
My question is I get error saying "control may reach end of non-void function" on the last two functions, icp and isp. How can I fix this?
*/
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#define MAX_SIZE 100
#define ENTER 0x000d
void infixtopostfix(char expression[]);
char get_token(char expression[], int *index);
void push(int *top, char token);
int pop(int *top);
int icp(char op);
int isp(char op);
char stack[MAX_SIZE];
int main(void) {
int i, num;
FILE *file;
char expression[MAX_SIZE];
if((file=fopen("infix.txt","r")) == NULL) {
printf("No file.\n");
}
fgets(expression, MAX_SIZE, file);
num = atoi(expression);
for(i=0; i < num; i++) {
fgets(expression, MAX_SIZE, file);
printf("%s", expression);
infixtopostfix(expression);
}
fclose(file);
}
void infixtopostfix(char expression[]) {
char token;
char element;
int top=0;
int index=0;
for(token=get_token(expression, &index); token!=';'; token=get_token(expression, &index)) {
if(isdigit(token)) printf("%c", token);
else if(token == ')') {
while (stack[top] != '(') {
element = pop(&top);
printf("%c", element);
}
pop(&top);
}
else {
while (isp(stack[top])>=icp(token)) {
element = pop(&top);
printf("%c", element);
}
push(&top, token);
}
}
while((token=pop(&top))!=0) printf("%c", token);
printf("\n");
}
char get_token(char expression[], int *index) {
char token=expression[(*index)++];
return token;
}
void push(int *top, char data) {
if(*top < (MAX_SIZE-1)) stack[++(*top)] = data;
}
int pop(int *top) {
if(*top > -1) return stack[(*top)--];
else return 0;
}
int icp(char op) {
switch (op){
case '(' : return 20; break;
case '+' : return 12; break;
case '-' : return 12; break;
case '*' : return 13; break;
case '%' : return 13; break;
case ';' : return 0;
}
}
int isp(char op) {
switch (op){
case '(' : return 0; break;
case '+' : return 12; break;
case '-' : return 12; break;
case '*' : return 13; break;
case '%' : return 13; break;
case ';' : return 0;
}
}
While you may believe that your methods will only ever get one of these 6 characters, the compiler has to assume that any character can be passed in. At the moment, these methods will not return anything if you pass in, for example, 'x'.
You need to specify a default action for all characters not otherwise covered by your switch. Whether this is returning a default value or throwing an exception, that is up to you. But it's nonetheless a possibility your code needs to handle.
like this:
}//end switch
fprintf(stderr, "\nunrecognized OP(%c) is specified.\n", op);// '/', '^'...
return -1;//or exit(-1);
I was making a C program to convert infix expression to postfix expression in which unwanted symbols are showing instead of operators
The output is like abc##$^ for input (a+b+c).
I am hereby attaching the code
//to convert infix expression to postfix expression
#include <stdio.h>
#include <conio.h>
#include <string.h>
void push(char);
char pop();
int is_operator(char);
int precedence(char);
char stack[100];
int top=-1;
void main()
{
int i=0,j=0,count;
char infix[100],item,x;
char postfix[100];
clrscr();
printf("Enter Infix String");
gets(infix);
count= strlen(infix);
for(i=0;i!=count;i++){
item=infix[i];
if(item=='('){
push(item);
}
else if((item>='A'&& item<='Z')||(item>='a' && item<='z')){
postfix[j]=item;
j++;
}else if(is_operator(item)==1){
x=pop();
if(precedence(x)>precedence(item)){
postfix[j]=x;
j++;
}
else{
push(item);
}
}else if(item==')'){
char a;
a=pop();
while(a!='('){
postfix[j]=a;
a=pop();
}
}else{
printf("Invalid Expression");
}
}
postfix[j]='\0';
printf("Postfix Expression\n");
puts(postfix);
getch();
}
void push(char a)
{
char y;
y=a;
top++;
stack[top]=y;
}
char pop()
{
char ch;
ch=stack[top];
top--;
return(ch);
}
int is_operator(char i)
{
if(i=='+'||i=='-'||i=='/'||i=='*'||i=='%'){
return(1);
}else{
return(0);
}
}
int precedence(char c)
{
if(c=='/'||c=='*'||c=='%'){
return(2);
}else if(c=='+'||c=='-'){
return(1);
}else{
return(0);
}
}
#include <stdio.h>
#include <stdlib.h>
static int top = 0;
static char stack[100];
void push(char thing2push)
{
if (top == 100){
fprintf(stderr, "Too many things in the stack");
exit(1);
}else{
stack[top] = thing2push;
top++;
}
}
then in the main I have:
extern void push(int);
push(1);
but that results in "segmentation fault". My guess that it has something to do with memory violations, but I have no idea on how to fix it.
EDIT Here's the full code:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
extern int pop();
extern void push(int);
void readTag(){
int tagVal = getchar();
int poppedVal;
if (getchar() == '/'){
poppedVal = pop();
if (poppedVal != tagVal){
printf("NOT Valid");
exit(1);
}
}else{
push(1);
}
}
int main(int argc, char * argv[])
{
int ch;
while ((ch = getchar()) != EOF) {
if (!(isalpha(ch) || ch == '<'))
continue;
readTag();
}
printf("Valid");
exit(0);
}
and here's the stack:
#include <stdio.h>
#include <stdlib.h>
static int top = 0;
static char stack[100];
int isEmpty()
{
return !(top);
}
char pop()
{
if (isEmpty()){
fprintf(stderr, "Stack is empty");
exit(1);
}
top--;
return stack[top+1];
}
void push(char thing2push)
{
if (top == 100){
fprintf(stderr, "Too many things in the stack");
exit(1);
}else{
stack[top] = thing2push;
top++;
}
}
The top variable always indicates the next entry in the stack (which obviously does not contain a valid element, as far as your program concerns). So you're not supposed to read the value at stack[top].
The segmentation fault occurs in function pop, when top reaches 100:
top--; // top == 99
return stack[top+1]; // return stack[100]
You should write into stack[top], but read from stack[top-1].
You can leave function push as is, and change only function pop:
top--;
return stack[top];
I've looked through similar questions on stackoverflow, but I'm still not sure how to fix it.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
extern char * pop();
extern void push(char *);
int i;
int j=0;
//Resize the array to 1.1 it's size
void reSize(char* tag){
char *temp = malloc(1.1*sizeof(tag));
for (i=0;i<(sizeof(tag)/sizeof(tag[0]));i++){
*(temp+i) = *(tag+i);
}
free(tag);
tag = temp;
}
int compare(char* tag, char* popVal){
i=0;
while (i<sizeof(tag)/sizeof(tag[0])){
if (*(tag+i) == *(popVal+i)){
i++;
}else{
return 0;
}
}
return 1;
}
void dothis(){
int ch;
int n=0;
char *tag = malloc(10* sizeof(char));
char *popVal;
while ((ch = getchar()) != '>'){
tag[n] = ch;
n++;
if (n > (sizeof(tag)/sizeof(tag[0]))-1 ){
reSize(tag);
}
}
if (*tag == '/'){
popVal = malloc(sizeof(tag));
popVal = pop();
j--;
if (!(compare(tag,popVal))){ // Compare will return 1 if the same
printf("Invalid");
exit(1);
}
}else{
push(tag);
j++;
}
free(tag);
free(popVal);
}
int main(int argc, char * argv[])
{
int ch;
while ((ch = getchar()) != EOF) {
if (!(isalpha(ch) || ch == '<'))
continue;
dothis();
}
if (j != 0){
printf("Invalid\n");
exit(1);
}
printf("Valid\n");
exit(0);
}
then the external methods:
#include <stdio.h>
#include <stdlib.h>
static int top = 0;
static char * stack[100];
int isEmpty()
{
return !(top);
}
char * pop()
{
if (isEmpty()){
fprintf(stderr, "Stack is empty");
exit(1);
}
top--;
return (char *) stack[top];
}
void push(char * thing2push)
{
if (top == 100){
fprintf(stderr, "Too many things in the stack");
exit(1);
}else{
stack[top] = thing2push;
top++;
}
}
In a previous question, the selected answer was "passing a pointer to memory you haven't allocated with malloc will definitely not do good things.", but I"m pretty sure I allocated everything
Here's a bug:
popVal = malloc(sizeof(tag));
popVal = pop();
You malloc an area and then immediately lose that value, replacing it with something from pop().
This is most definitely a bug:
while ((ch = getchar()) != '>'){
tag[n] = ch;
n++;
if (n > (sizeof(tag)/sizeof(tag[0]))-1 ){
You assign to tag[n] before checking the range of n. When you do check the range of n after the fact you use sizeof(tag). tag is a pointer. It's size is 4 (32 bit) or 8 (64 bit). Neither size has anything to do with how big n can be before tag[n] writes into invalid memory.
Another bug:
char * pop()
{
if (isEmpty()){
fprintf(stderr, "Stack is empty");
exit(1);
}
top--;
return (char *) stack[top];
}
If you're a beginning C programmer, never cast a pointer. Because I doubt that you have learned enough yet to know if this is a good or bad idea.
The type system exists for good reasons and if it complains about some types not matching, it is far more likely to be right than you are.