review and testing

Hi,
I am new to c++, this is my first real program in c++. I tested it and it works for me as I wanted to. At least as far as I myself tested. So I would like to have help me test it and show if here are equations it don't calculate, but it should calculate. Or to show me parts of codes that could be improved. Half of code are heavily commented, because it helped me to fix code.
Thanks.
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
206
207
208
209
210
211
212
213
214
215
216
217
#include <string>
#include <stdlib.h>
#include <iostream>
#include <cstring>
#include <math.h>
#include <sstream>
using namespace std;

class Calculator {
	/*
	 * This is calculator class to calculait equations given as a string.
	 * This class suports operations:
	 * +, -, *, /, (), sin(), cos(), tan(), sqrt()
	 * and can be easily extended.
	 * lines "for checking purposes" can be deleted or commented.
	 */
	public:
		Calculator(string);
		~Calculator();
		void add_to_equation(string);
		double count_equation();
		int show_errors();
		
	private:
		//Variables
		string equation;
		int error_code;
		int operation;
		char right_parenthesis;
		char left_parenthesis;
		string key_actions;
		string list_of_numbers;
		string functions[4];
		double PI;
		
		//----------for checking purposes--------------------------//
		string space;
		//----------for checking purposes--------------------------//
		
		//Functions
		double count_element_in_equation(string);
		double count_function(double, string);
		int find_key_operation(string, bool);
		double string_to_double(string);
		string double_to_string(double);
		string reverse_string(string);
		int find_first_key_operation(size_t*, int);
		bool check_key_action(string&, int&, size_t);
		
	/*
	* error_code:
	* 101 - empty equation.
	* 102 - wrong formula, missing bracket.
	* 103 - wrong formula, several +, * and / found side by side.
	* 104 - found the unknown function.
	* */
};

Calculator::Calculator(string line = "") {
	equation = line;
	right_parenthesis = ')';
	left_parenthesis = '(';
	error_code = 0;
	PI = 3.14159265;
	key_actions = "*/+-";
	list_of_numbers = "0123456789.";
	functions[0] = "sqrt";
	functions[1] = "sin";
	functions[2] = "tan";
	functions[3] = "cos";
	
	//----------for checking purposes--------------------------//
	space = "    ";
	//----------for checking purposes--------------------------//
}

Calculator::~Calculator() {}

void Calculator::add_to_equation(string line) {
	//add equation to object or append it to equation in object.
	equation += line;
}

