Different input results using cin extractor and relational operators.

I am using VS2K12 version 4.5.50709.

I am working Prata's C++ Primer 6ed. The exercise sequence of Listing 6.9 through Listing 6.11 involved using a switch statement with integer input (switch.cpp: 6.9), character input (switchchar.cpp: 6.10), and using integer input with enum (enum.cpp: 6.11). The main function of each was similar, especially in the usage of the input variable used by cin ("code" in the code provided below).

With switch.cpp, it was shown that entering a character caused the loop to cycle continuously. This was because the "cin >> choice" call failed to read the character into the int (choice) variable. The 'cin.fail() test followed by cin.clear().get() was added to switch.cpp to prevent the bad read from producing the loop spin.

However, in the original version of enum.cpp (below), which also uses integer input, if I input an 'm', the response is:

Enter color code (0-6): m
Bye!Press any key to continue . . .

In other words, with character input the int based read operation apparently did not fail. The main methods were very similar, but I noticed that switch.cpp used the "!=" operator in the while loop's test expression. So I tried it in enum.cpp and it is commented out in the code below. I found that with that code in place the inability to handle character input was present. When a character is input the failing response is:

Enter color code (0-6): Always include default case.
Enter color code (0-6): Always include default case.
Enter color code (0-6): Always include default case.
...
...

I assume this is a VS2K12 quirk, but I will likely try something like gcc at work tomorrow. I think it would be easy to chase this though the iostream code, for someone who has already been there. But it is going on 1AM, and I am not certain it would be time well spent (i.e. how often do you "really" need to debug iostream code?). I did use the debugger and see that (I believe) _OK is set to false. If I do not get a response I will likely look into it further this weekend. But if anyone has noticed this issue I would appreciated any info they have gathered on it.


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
// enum.cpp -- Listing 6.11 (PG 279): Using enum (091513)

#include <iostream>

// const int red = 0, orange = 1, ....
enum {red, orange, yellow, green, blue, violet, indigo};

int main() {
	using namespace std;

	int code;

	cout << "Enter color code (0-6): ";		// 1: Prompt

	cin >> code;					// 2: Read input
	while (code >= red && code <= indigo) {
	// while (code != red) {

		switch (code) {
			case red:	cout << "Her lips were red.\n"; break;
			case orange:	cout << "Her hair was orange.\n"; break;
			case yellow:	cout << "Her shows were yellow.\n"; break;
			case green:	cout << "Her nails were green.\n"; break;
			case blue:	cout << "Her sweatsuite was blue.\n"; break;
			case violet:	cout << "Her eyes were violet.\n"; break;
			case indigo:	cout << "Her mood was indigl.\n"; break;
			default:	cout << "Always include default case.\n";
		}
		cout << "Enter color code (0-6): ";		// 1: Prompt
		cin >> code;					// 2: Read input

	}
	cout << "Bye!";
	return 0;
}
That's because, the switch case statement is made only for integers ( as far as I know).
Do you mean something like this?
r=red, o=orange and so on.To exit press anything but a letter.
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
#include <iostream>

// const int red = 0, orange = 1, ....
enum {r=114, o=111, y=121, g=103, b=98, v=119, i=105};

int main() {
	using namespace std;

	char code;

	cout << "Enter color code (0-6): ";		// 1: Prompt

	cin >> code;					// 2: Read input
	while (code >= 97 && code <= 122) {
	// while (code != red) {

		switch (code) {
			case r:	cout << "Her lips were red.\n"; break;
			case o:	cout << "Her hair was orange.\n"; break;
			case y:	cout << "Her shows were yellow.\n"; break;
			case g:	cout << "Her nails were green.\n"; break;
			case b:	cout << "Her sweatsuite was blue.\n"; break;
			case v:	cout << "Her eyes were violet.\n"; break;
			case i:	cout << "Her mood was indigl.\n"; break;
			default:	cout << "Always include default case.\n";
		}
		cout << "Enter color code (0-6): ";		// 1: Prompt
		cin >> code;					// 2: Read input

	}
	cout << "Bye!";
	return 0;
}
I mean in its current state it does not fail (i.e. endless loop) on character input. But if I comment out "// while (code >= red && code <= indigo) {" and un-comment "while (code != red) {", it does fail (i.e. endless loop) on character input. I did confirm that in the failing mode the fail flag is being set.

