infix and postfix homework, stumped

Hello! As the title suggests, I am attempting to write a program that takes a infix equation in string format, with each term in the equation occupying a separate node in a Queue. This then must throw an exception if there are two numbers in a row or there is an unmatched parenthesis. Unfortunately, my professor's internal tests tell me that I have three problems:

1) I do not throw an exception when an erroneous input is given. He does not tell me this input.

2) I throw an exception for an input with no problems.

3) The equation returned by showConverted(), the string Converted, is blank.


The reason I'm posting for help is that, whenever I try to reproduce any of these issues, my program will not compile, and returns an error:

error LNK2005: "public: __thiscall Compute::Compute(void)" (??0Compute@@QAE@XZ) already defined in Compute.obj

1>testinggrounds.obj : error LNK2005: "public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall Compute::showOriginal(void)" (?showOriginal@Compute@@QAE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ) already defined in Compute.obj

1>testinggrounds.obj : error LNK2005: "public: class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > __thiscall Compute::showConverted(void)" (?showConverted@Compute@@QAE?AV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@XZ) already defined in Compute.obj

1>testinggrounds.obj : error LNK2005: "int __cdecl isoperator(char)" (?isoperator@@YAHD@Z) already defined in Compute.obj
1>testinggrounds.obj : error LNK2005: "int __cdecl priority(char)" (?priority@@YAHD@Z) already defined in Compute.obj
1>testinggrounds.obj : error LNK2005: "public: void __thiscall Compute::init(class Queue<class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > >)" (?init@Compute@@QAEXV?$Queue@V?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@@@Z) already defined in Compute.obj
fatal error LNK1169: one or more multiply defined symbols found


So my question: what do I need to change in order to be able to compile my program with the given main? AND, if any kind soul is willing, what am I doing wrong with the program itself?




My compute class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include "Stack.h"
#include "StackException.h"
#include "Queue.h"
#include "QueueException.h"
#include <string>
#include <sstream>
#include <cstdlib>
#include <math.h>

class Compute
{
	string Original;
	string Converted;
	Queue<string> input;
	Stack<string> stack1;
	Stack<double> stack2;
public:
	Compute();
	void init(Queue<string> input) throw (StackException, QueueException);
	double compute() throw(StackException);
	string showOriginal();
	string showConverted();
	//int priority(char e);
	//int isoperator(char input)
};





1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#include "Compute.h"

using namespace std;

Compute::Compute()
{
	string Original;
	string Converted;
	Queue<string> input;
	Stack<string> stack1;
	Stack<double> stack2;
}

string Compute::showOriginal()
{
	return Original;
}

string Compute::showConverted()
{
	return Converted;
}

int isoperator(char e)

{
	
    if(e == '+' || e == '-' || e == '*' || e == '/' || e == '%')
	{
        return 1;
	}
	else
	{
        return 0;
	}

}



int priority(char e)

{
    int pri = 0;

    if(e == '*' || e == '/' || e =='%')
	{
        pri = 2;
	}
    else
    {
        if(e == '+' || e == '-')
           pri = 1;
    }
   return pri;
}


void Compute::init(Queue<string> input) throw(StackException, QueueException)
{
	Queue<string> input2 = input;
	int leftcount;
	int rightcount;
		while(input2.isEmpty() != 1)
	{
		
		string index;
		index = input2.dequeue();
		Original.append(index);
		Original.append(" "); //placing a blank space between each input

		if(index == "(")
		{
			leftcount++;
		}
		else if(index == ")")
		{
			rightcount++;
		}
		else if(!isoperator(index[0]) && !isoperator(input2.front()[0]))
		{
			throw QueueException();
		}
		
	}
	
		if(leftcount > rightcount)
		{
			throw QueueException();
		}
		else if(rightcount > leftcount)
		{
			throw StackException();
		}
	

		

	
	while(input.isEmpty() != 1)
	{
	char ch = input.dequeue()[0];

	if(isoperator(ch))
	{
		while(!input.isEmpty() && input.front()[0] != '(' && priority(ch) <= priority(input.front()[0]))
		{
			stack1.push(input.dequeue());
		}
	}
	else if(ch == '(')
	{
		stack1.push(input.dequeue());
	}
	else if(ch == ')') 
	{
		while(input.front()[0] != '(')
		{
			stack1.push(input.dequeue());
		}
	}
	else // this assumes that if it's not a (, ), or an operator, it is guaranteed to be a operand
	{
		stack1.push(input.dequeue());
	}

	}

	Stack<string> input1 = stack1; // save converted equation in string format
	while(input1.isEmpty() != 1)
	{
		Converted.append(input1.pop());
		Converted.append(" ");
	}

}


