Using string with advantages of regular cin?

Hi - I've coded this calculator. In int main() I'm using "e" as a char so I can use cin.putback(e) - which is very crucial to this code! So is there a way to be able to use this with a string ? Since I get errors when I try to use it while e is a string. If not possible, is there a similar code I could use that would work if e was a string?

The reason I want e to be a string is because it allows for more characters (so users can type in "sa" rather than having to type "as" if you've looked that closely into my code) and other things. It would be useful to have e be a string, but at the same time the code won't work without the benefits of the functions not compatible with string. If there's a solution - let me know. 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
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
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
// It's Time To Calculate The Calculations With A Calculator !

#include "stdafx.h"

#include <iostream>
#include <fstream>
#include <string>
#include <cmath>
#include <iomanip>


double a;
double x;
double y;
char z;

int subtract()
{
	a = x - y;
	return a;
}

int add()
{
	a = x + y;
	return a;
}

int divide()
{
	a = x / y;
	return a;
}

int multiply()
{
	a = x * y;
	return a;
}

int power()
{
	a = pow(x, y);
	return a;
}

unsigned long long factorial(double f) //Loops Until int f = 1 
{									//Limit Is 64 Factorial
	//if (f = '.')
	//{
	//	std::cout << '\n' << "Sorry - No Decimal Factorials!" << '\n' << std::endl;
	//	return a = 0;
	//}
	if (f < 0)
	{
		std::cout << '\n' << "Cannot Have A Negative Or Decimal Factorial" << '\n' << std::endl; 
		return a = 0;
	}
	if (f > 20)
	{
		std::cout << '\n' << "Factorial Too Big!" << '\n' << std::endl;
		return a = 0;
	}
	if (f == 1) return a = 1;
	if (f == 0) return a = 1;
	else return a = f * factorial(f - 1);

}


int main()
{
	std::cout << "Press / To Exit." << '\n' 
	<< "Symbols: (+)  (-)  (/)  (* (or) x)  (!)  (^)  (% (Remainder))  (s (SquareRoot))  (as (SquareRoot Previous Value))" 
	<< '\n' << "Use 'a' To Symbolize Previous Value." << '\n' << "----------------------------------------" << '\n';

Equation:
	std::cout << "Type In Equation: ";
	char e;
	std::cin >> e;

	if (e == '/') // Pressing "/" Stops Program 
	{
		std::cout << '\n';
		return 0;
	}

	if (e == 'a') // Input "a" Will Give You You're Previous Answer To Work With
	{
		if (a == 0)
		{
			std::cout << '\n' << "No Previous Value" << '\n' << '\n';
			std::cin.clear();
			std::cin.ignore(std::numeric_limits<int>::max(), '\n');
			goto Equation;
		}
		x = a; 
		std::cin.putback(e);
		std::cin.ignore(10, 'a');
		goto Op; //Since We Already Got Our "x" Value
	}
	if (e == 'A') // Input "A" Will Give You You're Previous Answer To Work With
	{
		if (a == 0)
		{
			std::cout << '\n' << "No Previous Value" << '\n' << '\n';
			std::cin.clear();
			std::cin.ignore(std::numeric_limits<int>::max(), '\n');
			goto Equation;
		}
		x = a;
		std::cin.putback(e);
		std::cin.ignore(10, 'A');
		goto Op; //Since We Already Got Our "x" Value
	}
	if (e == 'sa')
	{
		z = 's';
		if (a == 0)
		{
			std::cout << '\n' << "No Previous Value" << '\n' << '\n';
			std::cin.clear();
			std::cin.ignore(std::numeric_limits<int>::max(), '\n');
			goto Equation;
		}
		x = a;

		goto Operation;
	}
	if (e == 's')
	{
		z = 's';

		std::cin.putback(e);
		std::cin.ignore(10, 's');
		std::cin >> x;
		if (std::cin.fail())
		{
			std::cout << '\n' << "Not A Number" << '\n' << std::endl;
			std::cin.clear();
			std::cin.ignore(std::numeric_limits<int>::max(), '\n'); // Used When Code Returns To Equation To Clear Cin Errors/Clear Cin Values
			goto Equation;
		}
		goto Operation;
	}
	if (e == 'S')
	{
		z = 's';

		std::cin.putback(e);
		std::cin.ignore(10, 'S');
		std::cin >> x;
		if (std::cin.fail())
		{
			std::cout << '\n' << "Not A Number" << '\n' << std::endl;
			std::cin.clear();
			std::cin.ignore(std::numeric_limits<int>::max(), '\n'); // Used When Code Returns To Equation To Clear Cin Errors/Clear Cin Values
			goto Equation;
		}
		goto Operation;
	}
	
		std::cin.putback(e);
	

	std::cin >> x;

	if (std::cin.fail())
	{
		std::cout << '\n' << "Not A Number" << '\n' << std::endl;
		std::cin.clear();
		std::cin.ignore(std::numeric_limits<int>::max(), '\n'); // Used When Code Returns To Equation To Clear Cin Errors/Clear Cin Values
		goto Equation;
	}

	Op:
	std::cin >> z;
	if (z == '!') // To Skip Getting A "y" Value For Factorials
	{
		goto Operation;
	}
	if (z == 's')
	{
		goto Operation;
	}
	std::cin >> y;

	if (std::cin.fail())
	{
		std::cout << '\n' << "Not A Number" << '\n' << std::endl;
		std::cin.clear();
		std::cin.ignore(std::numeric_limits<int>::max(), '\n'); // Used When Code Returns To Equation To Clear Cin Errors/Clear Cin Values
		goto Equation;
	}

	
Operation:
	switch (z)
	{
	case '-':
		subtract();
		std::cout << '\n' << "The Sum Is: " << std::setprecision(7) << a << std::endl;
		break;
	case '+':
		add();
		std::cout << '\n' << "The Sum Is: " << std::setprecision(7) << a << std::endl;
		break;
	case '/':
		if (x == 0 || y == 0)
		{
			std::cout << '\n' << "Not Possible" << std::endl;
			break;
		}
		divide();
		std::cout << '\n' << "The Sum Is: " << std::setprecision(7) << a << std::endl;
		break;
	case '*':
		multiply();
		std::cout << '\n' << "The Sum Is: " << std::setprecision(7) << a << std::endl;
		break;
	case 'x':
		multiply();
		std::cout << '\n' << "The Sum Is: " << std::setprecision(7) << a << std::endl;
		break;
	case '^':
		power();
		std::cout << '\n' << "The Sum Is: " << std::setprecision(7) << a << std::endl;
		break;
	case '%':
		if (x < y)
		{
			std::cout << '\n' << "Not Applicable" << std::endl;
		}
		else
		{	// Won't Work If Not Placed Here. Can't Perform % With Anything But Integers.
			int b = x;
			int c = y;
			a = b % c;
			std::cout << '\n' << "The Remainder is: " << a << std::endl;
		}
		break;
	case '!':
	{
		factorial(x);
		if (a == 0)
		{
			break;
		}
		std::cout << '\n' << "The Factorial Is: " << a << std::endl;
		break;
	}
	case 's':
	{
		a = sqrt(x);
		if (x < 0)
		{
			std::cout << '\n' << "Can't Have A Negative Square Root!" << std::endl;
			break;
		}
		std::cout << '\n' << "The SquareRoot Is: " << a << std::endl;
		break;
	}
	default:
		std::cout << '\n' << "Unknown Operation: '" << z << "'" << '\n' << '\n';
	}

	std::cin.clear();
	std::cin.ignore(std::numeric_limits<int>::max(), '\n');
	
	std::cout << '\n';

	goto Equation;

	return 0;
}
cin.get can only read 1 char at the time. If you want to use string create one and add the characters to it. Then you process the string.
Hello zapshe,

Which program / topic ar we working on?

http://www.cplusplus.com/forum/beginner/233538/
http://www.cplusplus.com/forum/beginner/233593/

Line 79 define "e" as a "std::string".

Lines 82, 88 , 102, 130 and 146 the if statement would be: if (e[0] == '?' note single quotes ('). This way you are comparing a character to a character.

Line 116 since there is more than one character you will need double quotes (") to compare a string to a string. With (sa) in single quotes this should be a compile error.

Hope that helps,

Andy
Hi Handy Andy, I know how to change the if statements to account for the string, but I'm wondering how I'll be able to use cin.putback(e) or some other equivalent code. cin.putback is important in this code, so I can't change e to a string without having some way to use cin.putback or a string function that does the same thing. Any ideas? Thanks!
Hello zapshe,

cin.putback is important in this code

Why? if the code is written right this is not needed.

This is what I did:

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
//  equ short for equation.
//  num1 and num2 replace x and y.
//  ans, which you do not see replaces a.
//  sign replaces z.

std::getline(std::cin, equ);

if (equ[0] != 'e')
{
	try
	{
		num1 = std::stod(equ);
	}
	catch (const std::exception& e)
	{
		//std::cout << "\n Execption: " << e.what() << std::endl;
		num1 = ans;
	}

	pos = equ.find_first_of("+-*/!%^");

	sign = equ[pos];

	if (sign != '!')
		try
	{
		num2 = std::stod(equ.substr(pos + 1));

	}
	catch (const std::exception& e)
	{
		num2 = ans;
	}
}
else
	sign = 'e';

switch (sign)


I have used a try/catch like this before. In the try section a string like "10+5" will use the "stod" function and put the number into a double variable with no problem and will stop at the first non digit character. So when the string looks like "a+5" it caused the try to fail and the catch sets num1 to ans from the previous equation.

This can be expanded to check ans being zero and getting input for num1 and num2.

If you reach the else statement this sets up the switch/case statements to exit the program. With a case statement for 'e'.

I still have a hard time why you feel the need for "cin.putback()". If you break up the formula received from "cin" properly everything you need will be in your variables.

Hope that helps,

Andy
Thanks for code Handy Andy. However, I've never seen try or catch before. I'll make sure to look into those functions. Moreover, I think I found a work around for my particular needs, so thanks anyway !
closed account (E0p9LyTq)
try and catch are used to handle exceptions, exceptional conditions such as a runtime error (dividing by zero for example), so the program doesn't just crash without warning.
http://www.cplusplus.com/doc/tutorial/exceptions/
Also, don't use goto, use loops and function instead. Most of lthe code in lines 77 to 196 could be replaced by one short function, which could be called from each of the cases in the switch.

Functions should be fairly short (say 20 LOC or less), including the main function.

Also, don't have global variables, they can cause awkward problems.

There is also a convention to put declarations of the functions before main, then the main function, then the function definitions. This is so the main function is near the top of the file, which makes it easier to read.

Check for divide by zero, before you do the division. If the type is a double, check if the value is less than some constant precision value. For example if the number is less than say 0.000001, then it is near enough to zero for our purposes.

1
2
3
4
5
6
7
const double Precision = 1e-6;

double a = 1e-7;

if (a < Precision) { // a is near enough to zero
   // print error mesg
}


The output could be a function of it's own, rather than repeatedly writing the same std::cout statement.

Good Luck !!
Thanks FurryGuy for the link and TheIdeasMan for the code and insight. I've heard a lot about not using "goto" - but I don't think they'll cause any trouble for me in this situation.

Also - the global variables have been extremely helpful with this calculator and I'd prefer not to have to re-code it while it's working fine.

I'll also keep in find the keep my functions short, that's good advice for noobie like me - I was typing away into that main function ! However, I feel that I'm in too deep to re-code any of this calculator (The code in the question is already old - my current is 400 lines).

Anyway, [thanks] for the code and lots of good advice TheIdeasMan - I'll have to keep that in mind when coding in the future to avoid bad coding habits !
Last edited on
I've heard a lot about not using "goto" - but I don't think they'll cause any trouble for me in this situation.


Also - the global variables have been extremely helpful with this calculator and I'd prefer not to have to re-code it while it's working fine.


However, I feel that I'm in too deep to re-code any of this calculator (The code in the question is already old - my current is 400 lines).


It's good to see some one suggestion being taken on board, but do you think it might be worth rewriting your calculator code, if it is:

going to be half as long, or less in terms of LOC ;
written properly, not spaghetti code?

Just because it works, doesn't mean it is correct.
This calculator was just something I made so that every time I learned something new I could implement in in the calculator. So it's not really worth re-coding - plus I may have to deal with messy code one day, so this may be good experience. Once I'm "done" learning, I may go back and re-code the calculator just to regain more experience and teach myself how to do things differently. But for now - while the calculator works I don't want to go out of my way to redo it.

Sorry if it seems like I'm accepting a bad way of coding and not caring - It's just that this calculator isn't important enough for me to care that much. However, I am taking your advice seriously and will keep it in mind when coding in the future. Thanks TheIdeasMan!
Topic archived. No new replies allowed.