I am trying to create a program to convert an infix expression to post fix and evaluate it using a stack. The three files are below. When I run the code I get a segmentation fault. The debugger in Xcode says that it occurs between the push and the two pop calls in the middle file in the evaluate_postfix function. Can anyone help me with why this is seg faulting?
#include <stdio.h>
#include <stdlib.h>
#include "stack.h"
stack* create_stack(void)
{
stack* newPtr = malloc(sizeof(stack));
newPtr->size = 0;
newPtr->stack = NULL;
return newPtr;
}
void push(stack *s, int val)
{
node* newPtr = (node*) malloc(sizeof(node));
newPtr->data = val;
newPtr->next = s->stack;
s->stack = newPtr;
s->size++;
}
void pop(stack *s)
{
node* newPtr = NULL;
node* tempPtr = NULL;
tempPtr = s->stack;
newPtr = tempPtr->next;
free(tempPtr);
s->stack = newPtr;
s->size--;
}
int top(stack *s)
{
int num;
node* newPtr = NULL;
newPtr = s->stack;
num = newPtr->data;
return num;
}
int isEmpty(stack *s)
{
if(s->stack == NULL)
{
return 1;
}
else
{
return 0;
}
}
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "stack.h"
#include <string.h>
#define MAX_EQU_LEN 100
static int prec(char operator)
{
switch (operator)
{
case '*':
return 5;
case '/':
return 4;
case '%':
return 3;
case '+':
return 2;
case '-':
return 1;
default:
break;
}
return 0;
}
static int isNumeric(char* num)
{
if(atoi(num) == 0)
{
return 0;
}
return 1;
}
char* infix_to_postfix(char* infix)
{
int i,a=0;
char* postfix = malloc(MAX_EQU_LEN);
stack* s = create_stack();
for(i=0;infix[i]!='\0';i++){
if(!isNumeric(&((infix[i]))))
{
postfix[a]=infix[i];
a++;
}
else if(isEmpty(s))
push(s,infix[i]);
else if(prec(infix[i])>prec(s->stack->data))
push(s,infix[i]);
else
{
postfix[a]=s->stack->data;
a++;
pop(s);
if(!isEmpty(s)){
while(prec(s->stack->data)<= prec (infix[i]))
{
postfix[a]=s->stack->data;
a++;
pop(s);
}
}
else
push(s,infix[i]);
}
}
return postfix;
}
int evaluate_postfix(char* postfix) {
int i,result = 0;
int right = 0, left = 0;
char* token = NULL;
stack* s = create_stack();
s->size = strlen(postfix);
node* tempPtr = NULL;
for(i = 0; i < s->size ; i++)
{
token = strtok(postfix, " ");
if(isNumeric(token) == 1)
{
atoi(token);
push(s, *token);
}
else
{
left = tempPtr->data;
pop(s);
right = tempPtr->data;
pop(s);
switch(*token)
{
case '+':
result = left + right;
break;
case '-':
result = left - right;
break;
case '*':
result = left * right;
break;
case '/':
result = left / right;
break;
case '%':
result = left % right;
break;
}
push(s, result);
}
strtok(NULL, " ");
}
return result;
}
#include <stdio.h>
#include <string.h>
#include "calculator.h"
#define BUFFERSIZE 100
int main(int argc, char* argv[]) {
char buffer[BUFFERSIZE];
if (argc != 2) {
printf("correct ussage: %s <input file>\n", argv[0]);
return 1;
}
FILE* fp = fopen(argv[0], "r");
if(fp == NULL) {
printf("unable to open file: %s\n", argv[1]);
return 1;
}
while(fgets(buffer, BUFFERSIZE, fp)) {
if (buffer[strlen(buffer)-1] == '\n') {
buffer[strlen(buffer)-1] = '\0';
}
char *postfix = infix_to_postfix(buffer);
int result = evaluate_postfix(postfix);
printf("%s = %d\n", buffer, result);
}
return 0;
}
Each call to strtok() that doesn't contain a NULL pointer as its first argument resets the internal pointer of the strtok() function to the beginning of the string.
At the beginning of the loop in your int evaluate_postfix(char* postfix); function, you call
token = strtok(postfix, " ");
Which means that at the beginning of the loop, token ALWAYS pointers to the first non-space character at the beginning of postfix. So each loop it would see an operator, and try to pop() two values from the stack. But your stack would quickly deplete, and the stack will begin to point to garbage data (s->size < 0).
token = strtok(postfix, " ");
for(i = 0; i < s->size ; i++)
{
....
token = strtok(NULL, " ");
}
Should fix your issue.
Related
I'm new to programming, while I know there are better codes out there for this question I sort of don't understand why this isn't working, the value returned by pop2() here is a part of a string which is why for %d it doesn't print the correct value but for %c it does
int n = pop2();
printf("n is now %c\n", n);
thus even numbers are of string type for s = "3[a2[c]]" I want my loop to run the number of times that is returned by pop (2 and then 3 in this case), since the value returned by pop2() is of char type even after using atoi it doesn't work
I tried doing
int n = atoi(pop2());
//or even
char* n = pop2();
int num = atoi(n);
but it still wouldn't work, here's the entire code of the function, I've typed out printf statements to help me recognize where I was going wrong, I'd be so grateful if you don't mind helping me out. Thanks :)
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <ctype.h>
struct node
{
int data;
struct node *link;
} *top = NULL;
struct node2
{
int data;
struct node2 *link;
} *top2 = NULL;
int isEmpty()
{
if (top == NULL)
{
return 1;
}
return 0;
}
int isEmpty2()
{
if (top2 == NULL)
{
return 1;
}
return 0;
}
int pop()
{
if (isEmpty())
{
return 0;
}
int val;
val = top->data;
top = top->link;
return val;
}
int pop2()
{
if (isEmpty2())
{
return 0;
}
int val;
val = top2->data;
top2 = top2->link;
return val;
}
void push(int data)
{
struct node *new = (struct node *)malloc(sizeof(struct node));
if (new == NULL)
{
exit(1);
}
new->data = data;
new->link = NULL;
new->link = top;
top = new;
}
void push2(int data)
{
struct node2 *new = (struct node2 *)malloc(sizeof(struct node2));
if (new == NULL)
{
exit(1);
}
new->data = data;
new->link = NULL;
new->link = top2;
top2 = new;
}
int peek()
{
if (isEmpty())
{
return 0;
}
return top->data;
}
int peek2()
{
if (isEmpty2())
{
return 0;
}
return top2->data;
}
char *decodeString(char *s, char *arr)
{
for (int i = 0; i < strlen(s); i++)
{
if (s[i] == '[')
{
printf("pushing s[i] that is %c on stack 1\n", s[i]);
push(s[i]);
}
if (isalpha(s[i]))
{
printf("pushing %c on stack 2\n", s[i]);
push2(s[i]);
}
if (isdigit(s[i]))
{
printf("pushing %c on stack 2\n", s[i]);
push2(s[i]);
}
if (s[i] == ']')
{
if (peek() == '[')
{
printf("s[i] is %c and peek element is %c \n", s[i],
peek());
printf("%c is now popped out next element in stack one is %c\n", pop(), peek());
if (isalpha(peek2()))
{
printf("element in stack 2 now is %c\n", peek2());
char ch = pop2();
printf("ch now is %c\n", ch);
strcat(arr, &ch);
printf("arr after strncating is:");
printf("%s ", arr);
printf("\n");
}
if (isdigit(peek2()))
{
printf("element in stack 2 now is %c\n", peek2());
int n = pop2();
printf("n is now %c\n", n);
printf("current arr is %s\n", arr);
while (n < 0)
{
strcat(arr, &arr);
printf("i. %d strncated %s\n", i, arr);
n--;
}
}
}
}
}
for (int i = 0; i < 10; i++)
{
printf("%c ", arr[i]);
}
printf("\n");
return arr;
}
int main()
{
char s[100] = "3[a2[c]]";
char arr[10] = {0};
decodeString(s, arr);
return 0;
}
here's the output I'm getting, sorry for making this so long
I am having trouble understanding what I should do in the AddNumber function of my program. When the AddNumber function is called in main a pointer variable previous is created, and it takes the user's input and points it at the address of the variable newNum. I created an if statement for it to do that, but I was informed it doesn't do anything.
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
typedef struct A_NewNumber{
struct A_NewNumber *next;
double newNum;
} NewNumber;
NewNumber *AddNumber(NewNumber *previous, char *input){
//char input[16];
//double numEntered = 0;
NewNumber *newNum = malloc(sizeof(NewNumber));
sscanf(input, "%lf", &newNum->newNum);
//sscanf(input, "%s", newNum->enterNumber);
//numEntered = atof(input);
/*if (previous != NULL){
previous->newNum;
}*/
newNum->next = NULL;
newNum->newNum = 0;
return newNum;
}
void PrintList(NewNumber *start){
NewNumber *currentNumber = start;
int count = 0;
while(currentNumber != NULL){
count++;
printf("Numbers:%lf\n",
currentNumber->newNum);
currentNumber = currentNumber->next;
}
printf("Total Numbers Entered%d\n", count);
}
void CleanUp(NewNumber *start){
NewNumber *freeMe = start;
NewNumber *holdMe = NULL;
while(freeMe != NULL){
holdMe = freeMe->next;
free(freeMe);
freeMe = holdMe;
}
}
int main(){
//indexNum = 0;
char command[16];
char input[16];
//float userInput;
NewNumber *userEnter = NULL;
NewNumber *start = NULL;
NewNumber *newest = NULL;
while(fgets(input, sizeof input, stdin)){
printf("Please enter a number->");
printf("Enter 'quit' to stop or 'print' to print/calculate");
sscanf(input, "%s", command);
if(newest == NULL){
start = AddNumber(NULL, input);
newest = start;
}else{
newest = AddNumber(newest, input);
}if(strncmp(command, "print", 5) == 0){
PrintList(start);
}else if(strncmp(command, "quit", 4)== 0){
printf("\n\nQuitting....\n");
break;
//userInput = enterNumber;
}
}
CleanUp(start);
return 0;
}
}
It was not that bad, was just in need of a bit of clean-up.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// ALL CHECKS OMMITTED!
typedef struct A_NewNumber {
struct A_NewNumber *next;
double newNum;
} NewNumber;
NewNumber *AddNumber(NewNumber * previous, char *input)
{
int res;
// allocate new node
NewNumber *newNum = malloc(sizeof(NewNumber));
if (newNum == NULL) {
fprintf(stderr, "Malloc failed in AddNUmber()\n");
return previous;
}
// convert input string to float
res = sscanf(input, "%lf", &newNum->newNum);
if (res != 1) {
fprintf(stderr, "Something bad happend in AddNUmber()\n");
return previous;
}
// terminate that node
newNum->next = NULL;
// if this is NOT the first node
// put new node to the end of the list
if (previous != NULL) {
previous->next = newNum;
}
// return pointer to new node at end of the list
return newNum;
}
void PrintList(NewNumber * start)
{
NewNumber *currentNumber = start;
int count = 0;
while (currentNumber != NULL) {
count++;
printf("Numbers:%lf\n", currentNumber->newNum);
currentNumber = currentNumber->next;
}
printf("Total Numbers Entered %d\n", count);
}
void CleanUp(NewNumber * start)
{
NewNumber *freeMe = start;
NewNumber *holdMe = NULL;
while (freeMe != NULL) {
holdMe = freeMe->next;
free(freeMe);
freeMe = holdMe;
}
}
int main()
{
char input[16];
NewNumber *start = NULL;
NewNumber *newest = NULL;
int res;
// infinite loop
while (1) {
// give advise
printf("Please enter a number or\n");
printf("'quit' to stop or 'print' to print/calculate\n");
// get input from user
res = scanf("%s", input);
if (res != 1) {
if (res == EOF) {
fprintf(stderr, "Got EOF, bailing out\n");
break;
} else {
fprintf(stderr, "something bad happend, bailing out\n");
break;
}
}
// check if a command was given
if (strncmp(input, "print", 5) == 0) {
PrintList(start);
continue;
} else if (strncmp(input, "quit", 4) == 0) {
printf("\n\nQuitting....\n");
break;
}
// otherwise gather numbers
if (newest == NULL) {
start = AddNumber(NULL, input);
if (start == NULL) {
fprintf(stderr, "AddNumber returned NULL\n");
break;
}
newest = start;
} else {
newest = AddNumber(newest, input);
if (newest == NULL) {
fprintf(stderr, "AddNumber returned NULL\n");
break;
}
}
}
CleanUp(start);
return 0;
}
You should really make a habit of checking all returns and if you don't: be able to give a good reason why you didn't.
Don't forget to switch on all warnings your compiler offers. Even if you don't understand them now, Google might have an answer and if not some people here do (in that order, thank you).
i'm trying to create a postfix calculator using linked-list.
when i compile, it doesn't show any errors but when it's executed it would show Segmentation Fault. i don't know how to deal with this, please help.
here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
typedef struct node {
int num;
struct node *next;
} node;
void push(int num, node **head);
int pop(node **head);
void display(node **head);
int is_empty();
int evaluatePostfix();
struct node *head;
int main() {
head = NULL;
char exp[1000]; // = "5 1 2 + 4 * + 3 -";
printf("Input expression:\t");
fgets(exp, 1000, stdin);
for(int i = 1; i <= strlen(exp); i++) {
if(exp[i] == '\n') {
exp[i] = '\0';
}
else if (exp[0] == '\n') {
printf("stack is empty\n");
exit(0);
}
}
printf("%s = %d\n", exp, evaluatePostfix(exp));
return 0;
}
int evaluatePostfix(char* exp) {
char * token;
int counter = 0;
char temp[256][256];
token = strtok(exp, " ");
while(token != NULL) {
strcpy(temp[counter], token);
counter++;
token = strtok(NULL, " ");
}
for (int i = 0; temp[i]; ++i) {
if (isdigit(*(temp[i]))) {
int val = atoi(temp[i]);
push(val, &head);
}
else {
int val1 = pop(&head);
int val2 = pop(&head);
switch (exp[i]) {
case '+': push(val2 + val1, &head);
printf("%d\n", (*head).num);
break;
case '-': push(val2 - val1, &head); break;
case '*': push(val2 * val1, &head); break;
case '/': push(val1 / val2, &head); break;
}
}
}
return pop(&head);
}
void push (int item, node **head) {
node *temp;
node * get_node(int);
temp = get_node(item);
temp->next = *head;
*head = temp;
}
node *get_node(int item) {
node *temp;
temp = (node*)malloc(sizeof(node));
if (temp == NULL)
printf("\nMemory cannot be allocated");
temp->num = item;
temp->next = NULL;
return(temp);
}
int pop(node **head) {
int item;
node *temp;
item = (*head)->num;
temp = *head;
*head = (*head)->next;
free(temp);
return(item);
}
int is_empty(node *temp) {
if (temp == NULL)
return 1;
else
return 0;
}
void display(node **head) {
node *temp;
temp = *head;
if(head == NULL) {
printf("stack is empty\n");
return;
}
printf("\n");
printf("=========\n");
while(temp!=NULL) {
printf("%d\n", (*temp).num);
temp = (*temp).next;
}
printf("=========\n");
}
Given this declaration ...
char temp[256][256];
... the loop termination condition here is wrong:
for (int i = 0; temp[i]; ++i) {
C multi-dimensional arrays are not Java-style arrays of array references. They are arrays of actual arrays. The expression temp[i] will not be false when i exceeds the number of elements of temp[] into which you have written data.
It looks like you want simply
for (int i = 0; i < counter; ++i) {
. Alternatively, there's no particular need to tokenize before your start the computation. You could as easily combine the two loops in function evaluatePostfix() into one. That would be a bit simpler, and would remove any fixed limit on the number of terms in the expression.
Update: That might look like this:
for (token = strtok(exp, " "); token; token = strtok(NULL, " ")) {
/* ... use token instead of temp[i] ... */
}
It is conceivable that there are other errors in your code as well, though I didn't spot any on my scan through it.
"btw, all identifiers for functions in the Standard Library are reserved.
There is a function exp() in math.h, so exp falls into that category.
Technically, using a reserved identifier in your code results in undefined behaviour."
Thanks for the help guys! Changing exp to another variable name did the trick. here's the working code so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
typedef struct node {
int num;
struct node *next;
} node;
void push(int num, node **head);
int pop(node **head);
void display(node **head);
int is_empty(node *temp);
int evaluate(char *expression);
struct node *head;
int main() {
head = NULL;
char expression[1000]; // = "5 1 2 + 4 * + 3 -";
printf("Input expression:\t");
fgets(expression, 1000, stdin);
for(int i = 1; i <= strlen(expression); i++) {
if(expression[i] == '\n') {
expression[i] = '\0';
}
else if (expression[0] == '\n') {
printf("empty stack\n");
exit(0);
}
}
printf("Answer: %d\n", evaluate(expression) );
return 0;
}
int evaluate(char* expression) {
char * token;
int counter = 0;
char temp[256][256];
token = strtok(expression, " ");
while(token != NULL) {
strcpy(temp[counter], token);
token = strtok(NULL, " ");
counter++;
}
for (int i = 0; i < counter; i++) {
if (isdigit(*(temp[i]))) {
int val = atoi(temp[i]);
push(val, &head);
}
else {
int val1 = pop(&head); //pop the last two values from stack
int val2 = pop(&head);
switch (*(temp[i])) { //perform operation
case '+': push(val2 + val1, &head); break;
case '-': push(val2 - val1, &head); break;
case '*': push(val2 * val1, &head); break;
case '/': push(val1 / val2, &head); break;
}
}
}
return pop(&head);
}
void push (int item, node **head) {
node *temp;
node * get_node(int);
temp = get_node(item);
temp->next = *head;
*head = temp;
}
node *get_node(int item) {
node *temp;
temp = (node*)malloc(sizeof(node));
if (temp == NULL)
printf("\nMemory cannot be allocated");
temp->num = item;
temp->next = NULL;
return(temp);
}
int pop(node **head) {
int item;
node *temp;
item = (*head)->num;
temp = *head;
*head = (*head)->next;
free(temp);
return(item);
}
int is_empty(node *temp) {
if (temp == NULL)
return 1;
else
return 0;
}
void display(node **head) {
node *temp;
temp = *head;
if(head == NULL) {
printf("stack is empty\n");
return;
}
printf("\n");
printf("=========\n");
while(temp!=NULL) {
printf("%d\n", (*temp).num);
temp = (*temp).next;
}
printf("=========\n");
}
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "stack.h"
#define MAX_EQU_LEN 100
static int prec(char operator)
{
switch (operator)
{
case '*':
return 5;
case '/':
return 4;
case '%':
return 3;
case '+':
return 2;
case '-':
return 1;
default:
break;
}
return 0;
}
static int isNumeric(char* num)
{
if(atoi(num) == 0)
{
return 0;
}
return 1;
}
char* infix_to_postfix(char* infix)
{
char* postfix = malloc(MAX_EQU_LEN);
stack* s = create_stack();
s->size = strlen(infix);
node* tempPtr = s->stack;
unsigned int i;
char symbol,next;
char temp[2] = {0};
for(i = 0; i < s->size ; i++)
{
symbol = *((infix + i));
temp[0] = symbol;
tempPtr = s->stack;
if(isNumeric(temp) != 1)
{
strcat(postfix, temp);
}
else if(symbol == '(')
{
push(s, symbol);
}
else if(symbol == ')')
{
while(s->size != 0 && top(s) != '(')
{
next = tempPtr->data;
temp[0] = next;
pop(s);
strcat(postfix, temp);
tempPtr = s->stack;
if(tempPtr->data == '(')
{
pop(s);
}
}
}
else
{
while(s->size != 0 && prec(top(s)) > prec(symbol))
{
next = tempPtr->data;
temp[0] = next;
pop(s);
strcat(postfix,temp);
push(s,next);
}
}
while(s->size != 0)
{
next = tempPtr->data;
temp[0] = next;
pop(s);
strcat(postfix, temp);
}
}
return postfix;
}
int evaluate_postfix(char* postfix) {
//For each token in the string
int i,result;
int right, left;
char ch;
stack* s = create_stack();
node* tempPtr = s->stack;
for(i=0; i < strlen(postfix); i++){
//if the token is numeric
ch = postfix[i];
if(isNumeric(&ch)){
//convert it to an integer and push it onto the stack
atoi(&ch);
push(s, ch);
}
else
{
pop(&s[0]);
pop(&s[1]);
//apply the operation:
//result = left op right
switch(ch)
{
case '+': push(&s[i],right + left);
break;
case '-': push(&s[i],right - left);
break;
case '*': push(&s[i],right * left);
break;
case '/': push(&s[i],right / left);
break;
}
}
}
tempPtr = s->stack;
//return the result from the stack
return(tempPtr->data);
}
This code is part of a bigger program that is designed to convert simple math from infix to postfix and then evaluate it. This will be aided by a stack to hold the numbers and symbols. However when I run the program it seg faults and all the debugger says is that it is in the infix_to_postfix function and I cannot figure out what part of the code makes it seg fault.
I've been trying to debug this program for a long time. It works fine when I input expressions like a + b - c or a / b + c where the first operator has a greater or equal precedence than the second. But for expressions like a - b / c where the first operator has a lesser precedence than the second, the compiler throws a breakpoint.
struct stack
{
char ele;
struct stack *next;
};
void push(int);
int pop();
int precedence(char);
struct stack *top = NULL;
int main()
{
char infix[20], postfix[20];
int i = 0, j = 0;
printf("ENTER INFIX EXPRESSION: ");
gets(infix);
while(infix[i] != '\0')
{
if(isalnum(infix[i]))
postfix[j++] = infix[i];
else
{
if(top == NULL)
push(infix[i]);
else
{
while( top != NULL &&
(precedence(top->ele) >= precedence(infix[i])) )
postfix[j++]=pop();
push(infix[i]);
}
}
++i;
}
while(top != NULL)
postfix[j++] = pop();
postfix[j] = '\0';
puts(postfix);
getchar();
return 0;
}
int precedence(char x)
{
switch(x)
{
case '^': return 4;
case '*':
case '/': return 3;
case '+':
case '-': return 2;
default: return 0;
}
}
void push(int x)
{
int item;
struct stack *tmp;
if(top == NULL)
{
top = (struct stack *)malloc(sizeof(struct stack));
top->ele = x;
top->next = NULL;
}
else
{
tmp = top;
top->ele = x;
top->next = tmp;
}
}
int pop()
{
struct stack *tmp;
int item;
if(top == NULL)
puts("EMPTY STACK");
else if(top->next == NULL)
{
tmp = top;
item = top->ele;
top = NULL;
free(tmp);
}
else
{
tmp = top;
item = top->ele;
top = top->next;
free(tmp);
}
return item;
}
Any advice on how to improve my coding would be helpful.