double Compute::compute() throw(StackException)
{
	double op1;
	double op2;
	double result;
	

	while(stack1.isEmpty() != 1)
	{
		while(stack1.top() == " " || stack1.top() == "/t")
		{
			stack1.pop();
		}
		if(isoperator(stack1.top()[0]) == 1)
		{
			op1 = stack2.pop();
			op2 = stack2.pop();
			
			switch(stack1.top()[0])
			{
				case '+':

                    result = op2 + op1;
                    break;

                case '-':
                    result = op2 - op1;
                    break;

                case '/':
                    result = op2 / op1;
                    break;
 
                case '*':
                    result = op2 * op1;
                    break;

			}
			stack2.push(result);
			stack1.pop();
		}
		else
		{
			double index;
			index = ::atof(stack1.pop().c_str());
			stack2.push(index);
		}

	}
	result = stack2.pop();
	return result;
}







The main I am trying to use to replicate my errors:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include "Compute.cpp"

using namespace std;
void main()
{
	Queue<string> testinput;

	testinput.enqueue("5");
	testinput.enqueue("8");

	Compute winning;
	winning.init(testinput);

	cout << winning.showOriginal() << endl;
	cout << winning.showConverted() << endl;

	int pause;

	cin >> pause;
}



Last edited on
not to double post, but here is my Queue class if it matters. The input to init() comes in the form of a Queue, with each node in the Queue containing a single term of the equation in string form.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#ifndef QUEUE_H
#define QUEUE_H

#include "Node.h"
#include "QueueException.h"

using namespace std;

template <typename T>
class Queue 
{
public:
Node<T>* head;
Node<T>* current;
int cnt;

Queue();
Queue(T data);
Queue(const Queue &rhs);
const Queue & operator=(const Queue &rhs);
~Queue();
void enqueue(T data);
T dequeue() throw (QueueException);
T front() throw (QueueException);
bool isEmpty();
};

template <typename T>
Queue<T>::Queue()
{
	head = NULL;
	current = NULL;
	cnt = 0;
}

template <typename T>
Queue<T>::Queue(T data)
{
	head = new Node<T>(data,NULL);
	current = head;
	cnt = 1;
}

template <typename T>
Queue<T>::~Queue()
{
	if(head != NULL)
	{
		
	
	current = head;
	while(current->getNext() != NULL)
	{
		cout << current->next;
		Node<T>* next = current->next;
		//cout << current->next;
		//delete current;
		current = next;
	}
	}
}

template <typename T>
Queue<T>::Queue(const Queue<T> &rhs)
{
	cnt = rhs.cnt;
    head = NULL;
    if (rhs.head != NULL)
    {
        head = new Node<T>(rhs.head->getData());
        Node<T>* curr = head;
        Node<T>* otherCurr = rhs.head->getNext();
        while(otherCurr != NULL)
        {
            curr->setNext(new Node<T>(otherCurr->getData()));
            curr = curr->getNext();
            otherCurr = otherCurr->getNext();
        }
    }

}

template <typename T>
bool Queue<T>::isEmpty()
{
	if(cnt == 0)
	{
		return 1;
	}
	else
	{
		return 0;
	}
}

template <typename T>
T Queue<T>::front() throw(QueueException)
{
	if(cnt == 0)
	{
		throw QueueException();
	}
	return head->getData();
}

template <typename T>
T Queue<T>::dequeue() throw (QueueException)
{
	T toRemove;
	if(cnt == 0)
	{
		throw QueueException();
	}
	if(cnt == 1)
	{
		
	  toRemove = head->getData();
	  //head->data = NULL;
	  cnt--;
	  return toRemove;
	}
	
	  toRemove = head->getData();
        head = head->getNext();
        cnt--;
        return toRemove;
}

template <typename T>
void Queue<T>::enqueue(T newdata)
{
    if(head != NULL)
    {
        current = head;
        while(current->getNext() != NULL)
        {
            current = current->getNext();
        }
        Node<T>* newinsert = new Node<T>(newdata, NULL);
        current->setNext(newinsert);
    }
    else
    {
        Node<T>* newinsert = new Node<T>(newdata, NULL);
        head = newinsert;
    }
    cnt++;
}


template <typename T>
const Queue<T>& Queue<T>::operator=(const Queue<T> &rhs)
{
		cnt = rhs.cnt;
    head = NULL;
    if (rhs.head != NULL)
    {
        head = new Node<T>(rhs.head->getData());
        Node<T>* curr = head;
        Node<T>* otherCurr = rhs.head->getNext();
        while(otherCurr != NULL)
        {
            curr->setNext(new Node<T>(otherCurr->getData()));
            curr = curr->getNext();
            otherCurr = otherCurr->getNext();
        }
    }

}