So the issue is, why does it NOT FAIL in its current state, which uses the "while (code >= red && code <= indigo) {" test expression. This might have been lost in my wordy initial update.

As an aside, I found that if I place a comment within the while loop's test expression, I receive a 'cout is ambiguous' indication with cout underlined in red. The code compiles just fine. To clear the condition I need to restart VS2K12. So I am planning to install all available updates, which is something I avoid unless absolutely necessary. I will have an update sometime tonight.
closed account (Dy7SLyTq)
could have something to do with comparing code against ascii values and then implicitly cast to match an enumerated value? (does it cast to match the enum?)
If you input a character into an integer the integer return 0. enum red=0.
So while(0 != 0) it is false so the loop ends.
The same if you input 0 (for red color).
Last edited on
On line 11, int code; the variable code is not initialized. Consequently there is a garbage value in code. The attempt to read a character into code will fail, leaving code unchanged (still with a garbage value).

The while loop never executes because the garbage value in code is not in the range 0-6, so program execution jumps to line 31 and you output
Bye!
@Alrededor the variable code is initialized on line 15 by cin>>code;before the loop begins so there is no garbage, try this after inputting a character.

1
2
3
4
5
6
int code;//line 11

	cout << "Enter color code (0-6): ";		// 1: Prompt

	cin >> code;
        cout<<code;
Chriscpp-

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>

int main() {
    using namespace std;

	int code;
    
    cout << code << endl;

	cin >> code;					// 2: Read input
    
    cout << endl << code << endl;
    return 0;
}


Running this on one of the online compilers and entering the character m shows that the uninitialized value of code is zero, but I do not believe there is any requirement for the compiler to initialize to zero.

Now try the following with code initialized to 100 and input a character and the value of code is not changed to zero by the cin statement but remains 100.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>

int main() {
    using namespace std;

	int code = 100;
    
    cout << code << endl;

	cin >> code;					// 2: Read input
    
    cout << endl << code << endl;
    return 0;
}

Last edited on
┬┐which compiler are you using?
clang and gcc output `0' in a bad reading.
I apologize for the confusion I caused. The issue is the code provided in my original post DOES NOT FAIL with the endless loop condition. Such an issue occurs when you (for example) try to use cin to read a char into an int variable. I do not believe casting is involved in the conversion iostream performs and I might review it just to see how it works. However, this much time should not be spent on a cin read issue. I just assumed this was an issue others had run into.

I will not post again until I install VS2K12 fixes, which may take a day or two. For anyone who is confused, if you understand how cin should work (and fail) and understand why cin.fail() would return the value true, my original post should make sense, but maybe not. I do want to thank everyone for their responses.

> but I do not believe there is any requirement for the compiler to initialize to zero.

If extraction fails (e.g. if a letter was entered where a digit is expected), value is left unmodified and failbit is set. (until C++11)

If extraction fails, zero is written to value and failbit is set. If extraction results in the value too large or too small to fit in value, std::numeric_limits<T>::max() or std::numeric_limits<T>::min() is written and failbit flag is set. (sinceC++11)
http://en.cppreference.com/w/cpp/io/basic_istream/operator_gtgt
Last edited on
oops, we flipped the since/until on that one. C++03 forbids modification, C++11 requires 0 or min/max. Fixed
Last edited on
Ok, Thanks. Fixing my post too, lest it mislead someone.
When I attempted to install fixes for VS2K12 I received a warning, and I believe the KB article indicated recovery might require a reinstall, which I am not prepared to do. So for now the reason for the original issue will need to go unanswered.

For anyone who is still confused, the issue is as simple as this. When reading numeric input (e.g. from keyboard), attempting to input a character should result in a cin read failure. With the following line of code in place (see initial post), the failure did not occur:

while (code >= red && code <= indigo) {

However, with the above line commented out at the following line of code in place, the read failure did occur:

while (code != red) {

So the failure is the expected result. My question was why the first line of code did not produce the failure, and it is likely is issue with VS2K12 as there is nothing in C++11 that could justify this.

I plan to save this thread and look into this as soon as I have some "free time".

Thanks for your responses.






Topic archived. No new replies allowed.