double Calculator::count_equation() {
	
	//----------for checking purposes--------------------------//
	cout << "We calculate: " << equation << endl;
	//----------for checking purposes--------------------------//
	
	string string_temp;
	double result = 0.0;
	//checks whether variable equation are empty or have data in it.
	//if empty sets error_code to 101 and returns result variable.
	if (equation.empty()) {
		error_code = 101;
		return result;
	}
	
	//creats variables for right and left parenthesis locations in equation.
	size_t found_right_parenthesis_location, found_left_parenthesis_location;
	//search right paranthesis in equation.
	found_right_parenthesis_location = equation.find(right_parenthesis);
	//checks if right paranthesis was found or not.
	if (found_right_parenthesis_location != string::npos) {
		//if right paranthesis are found, then makes a copy of part of equation and reverse it
		//to make it easy to find left paranthesis.
		string_temp = reverse_string(equation.substr(0, found_right_parenthesis_location));
		//search left paranthesis in equation.
		found_left_parenthesis_location = string_temp.find(left_parenthesis);
		//checks if left paranthesis was found or not.
		if (found_left_parenthesis_location != string::npos) {
			//if left paranthesis was found, then corrects location of left paranthesis in full equation.
			found_left_parenthesis_location = string_temp.length() - found_left_parenthesis_location - 1;
		}
		else {
			//if left paranthesis was not found, then sets error_code to 102 and returns result variable.
			error_code = 102;
			return result;
		}
	}
	else {
		//if right paranthesis are not found, then checks if left paranthesis are in equation.
		found_left_parenthesis_location = equation.find(left_parenthesis);
		if (found_left_parenthesis_location != string::npos) {
			//if left paranthesis was not found, then sets error_code to 102 and returns result variable. 
			error_code = 102;
			return result;
		}
		//if no paranthesis was found sets left paranthesis location to -1 and right paranthesis to string length.
		//Because all equation are wraped in imaginary paranthesis.
		found_left_parenthesis_location = -1;
		found_right_parenthesis_location = equation.length();
	}
	
	string_temp = equation.substr(found_left_parenthesis_location + 1, found_right_parenthesis_location - found_left_parenthesis_location - 1);
	
	//----------for checking purposes--------------------------//
	cout << "I give: " << string_temp << endl;
	//----------for checking purposes--------------------------//
	
	//counts equation between left and right paranthesis.
	result = count_element_in_equation(string_temp);
	
	//----------for checking purposes--------------------------//
	cout << "I got: " << result << endl;
	//----------for checking purposes--------------------------//
	
	//checks if paranthesis are from function or not.
	if (found_left_parenthesis_location != string::npos) {
		//if left paranthesis location are 0, here can't be anything in left of it. 
		if (found_left_parenthesis_location != 0) {
			//if left paranthesis are not 0 checks that is in left of it.
			//in left of left paranthesis can be another left paranthesis, one of key action or function.
			//if it is function that function must be calculated.
			char symbol;
			bool found_symbol = false;
			//gets a simbol in left of left paranthesis.
			symbol = equation[found_left_parenthesis_location - 1];
			//if simbol are left paranthesis skip all code in this if statment.
			if (symbol != left_parenthesis) {
				//checks if simbol are one of key actions.
				for (int i = 0; i < 4; i++) {
					if (symbol == key_actions[i]) {
						found_symbol = true;
					}
				}
				//if simbol are not one of key actions get functions name in left of left paranthesis.
				if (!found_symbol) {
					int location;
					//gets location of first key action in left of left paranthesis.
					location = find_key_operation(reverse_string(equation.substr(0, found_left_parenthesis_location)), true);
					//changes location of left paranthesis, becouse function name was found.
					found_left_parenthesis_location = found_left_parenthesis_location - location;
					//calculates result of funcion.					
					result = count_function(result, equation.substr(found_left_parenthesis_location, location));
					
					//----------for checking purposes--------------------------//
					cout << "I calculated: " << equation.substr(found_left_parenthesis_location, location) << "()=" << result << endl;
					//----------for checking purposes--------------------------//
				}
			}
		}
	}
	
	if (found_left_parenthesis_location != string::npos) {
		//if paranthesis was found, changes them to result of calculations.
		equation.replace(found_left_parenthesis_location, found_right_parenthesis_location - found_left_parenthesis_location + 1, double_to_string(result));
		
		//----------for checking purposes--------------------------//
		cout << "I changed to: " << equation << endl << endl;
		//----------for checking purposes--------------------------//
		
		//calls function count_equation() to recalculate equation.
		result = count_equation();
	}
	return result;
}