#endif	 
Why are you including the .cpp file? That is defining your methods multiple times in two cpp files, resulting in all the errors. Just include the header file.
Oh wow, that... worked.

Sorry for the trouble.
Well, I've tried a few inputs, and my exceptions aren't working properly. When my main is this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include "Compute.h"

using namespace std;
void main()
{
	Queue<string> testinput;

	testinput.enqueue("5");
	testinput.enqueue("+");
	testinput.enqueue("8");

	Compute winning;
	winning.init(testinput);

	cout << winning.showOriginal() << endl;
	cout << winning.showConverted() << endl;

	int pause;

	cin >> pause;
}



My code ends at line 85 of compute.cpp, and throws a QueueException. What am I doing wrong with my exception checking?

OK,

Here is my updated Compute.cpp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
#include "Compute.h"

using namespace std;

Compute::Compute()
{
	string Original;
	string Converted;
	Queue<string> input;
	Stack<string> stack1;
	Stack<double> stack2;
}

string Compute::showOriginal()
{
	return Original;
}

string Compute::showConverted()
{
	return Converted;
}

int isoperator(char e)

{
	
    if(e == '+' || e == '-' || e == '*' || e == '/' || e == '%')
	{
        return 1;
	}
	else
	{
        return 0;
	}

}



int priority(char e)

{
    int pri = 0;

    if(e == '*' || e == '/' || e =='%')
	{
        pri = 2;
	}
    else
    {
        if(e == '+' || e == '-')
           pri = 1;
    }
   return pri;
}


void Compute::init(Queue<string> input) throw(StackException, QueueException)
{
	Queue<string> input2 = input;
	int leftcount = 0;
	int rightcount = 0;
	bool lastnumber = 0;
	if(input.isEmpty() == 1)
	{
		throw QueueException();
	}
		while(input2.isEmpty() != 1)
	{
		
		string index;
		index = input2.dequeue();
		Original.append(index);
		Original.append(" "); //placing a blank space between each input

		if(index == "(")
		{
			leftcount++;
			lastnumber=0;
		}
		else if(index == ")")
		{
			rightcount++;
			lastnumber = 0;
		}
		
		else if(isoperator(index[0]) == 1)
		{
			lastnumber = 0;
		}
		else
		{
			if(lastnumber == 1)
			{
				throw QueueException();
			}
			lastnumber = 1;
		}
	}
	
		if(leftcount > rightcount)
		{
			throw QueueException();
		}
		else if(rightcount > leftcount)
		{
			throw StackException();
		}
	

		

	
	while(input.isEmpty() != 1)
	{
	char ch = input.dequeue()[0];

	if(isoperator(ch))
	{
		while(!input.isEmpty() && input.front()[0] != '(' && priority(ch) <= priority(input.front()[0]))
		{
			stack1.push(input.dequeue());
		}
	}
	else if(ch == '(')
	{
		stack1.push(input.dequeue());
	}
	else if(ch == ')') 
	{
		while(input.front()[0] != '(')
		{
			stack1.push(input.dequeue());
		}
	}
	else // this assumes that if it's not a (, ), or an operator, it is guaranteed to be a operand
	{
		stack1.push(input.dequeue());
	}

	}

	Stack<string> input1 = stack1; // save converted equation in string format
	while(input1.isEmpty() != 1)
	{
		Converted.append(input1.pop());
		Converted.append(" ");
	}

}


double Compute::compute() throw(StackException)
{
	double op1;
	double op2;
	double result;
	

	while(stack1.isEmpty() != 1)
	{
		while(stack1.top() == " " || stack1.top() == "/t")
		{
			stack1.pop();
		}
		if(isoperator(stack1.top()[0]) == 1)
		{
			op1 = stack2.pop();
			op2 = stack2.pop();
			
			switch(stack1.top()[0])
			{
				case '+':

                    result = op2 + op1;
                    break;

                case '-':
                    result = op2 - op1;
                    break;

                case '/':
                    result = op2 / op1;
                    break;
 
                case '*':
                    result = op2 * op1;
                    break;

			}
			stack2.push(result);
			stack1.pop();
		}
		else
		{
			double index;
			index = ::atof(stack1.pop().c_str());
			stack2.push(index);
		}

	}
	result = stack2.pop();
	return result;
}





It is now throw exceptions for erroneous inputs correctly. However, it is incorrectly throw exceptions for non-erroneous inputs.

Specifically, it is triggering the built-in exception in the dequeue on line 73 of the Compute.cpp. This is despite the fact that this exists in a loop that should stop when the queue is empty. What am I doing wrong?

It is also not handling parenthesis correctly. Any idea why?
Last edited on
Looks like i'm trying to continue pulling terms from the input even when it's empty. I don't understand though, the internal cnt variable should keep track of when it's empty.
Topic archived. No new replies allowed.