basic calculator

Hi guys so I am reading Bjarnes principal and practice for the first time,and I am going over an example he gives in the book I did modify it a little and go un wanted results for some reason when I type the expression in followed by an e to end the expression another input line appears expecting more input from me I then type a random number that doesn't seem to do anything and THEN it prints the result,I wasn't expecting to be prompted to enter another value

is there something I am missing?

note I know this is a terrible idea because I will always get the wrong answer since the addition will be done before the * as Bjarne says in his book.

thanks

enter an expression with an operator
to end type e after expression ie 2 + 2 * 3 e
2 + 2 * 1 e
7 // I HAVE TO TYPE THIS IN
4 // 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
  int main() {

	cout << "enter an expression with an operator" << endl;
	cout << "to end type e after expression ie 2 + 2 * 3 e" << endl;

	int lvalue = 0;
	int rvalue = 0;
	char op;

	cin >> lvalue;
	while (cin >> op) {

		if (!cin) {
			cout << "no second value" << endl;
			return 1;
		} else {

			cin >> rvalue;
		}
		if (op != 'e') {

			switch (op) {

			case '+':
				lvalue += rvalue;
				break;
			case '-':
				lvalue -= rvalue;
				break;
			case '*':
				lvalue *= rvalue;
				break;
			case '/':
				lvalue /= rvalue;
				break;
			default:
				cout << "error" << endl;
			}
		} else {

			cout << lvalue << endl;
			return 0;
		}
	}
}



side question** I still don't understand why that's happening in my first question but a side question is,I fixed the code( kind of ) and lets say when I add 2 + and add nothing after the plus how come this block of code does not get run?

1
2
3
4
5
6
7

if (!cin) {
		cout << "no second value" << endl;
		return 1;
	}





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


#include <iostream>
using namespace std;

int main() {

	cout << "enter an expression with an operator" << endl;
	cout << "to end type e after expression ie 2 + 2 * 3 e" << endl;

	int lvalue = 0;
	int rvalue = 0;
	char op;

	cin >> lvalue;
	while (cin >> op) {
        if(op != 'e'){
        	cin >> rvalue;
        }
		if (!cin) {
			cout << "no second value" << endl;
			return 1;
		}
		if (op != 'e') {

			switch (op) {

			case '+':
				lvalue += rvalue;
				break;
			case '-':
				lvalue -= rvalue;
				break;
			case '*':
				lvalue *= rvalue;
				break;
			case '/':
				lvalue /= rvalue;
				break;
			default:
				cout << "error" << endl;
			}
		} else {

			cout << lvalue << endl;
			return 0;
		}
	}
}

Last edited on
Hello adam2016,

I have not read the book you mentioned, so I do not know what the original code looks like or what you have changed.

I do not think that if (!cin) will work the way you think it should. Since "op" is defined as a "char" input of +, -, *, / or 1, 2, 3 or a, b, c will be accepted and none of this will make "cin" fail, but some of the characters entered will not work with the math. The if statement would work better checking for the correct operator. Also the error message is premature since you have yet to enter an "rvalue".

Based on our example, 2 + 2 * 3, and according to the rules of precedence this should produce the answer of 8, but you program I think would give the answer of 12. Doing your math and storing the answer in the "lvalue" variable is not the best way of doing this.

I will have to run the program to what is happening and better understand what is going on with the program.

For now these are my thoughts just looking at your code. More in a little while.

Hope that helps,

Andy
Hello adam2016,

This has the changes that made the program work. Your original code was waiting for the "rvalue" at the wrong time. Since there is no prompt for the "rvalue" tiy had no idea what you were waiting for. Notice the comments.

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
int main()
{
	std::cout << "enter an expression with an operator" << std::endl;
	std::cout << "to end type e after expression ie 2 + 2 * 3 e" << std::endl;

	int lvalue = 0;
	int rvalue = 0;
	char op;

	std::cin >> lvalue;
	while (std::cin >> op)
	{
                //  May be OK to leave, but seemed to be a problem when I first started.
                //  Does not work right anyway.
		//if (!std::cin)
		//{
		//	std::cout << "no second value" << std::endl;
		//	return 1;
		//}
		//else
		//{
		//}

		if (op != 'e')
		{
			std::cin >> rvalue;  // <--- Moved down.

			switch (op)
			{

			case '+':
				lvalue += rvalue;
				break;
			case '-':
				lvalue -= rvalue;
				break;
			case '*':
				lvalue *= rvalue;
				break;
			case '/':
				lvalue /= rvalue;
				break;
			default:
				std::cout << "error" << std::endl;
			}
		}
		else
		{

			std::cout << lvalue << std::endl;

				return 0;
		}
	}
}


You still have th problem that the math is not done in the right order.

Hope that helps,

Andy
Hi Andy amazing answer much appreciated for the time =)

I'll post the original code from Bjarnes book I must say it is quite confusing and I am no experienced programmer like Bjarne but the code does look quite messy and complicated