double Calculator::count_function(double number, string line) {
	double result;
	//checks which function need to be used and calculates given number.
	if (line == functions[0]) 
		result = sqrt(number);
	else if (line == functions[1]) 
		result = sin(number * PI / 180);
	else if (line == functions[2]) 
		result = tan(number * PI / 180);
	else if (line == functions[3]) 
		result = cos(number * PI / 180);
	else {
		//if function name are not found in functions[] gives back error code and returns 0.0.
		error_code = 104;
		result = 0.0;
	}

	return result;
}
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
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
double Calculator::count_element_in_equation(string line) {
	
	//----------for checking purposes--------------------------//
	cout << space << "I got: " << line << endl;
	//----------for checking purposes--------------------------//
	
	//this function calculates part of equation that is between parenthesis.
	//number_double[] are for two nombers, in left and in rigth of key action.
	double result, number_double[2];
	//saves first key action to use it in calculating numbers.
	int operation_temp;
	//number_str[] hold two numbers as string from equation.
	//new_line hold part of given equation. 
	string number_str[2], new_line;
	//location[] holds location of key actions to know where are numbers.
	int location[3], temp;
	bool check;
	//finds location of main key action.
	location[1] = find_key_operation(line, false);
	//checks if key action was found. If variable operation is 0, 1, 2 or 3 it means key action
	//was found. If it is greate, no key action was found.
	if (operation > 3) {
		//if no key action was found it means only number are left, so it returns that number. 
		//But first converts it from string to double.
		return string_to_double(line);
	}
	//makes a copy of main key action.
	temp = location[1];
	//checks if here are other key action in left or right from main key action.
	check = check_key_action(line, temp, line.length());
	//checks if error was detected.
	if (!check) {
		return 0.0; 
	}
	//check_key_action() changes line and temp variables.
	//if key action was found and if this key action are acceptable variable line will be changed, 
	//if it are not acceptable false will be returned and error code will be given.
	//if variable line changes location of main key action may be changed and returned in temp variable.
	location[1] = temp;
	
	//saves main key action.
	operation_temp = operation;
	//takes part of equation given to this funcion.
	new_line = line.substr(0, location[1]);
	//reverses this part.
	new_line = reverse_string(new_line);
	//finds new key action and its location in part of equation.
	location[0] = find_key_operation(new_line, true);
	if (operation < 4) {
		//if key action was found changes location for location[0] to be correct in variable line.
		location[0] = location[1] - location[0] - 1;
		// checks if here are other key actions in left or right from second key action.
		temp = location[0];
		check = check_key_action(line, temp, line.length());
		//checks if error was detected.
		if (!check) {
			return 0.0; 
		}
		//if key action was found in last check and no errors was given,
		//changes locations for location[0] and location[1]
		if (temp != location[0]) {
			location[1] = location[1] - location[0] + temp;
			location[0] = temp;
		}
		//takes left number from equation.
		number_str[0] = line.substr(location[0] + 1, location[1] - location[0] - 1);
	}
	else {
		//if key action was not found, takes left number from equation.
		number_str[0] = line.substr(0, location[1]);
		//and sets location[0] to imaginary location out of equation.
		location[0] = -1;
	}
	
	//converts left number from string to double.
	number_double[0] = string_to_double(number_str[0]);
	
	new_line = line.substr(location[1] + 1);
	location[2] = find_key_operation(new_line, true);
	if (operation < 4) {
		//if key action was found changes location for location[2] to be correct in variable line.
		location[2] = location[1] + location[2] + 1;
		// checks if here are other key actions in left or right from third key action.
		temp = location[2];
		check = check_key_action(line, temp, line.length());
		//checks if error was detected.
		if (!check) {
			return 0.0; 
		}
	}
	else {
		//sets location[2] to imaginary location out of equation.
		location[2] = line.length();
	}
	//takes rigth number from equation.
	number_str[1] = line.substr(location[1] + 1, location[2] - location[1] - 1);
	//converts right number from string to double.
	number_double[1] = string_to_double(number_str[1]);
	
	//calculates result of left and right numbers action.
	if (operation_temp == 0) {
		result = number_double[0] * number_double[1];
	}
	else if (operation_temp == 1) {
		result = number_double[0] / number_double[1];
	}
	else if (operation_temp == 2) {
		result = number_double[0] + number_double[1];
	}
	else if (operation_temp == 3) {
		result = number_double[0] - number_double[1];
	}
	
	//----------for checking purposes--------------------------//
	cout << space << "I calculated: " << number_double[0] << key_actions[operation_temp] << number_double[1] << "=" << result << endl;
	//----------for checking purposes--------------------------//
	
	//checks if all equation given to this function are calculated.
	if (((int)location[0] > 0) or ((int)location[2] < (int)line.length())) {
		//if not all equation are calculated, changes equation part which are calculated to it result.
		line.replace(location[0] + 1, location[2] - location[0] - 1, double_to_string(result));
		
		//----------for checking purposes--------------------------//
		cout << space << "I changed to: " << line << endl;
		//----------for checking purposes--------------------------//
		
		//recalculates equation.
		result = count_element_in_equation(line);
	}
	
	//----------for checking purposes--------------------------//
	cout << space << "I returned: " << result << endl;
	//----------for checking purposes--------------------------//
	
	return result;
}

