Hi!

I am trying to write calculator in c++ that takes an infix expression, converts it to postfix, and calculates.

I have the code that will do this written, but when I try to turn it into a class it gives my a Segmentation Fault.

Here is my code...

//calc.h


#ifndef INFIX_TO_POSTFIX_H
#define INFIX_TO_POSTFIX_H

#include "stack.h"
#include <iostream>
#include <string>
#include <cctype>
#include <cmath>


class Calculator
{
	public:
		
		void start();
		void check();
		bool error(string);
		void convert_postfix(string);
		void evaluate_postfix(string);
		
	private:
		MyStack<char> s;
		MyStack<int> ints;
		int priority;
		std::string exp;
		std::string postfix;
};

#endif

calc.cpp

#include "calc.h"
#include "stack.h"
#include <iostream>
#include <string>
#include <cctype>
#include <cmath>
using namespace std;


void Calculator::start()
{
	char ans;
	
	
		string exp;

		cout << "Enter an infix expression: ";
		cin >> exp;

		if ( error(exp) )
		{
			// CHECK FOR ERRORS IN EXPRESSION*********
			cout << "Program will not execute expression is incorrect\n";
		}
		else 
		{
			convert_postfix(exp);
			cout << "Here is your postfix expression " << postfix << endl;
			
			//evaluate_postfix(postfix);
			

		}
		
	
}


void Calculator::check()
{
	switch (s.get_top())
	{
	case '*':
	case '/':
	case '%':
		priority=1; break;
	case '+':
	case '-':
		priority=2; break;
	}

}



void Calculator::convert_postfix(string post)
{

	char ch;
	string temp;
	string infix = exp;

	for (int i = 0; i < exp.length(); i++)
	{

		ch = exp[i];

		if ( exp[i] == '+' || exp[i] == '-')
		{
			if (priority <= 2 )
			{
				while(!s.is_empty() && s.get_top() != '(')
					{
						postfix += s.get_top();
						s.pop();
					}
				priority = 0;
				s.push(ch);
				check();
			}
			else
				s.push(ch);
				check();
	}
	
	else if ( exp[i] == '*' || exp[i] == '/' || exp[i] == '%' )
	{
		if (priority == 1 )
		{
			while(!s.is_empty() && s.get_top() != '(')
					{
						postfix += s.get_top();
						s.pop();
						check();
					}
					s.push(ch);
					check();
		}
		else 
			s.push(ch);
			check();
	}
	
	else if ( exp[i] == '(' )
	{
			s.push(ch);
			check();
	}
	else if ( exp[i] == ')' )
	{
			   while(!s.is_empty() && s.get_top() != '(')
            {
				postfix += s.get_top();
                s.pop();
				check();
            }
            s.pop();
			check();
	}

	else if ( isdigit(infix[i]) )
	{
		if ( isdigit(infix[i+1]) )
		{
			int b=i+1;
			temp = infix[i];
			while ( isdigit(infix[b]) )
			{
				ch=infix[b];
				temp = temp + ch;
				++b;
			}
			postfix = postfix + ' ' + temp;
			i=b-1;
		}
		else
		{
			postfix = postfix + ' ' + ch;
		}

	}

}

  while(!s.is_empty())
    {
		char k = s.get_top();
		postfix = postfix + ' ' + k;
		s.pop();
		check();
    }



// FOR MULTIPLE AND SINGLE DIGIT NUMBERS

cout << "\nPOSTFIX "<< postfix << endl;

}

void Calculator::evaluate_postfix(string post)
{
	MyStack<int> s;
	int i, n = post.length();
	int op1, op2;
	
	for(i=0; i<post.length();)
	{
		if(isdigit(post[i]))
		{
			int temp = post[i]-'0';
			if(isdigit(post[i+1]))
			{
				int b=i+1;
				while(isdigit(post[b]))
				{
					temp = temp*10 + (post[i+1]-'0');
					b++;
				}
				s.push(temp);
				i++;
			}
			else
				s.push(temp);
				i++;
		}
		else if(post[i] == '+')
		{
			op1 = s.get_top();
			s.pop();
			op2= s.get_top();
			s.push(op1+op2);
			i++;
		}
		else if(post[i] == '-')
		{
			op1 = s.get_top();
			s.pop();
			op2= s.get_top();
			s.push(op2-op1);
			i++;
		}
		else if(post[i] == '*')
		{
			op1 = s.get_top();
			s.pop();
			op2= s.get_top();
			s.push(op1*op2);
			i++;
		}
		else if(post[i] == '/')
		{
			op1 = s.get_top();
			s.pop();
			op2= s.get_top();
			if(op1==0)
			{
				break;
			}
			else
				s.push(op2/op1);
				i++;
		}
		else if(post[i] = ' ')
		{
			i++;
		}
	}
	if(!s.is_empty())
	{
		cout<<"\nThe result is: " <<s.get_top()<<endl;
	}
	else
		cout<<"\nCalculation error. \n";
		
	
	cout<<endl<<endl;
}

// CHECKS EXPRESSION FOR ERRORS***********************************************************

bool Calculator::error(string exp)
{
	int count = 0;
	int count1 = 0;
	int len = exp.length();
	int a = 0;
	int b = 0;

	while (a <= len)
	{
		if ( exp[a] == '(' ) {++count;}
		++a;
	}

	while (b <= len)
	{
		if ( exp[b] == ')' ) {++count1;}
		++b;
	}



	if (count == count1) return false; else return true;

}

And main.cpp

#include "stack.h"
#include "calc.h"
#include <iostream>
#include <string>
#include <cctype>
#include <cmath>

using namespace std;



int main()
{
	Calculator mycalc;
	
	mycalc.start();
}

EDIT
Ok... I no longer get a segmentation fault. Now I am not getting any thing in the postfix string

Edited 4 Years Ago by cameronchuck: n/a

Your not getting anything because the string infix = exp; is not the exp read in at line 15 of calc.cpp (scope issue).
I replaced your MyStack with std::stack and made the fix above and it Segfaults in check() .
You can see that for the input of "5+5" the post fix string has the value " 5 5 +", but segfault. This fault is at the bottom of convert_postfix() in the while loop.

(gdb) r
Reading symbols for shared libraries ++. done
Enter an infix expression: 5+5

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x00000000000001ff
0x0000000100003987 in Calculator::check (this=0x7fff5fbff8b0) at calc.cpp:38
38		switch (s.top())
(gdb) p postfix
$1 = {
  static npos = 18446744073709551615, 
  _M_dataplus = {
    <std::allocator<char>> = {
      <__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, 
    members of std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Alloc_hider: 
    _M_p = 0x1001000b8 " 5 5 +"
  }
}
(gdb)

If in that while loop I don't call check if s is empty().

while(!s.empty())
{
     char k = s.top();
     postfix = postfix + ' ' + k;
     s.pop();
     // Not sure of all the details of check(), but
     // calling check on an empty stack is bad
     if ( !s.empty())
          check();
}

This is the result:

$ ./cal
Enter an infix expression: 5+5

POSTFIX  5 5 +
Here is your postfix expression  5 5 +

(5+5)*2 still segfaults, but get easy ones working first, then move on from there.
And again I used std::stack because you didn't post your stack.h, so make sure I am not sending you down the wrong path.

Edited 4 Years Ago by histrungalot: n/a

This article has been dead for over six months. Start a new discussion instead.