the code Andy gave me looks more concise and easier to read

Bjarnes code works but I just don't understand why it does and how it does



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

#include <iostream>
using namespace std;

int main() {

	cout << "please enter an expression ( +,-,*,/) " << endl;
	cout << "add an x to end of expression to end it" << endl;

	int lval = 0;
	int rval;
	char op;
	cin >> lval;
	if(!cin){
		cout << "error no first operand" << endl;
		return 1;
	}

	while(cin >> op){

		if(op!='x'){

	       cin >> rval;
		}

		if(!cin){

			cout << "no second operand" << endl;
			return 1;
		}

			switch (op) {

			case '+':
				lval += rval;
				break;
			case '-':
				lval -= rval;
				break;
			case '*':
				lval *= rval;
				break;
			case '/':
				lval /= rval;
				break;
			default:
				cout << "result" << lval << endl;
				return 0;
			}
	}
	cout << " error :: bad expression" << endl;

}


if!(cin){

cout << "no second operand" << endl;

}

lets say I entered 2 + 2 * 3 x the result turns out to be 12,but I don't know how the code even works after x there is no more data in cin.

how is this possible how does this block of code above not run after we type x? because when we enter x we don't add anything after it so since there is no more input should'nt this block of code run? because (!cin) is true,cin == false (!cin) !cin means if there is no more data in the cin stream which there isn't so why doesn't this statement run

if anybody could break this code down with me and explain whats going on or if I'm thinking wrong please please tell me much appreciated


thanks


I would have expected after 2 + 2 * 3 x were all read in from cin that !cin would be true
so that block of code would be run and it would return 1,

because after x there is no more values in cin it's empty? or it can't read anymore values because there is nothing after x

so how come this block of code doesn't run I tried drawing it out on a piece of paper to see if I was wrong but the paper only confirms what I'm thinking

**edit I think I'm confusing what !cin is checking for I thought that !cin is checking to see if there anything left in the stream or buffer but I think it's actually checking if it's not in an error state thats why it never runs,so how would I check to see if there is anything left in the stream is there a function that checks this?

thanks
Last edited on
Hello adam2016,

Below is Bjarnes's code with a few additions to pause the program before the window closes, at least the way I use it the window closes before I can read what was output, anyway it will give you a chance to see what is output.

I do not think you are understanding how "cin" works. From the keyboard an entry of "2 +2 * 3 x" is stored in the input buffer first. This is why the program works the way it does because it is getting the input to the variables from the buffer not directly from the keyboard.

Now "cin >> lval;" is known as formatted input. Because "lval" is defined as an "int" the input is expecting a number only. If anything other than a number is entered the stream fails and one or more of the state bits of the stream is set. That is where the first if (!cin) comes into use. This happens when you enter something other than a number for "lval". The second comes into use when it receives something other than a number for "rval".

The way the program works is when you enter "2 + 2 * 3 x" from the keyboard this is stored in the input buffer. "cin >> lval" will extract from the buffer the first number up to the first white space and stop. Then in the while condition "cin >> op" extracts the (+, -, * or /) from the buffer up to the next white space then "cin >> rval" extracts up to the next white space and so on until the "\n" is reached leaving the "\n" in the input buffer. This way you keep extracting from the input buffer until "e" or "x" is extracted and the program ends with the "return 0;".

The program works and any length of expression will work, as long as you follow the correct format, until a "e" or "x" is read from the buffer.

Revised code:
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
#include <iostream>
#include <chrono>
#include <thread>

//using namespace std;

int main()
{
	std::cout << "please enter an expression ( +,-,*,/) " << std::endl;
	std::cout << "add an x to end of expression to end it" << std::endl;

	int lval = 0;
	int rval;
	char op;

	std::cin >> lval;

	if (!std::cin)
	{
		std::cout << "error no first operand" << std::endl;
		std::this_thread::sleep_for(std::chrono::seconds(3));  // Requires header files "chrono" and "thread"
		return 1;
	}

	while (std::cin >> op)
	{

		if (op != 'x')
		{

			std::cin >> rval;
		}

		if (!std::cin)
		{

			std::cout << "no second operand" << std::endl;
			std::this_thread::sleep_for(std::chrono::seconds(3));  // Requires header files "chrono" and "thread"
			return 1;
		}

		switch (op)
		{

		case '+':
			lval += rval;
			break;
		case '-':
			lval -= rval;
			break;
		case '*':
			lval *= rval;
			break;
		case '/':
			lval /= rval;
			break;
		default:
			std::cout << "result = " << lval << std::endl;
			std::this_thread::sleep_for(std::chrono::seconds(3));  // Requires header files "chrono" and "thread"
			return 0;
		}
	}  //end while

	std::cout << " error :: bad expression" << std::endl;

	return 0;
}


If anything is still unclear let me know.

Hope that helps,

Andy
that's perfect Andy,completely understand now =)

much appreciated for all the help
Topic archived. No new replies allowed.