int Calculator::find_key_operation(string line, bool reverse) {
	size_t found[4];
	for (int i = 0; i < 4; i++) {
		found[i] = line.find(key_actions[i]);
	}
	
	if (!reverse) {
		if (found[0] == string::npos and found[1] == string::npos) {
			if (found[2] == string::npos and found[3] == string::npos) {
				operation = 4;
				return -1;
			}
			
			if (found[2] == 0) {
				error_code = 103;
				operation = 4;
				return 0;
			}
			else if (found[3] == 0) {
				return find_key_operation(line.substr(1), reverse) + 1;
			}
			
			if (found[2] == string::npos) {
				operation = 3;
			}
			else if (found[3] == string::npos) {
				operation = 2;
			}
			else if (found[2] < found[3]) {
				operation = 2;
			}
			else {
				operation = 3;
			}
			return found[operation];
		}
		
		if (found[0] == 0 or found[1] == 0) {
			error_code = 103;
			operation = 4;
			return 0;
		}
		
		if (found[0] == string::npos) {
			operation = 1;
		}
		else if (found[1] == string::npos) {
			operation = 0;
		}
		else if (found[0] < found[1]) {
			operation = 0;
		}
		else {
			operation = 1;
		}
		return found[operation];
	}
	else {
		for (int i = 0; i < 4; i++) {
			if (found[i] == string::npos) {
				found[i] = line.length();
			}
			else if (found[i] == (line.length() - 1)) {
				found[i] = -1;
			}
		}
		if ((found[0] == found[1]) and (found[0] == found[2]) and (found[0] == found[3])) {
			operation = 4;
			return -1;
		}
		
		int result = find_first_key_operation(found, 4);
		for (int i = 0; i < 4; i++) {
			if (line[result] == key_actions[i]) {
				operation = i;
			}
		}
		return result;
	}
	
}

double Calculator::string_to_double(string line) {
	char * c_equation;
	double result;
	c_equation = new char [line.size()];
	strcpy (c_equation, line.c_str());
	result = atof(c_equation);
	delete c_equation;
	return result;
}

string Calculator::double_to_string(double number) {
	string result;
	stringstream str;
	str << number;
	result = str.str();
	return result;
}

int Calculator::show_errors() {
	return error_code;
}

string Calculator::reverse_string(string line) {
	string::reverse_iterator it;
	string result;
	for (it = line.rbegin(); it < line.rend(); it++) {
		result += *it;
	}
	return result;
}

int Calculator::find_first_key_operation(size_t * x, int y) {
	int number;
	number = x[0];
	for (int i = 1; i < y; i++) {
		if ((int)number > (int)x[i]) {
			number = x[i];
		}
	}
	return number;
}
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
bool Calculator::check_key_action(string & line, int & place, size_t length) {
	size_t temp;
	if (place < (int)length) {
		if (place == -1) {
			temp = 1;
		}
		else {
			temp = place + 1;
		}
		if (line[temp] == key_actions[0] or line[temp] == key_actions[1] or line[temp] == key_actions[2]) {
			error_code = 103;
			return false;
		}
		else if (line[temp] == key_actions[3]) {
			if (line[place] == key_actions[3]) {
				line.replace(place, 2, "+");
				operation = 2;
			}
			else if (line[place] == key_actions[2]) {
				line.replace(place, 2, "-");
				operation = 3;
			}
		}
	}
	else if (place > 0) {
		temp = place - 1;
		
		if (line[place] == key_actions[3]) {
			if (line[temp] == key_actions[3]) {
				line.replace(place - 1, 2, "+");
				operation = 2;
				place = temp;
			}
			else if (line[temp] == key_actions[2]) {
				line.replace(place - 1, 2, "-");
				operation = 3;
				place = temp;
			}
			else if (line[temp] == key_actions[0] or line[temp] == key_actions[1]) {
				place = temp;
			}
		}
		else {
			if (line[temp] == key_actions[0] or line[temp] == key_actions[1] or line[temp] == key_actions[2]  or line[temp] == key_actions[3]) {
				error_code = 103;
				return false;
			}
		}
	}
	return true;
}

int main() {
	Calculator calc;
	double result;
	int answer;
	string equation = "2*3+6*8+(3+sqrt(25+32/2)*2-sin(25+65*2)/cos(54*8+7))/2-5*sqrt(25-15)/3";
	
	cout << "Do you want to enter your equation? Yes (1) or No (0)." << endl;
	cin >> answer;
	if (answer == 1) {
		cout << "Enter your equation:" << endl;
		cin >> equation;
	}
	
	calc.add_to_equation(equation);
	result = calc.count_equation();
	if (calc.show_errors() > 100) {
		cout << "ERROR: " << calc.show_errors() << endl;
	}
	else if (calc.show_errors() == 0) {
		cout << "Equation: " << equation;
		cout << " = " << result << endl << endl;
		cout << "----------------------------------" << endl << endl;
	}
	
	main();
	
	return 0;
}
Topic archived. No new replies allowed.