Sign in to follow this  
otreum

Avoiding a infinite loop caused by non integer input.

Recommended Posts

I am going through the book called "Beginning C++ through games development", i'm up to the end of chapter 8, trying to do the exercises and have come across a niggling problem I keep coming across in nearly all of the examples that ask for user input. The problem is that when a player enters something other than what the user input is asking for, the program enters an infinite loop. The user is supposed to enter an integer value when prompted. This works perfectly fine IF the user enters anything from 0 to 4. However the program enters an infinite loop if the user inputs a value that is NOT AN INTEGER. I have tried to reset the value of 'choice' to a value that is not between 0 and 4, but IS an integer at the end of the loop and/or the beginning, however the compiler just avoids this all together, and repeats the DO loop forever. I also ran the debugger in microsoft visual studio, and I noticed that after the player enters a choice that is a letter or something other than a number between 0 and 4, the value of choice becomes some long negative integer (i'm guessing due to the compiler converting characters and strings to integer?), it then skips over the switch statement (because the value does not equal anything from the switch statement), outputs the message saying the value is not valid, repeats the main loop again, but instead of getting user input, it seems to retain the previous value rather than stop at the user input and allow for a new input. So after all that long winded text, is this a simple problem for a beginner, or is it a little more complex than I think? I swear i've fixed something like this before, but this has me baffled. And what would I need to do to fix this. Also, is it possible to use a tag other than [code] which shows colour coding and so on? Just like in microsoft visual studio. [Yes; the other tag is [source], and I have made the necessary edits for you. --Zahlman] Thanks in advance, here is the following code i'm talking about.

//Critter Caretaker
//Simulates caring for a virtual pet

#include<iostream>

using namespace std;

class Critter
{
public:
	Critter(int hunger = 0, int boredom = 0);
	void talk();
	void eat(int food = 4);
	void play(int fun = 4);
	void stats();

private:
	int m_hunger;
	int m_boredom;

	int GetMood() const;
	void PassTime(int time = 1);
};

Critter::Critter(int hunger, int boredom):
m_hunger(hunger),
m_boredom(boredom)
{}

inline int Critter::GetMood() const
{
	return (m_hunger + m_boredom);
}

void Critter::PassTime(int time)
{
	m_hunger += time;
	m_boredom += time;
}

void Critter::talk()
{
	cout << "I'm a critter and I feel ";
	int mood = GetMood();
	if (mood > 15)
		cout << "mad.\n";

	else if (mood > 10)
		cout << "frustrated.\n";
	else if (mood > 5)
		cout << "okay\n";
	else
		cout << "HAPPY! :D \n";
	PassTime();
}

void Critter::eat(int food)
{
	cout << "Brruuppp\n";
	m_hunger -= food;
	if (m_hunger < 0)
		m_hunger = 0;
	PassTime();
}

void Critter::play(int fun)
{
	cout << "WHEEEE! THIS IS FUN!\n";
	m_boredom -= fun;
	if (m_boredom < 0)
		m_boredom = 0;
	PassTime();
}

void Critter::stats()
{
	cout << "Creature's Happiness level is: ";
	cout << Critter::GetMood() << "\n";
	cout << "Creature's Hunger level is: \n";
	cout << Critter::m_hunger << "\n";
	cout << "Creature's Boredom level is: \n";
	cout << Critter::m_boredom << "\n";
}

int main()
{
	Critter crit;
	crit.talk();
	int choice;
	
	do
	{
		
		cout << "\nCritter Caretaker\n\n";
		cout << "0 - QUIT\n";
		cout << "1 - LISTEN TO YOUR CRITTER\n";
		cout << "2 - FEED YOUR CRITTER\n";
		cout << "3 - PLAY WITH YOUR CRITTER\n\n";

		cout << "(DEVELOPERS MENU)\n";
		cout << "4 - (LIST CREATURES STATISTICS)\n";

		cout << "Please type a number to choose an action\n";
		cout << "Choice: ";
		cin >> choice;
		
		switch (choice)
		{

		case 0:
				cout << "Good-bye.\n";
				break;
		case 1:
				crit.talk();
				break;
		case 2:
				crit.eat();
				break;
		case 3: 
				crit.play();
				break;
		case 4:
				crit.stats();
				break;
		default:
			cout << "\nSorry, but " << choice << " is not a valid choice.\n";
			}
		
	}while(choice != 0);
	return 0;
		}


[Edited by - Zahlman on February 22, 2010 2:18:31 PM]

Share this post


Link to post
Share on other sites
Add choice = 0 inside the default case of the switch:


default:
cout << "\nSorry, but " << choice << " is not a valid choice.\n";
choice = 0;


You can use source tags (just like the code tags, except using source instead of code in the tag) to get the color coding.

Edit - mattd has a much better answer

Share this post


Link to post
Share on other sites
When the user enters a line of text that cin (or any other istream) can't convert to the required type (int), cin (or the other istream) keeps the line of text in its stream buffer, and sets its fail flag bit.

You're meant to check whether the extraction (via operator >>) actually succeeded or not, and if not, clear the fail flag, read in and ignore the line entered, and retry.

Like this:


cout << "Choice: ";

if(!(cin >> choice)) // check if extraction failed, it returns a bool
{
cin.clear(); // reset error flags
getline(cin, string()); // ignore the line entered

cout << "Please enter a number.\n"; // complain

continue; // retry
}

Share this post


Link to post
Share on other sites
What mattd kind of makes sense, but i'd like to confirm that I understand it.

The way I read that code is it checks to see if the input is not an integer (choice)?

Then goes through a loop that first clears the input cin.clear() , which also clears those "flags" (could you please explain these? I'm guessing these "flags" basically work like a bunch of check boxes?).

Then the next line getline(cin, string()) I'm not too sure about. I think i've only seen this used once. Could you please explain what this line does in more detail?

I had a quick read in my other books at what getline is, and still i'm not sure how it ties into what you've written. You say it "ignores" the line entered. Is this because it gets the line in the input (even if it is just one character) stores it, then when getline reaches the end of the input value, it discards whatever was in input?....or am I just talking gibberish? :S

Sorry if these questions seem stupid. But I believe the the only stupid question is the sensible one that is not asked. If I don't ask, I can't really learn.

Share this post


Link to post
Share on other sites
Quote:
Original post by otreum
What mattd kind of makes sense, but i'd like to confirm that I understand it.

The way I read that code is it checks to see if the input is not an integer (choice)?

Right. It checks to see if a value couldn't be extracted from cin to choice (because it couldn't convert a line containing alphabetical characters to a number).

Quote:
Then goes through a loop..

Not a loop, just a regular statement block.

Quote:
..that first clears the input cin.clear() , which also clears those "flags" (could you please explain these? I'm guessing these "flags" basically work like a bunch of check boxes?).

clear only clears the flags. You can just think of flags as boolean values - have you read about those yet?

Quote:
Then the next line getline(cin, string()) I'm not too sure about. I think i've only seen this used once. Could you please explain what this line does in more detail?

I had a quick read in my other books at what getline is, and still i'm not sure how it ties into what you've written. You say it "ignores" the line entered. Is this because it gets the line in the input (even if it is just one character) stores it, then when getline reaches the end of the input value, it discards whatever was in input?....or am I just talking gibberish? :S

You're not far off.

You'd normally use getline like this, to read in a line from a stream:
string line;
getline(stream, line); // read from stream to line

However, we use:

getline(stream, string())

"string()" constructs a new string variable, and getline dutifully stores a line from the stream into it. The trick is that the string() value is just an unnamed temporary - so yes, it disappears right after getline is finished.

You could just use:
string ignored;
getline(cin, ignored);

if the temporary value thing isn't making sense right now.

Quote:
But I believe the the only stupid question is the sensible one that is not asked.

Too right.

Share this post


Link to post
Share on other sites
Quote:
Original post by mattd
However, we use:

getline(stream, string())

This has two problems. One, it isn't legal C++. A temporary can't be bound to a non-const reference. Your compiler may allow it as a non-standard extension, but on most compilers this will get rejected. Two, if you want to ignore what's in the buffer, istream has a member function for that: ignore().

Share this post


Link to post
Share on other sites
For simple interactive programs like this, I recommend that you always read the standard input a line at a time (with std::getline), and then use the standard library class std::stringstream to re-parse that line of input. This makes it easier to ignore errors (you don't have to worry about resetting flags on std::cin, because they will be set on your temporary stringstream object instead, and you can just go through the loop again and it will be automatically thrown away and re-created with the next line of input) and to keep synchronized with the input (there is never any "left-over" data to ignore, because it's thrown away with the stringstream).


// std::stringstream comes from the library header <sstream>.

int main() {
Critter crit;
crit.talk();
int choice;

do
{
cout << "\nCritter Caretaker\n\n";
cout << "0 - QUIT\n";
cout << "1 - LISTEN TO YOUR CRITTER\n";
cout << "2 - FEED YOUR CRITTER\n";
cout << "3 - PLAY WITH YOUR CRITTER\n\n";

cout << "(DEVELOPERS MENU)\n";
cout << "4 - (LIST CREATURES STATISTICS)\n";

cout << "Please type a number to choose an action\n";
cout << "Choice: ";
string line;
getline(cin, line);
// We set 'choice' to an invalid value first. That way,
// if the input is garbage, nothing is read in, so it's still
// invalid, and the default case of the switch is triggered.
choice = -1;
stringstream parser(line);
parser >> choice;
// If you want, you can do additional checking that there is
// no extra text at the end of the line, e.g. "76 trombones":
// char c;
// if (parser >> c) { choice = -1; }
// That way lets the user put spaces and tabs at the end, which
// I think is reasonable. If you want to be even stricter, try
// using parser.get().

switch (choice)
{

case 0:
cout << "Good-bye.\n";
break;
case 1:
crit.talk();
break;
case 2:
crit.eat();
break;
case 3:
crit.play();
break;
case 4:
crit.stats();
break;
default:
// Notice the change here; we want the error message
// to reflect what the user actually typed.
cout << "\nSorry, but " << line << " is not a valid choice.\n";
}
} while(choice != 0);
}



As an exercise, pull out the part of the code that gets the number from the user, and make it into a function.

Share this post


Link to post
Share on other sites
Thanks for the responses again, I'm looking at Zahlmans response in particular, and TRYING to figure out how it works, but I seem to be stuck at a brick wall.

This morning I spent a good 1 and a half hours reading that code you posted and looking at my books to see what stringstream did and looking at what parser did, but I didn't find anything on parsers, I only found information on the stringstream, which now to my knowledge can read or write to a string.

I also ran the debugger on the code you wrote to try and understand it better, and I have learnt a bit of how it works, but I get stuck.

I'm going to write down what I think those few lines of code are doing based on what I learned from the debugger.

1. Creates a string variable called line. This will serve as a temporary value holder.

2. Getline reads/gets the user input and stores/writes it to 'line'.

3. THIS IS WHERE I HIT A BUMP.
Choice is then set to a non-valid value. So that if the string in 'line' is not an integer, then choice will go to the default arguement in the switch statement.
(But i'm stuck wondering how the compiler knows to not change the value of choice if the user input for line is something like 'h' or 'bobs your uncle')

4. THIS IS WHERE I HIT A BRICK WALL.

stringstream parser(line);
parser >> choice;

I really don't understand what a parser is, and I vaguely understand what stringstream is, but haven't studied anything about stringstream just yet, i've only found it through the glossary of C++ primer this morning.
What I did study of stringstream, I didn't fully understand.

I had a look online for what a parser is in C++ and it looks like it could require a really complicated explanation, however for this example, perhaps you could explain the purpose of parser in these lines of code and in the extra code below that says:

[code]
char c;
if (parser >> c)
{
choice = -1;
}
[code]


I feel a bit stupid for asking all of this, but i'd like to try and understand this at least a little bit before I move on to the next chapter, even though the book doesn't require that I know this stuff just yet.

Thankyou in advance for any help provided. I'm sorry if i've missed something, i've just spent a few hours trying to figure out what to write in this post while at the same time understanding new things about the code while I was writing here, so i'm just going to leave the post at that and if I need to ask anymore questions, I'll be sure to ask ;)

Share this post


Link to post
Share on other sites
A variable of type [b]stringstream[b/] can be used exactly like cin except for two differences. First, it will read data from an internal string while cin reads data from a keyboard. Second, stringstream can be destroyed when you are done using it while cin will not be destroyed until after the end of main(). Both of these differences can make stringstream more useful for converting text to an integer than cin.

The problem is users are really bad at entering in data correctly for a computer to understand. If you look at *any* online form to enter data you will see that each box only gets *one* type of information. You never see a box that let's people type their entire address, just parts of it in each box. One for the name (with the name split up between first/last), street name/number, another for city, another for state, then another for zip code. Why not one box like this?
Sherlock Holmes
221B Baker Street
London, England
Because being dumb a user might forget to put their name. Put the address above the name. Combine all lines into one line. And so on. Much easier to just read one line at a time.

Using stringstream like this is to accomplish that individual text box data entry in the console. You want to get an integer, but what's to stop someone from typing something you don't want. Like "21 years, 4 months, 3 days" instead of just "21" when you ask for the user's age. If you read in just one word you'll read 21, but then the input will still contain "years, 4 months, 3 days" which will screw up further data. You could just tell cin to ignore any other data saved in its internal buffer. Or, you can read an entire line of data at once clearing the buffer and then convert the line of data to whatever you want it to be. Doing it this way has the advantage of being incredibly consistent from a programming perspective. Sometimes you want a user to type "21 years, 4 months, 3 days" with all spaces. In that case you need to use getline. So why not always use getline?

Ok, so you have the line of input. It is all text at this point and we don't know what the heck is inside of it. But what we do know is we want to convert whatever is inside to an integer if possible. Zahlman went with "extract the first word from the string 'line' by letting stringstream convert it to an integer. If that fails, ignore the rest of the string by just letting stringstream get destroyed by going out of scope and repeat the process until the conversion works.

As for your question "what is a parser?" Doing this is parsing, basically.

Share this post


Link to post
Share on other sites
Firstly, thankyou Zahlman for giving me that little challenge at the end of your post, that's the kind of stuff that I believe makes a programmers knowledge that little bit better.

I first had some troubles and it was because of something SO stupid, SO simple and I really cannot believe I made the mistake and spent so long trying to fix it.

I had my function worked out correctly and tried so many methods to try and get it working, even though I didnt have to, but in the end, all my problems were caused by typing out a declaration...not a function call.

I put 'string' infront of the function call, which ultimately skipped the function all together resulting in an infinite loop.

Here is my new code with the function. If you think it needs any improvements please let me know, and maybe let me know why. (I think that MAYBE I did more than I needed to....maybe).


//Critter Caretaker
//Simulates caring for a virtual pet

#include<iostream>
#include<string>
#include<sstream>

using namespace std;

class Critter
{
public:
Critter(int hunger = 0, int boredom = 0);
void talk();
void eat(int food = 4);
void play(int fun = 4);
void stats();

private:
int m_hunger;
int m_boredom;

int GetMood() const;
void PassTime(int time = 1);
};

Critter::Critter(int hunger, int boredom):
m_hunger(hunger),
m_boredom(boredom)
{}

inline int Critter::GetMood() const
{
return (m_hunger + m_boredom);
}

void Critter::PassTime(int time)
{
m_hunger += time;
m_boredom += time;
}

void Critter::talk()
{
cout << "I'm a critter and I feel ";
int mood = GetMood();
if (mood > 15)
cout << "mad.\n";

else if (mood > 10)
cout << "frustrated.\n";
else if (mood > 5)
cout << "okay\n";
else
cout << "HAPPY! :D \n";
PassTime();
}

void Critter::eat(int food)
{
cout << "Brruuppp\n";
m_hunger -= food;
if (m_hunger < 0)
m_hunger = 0;
PassTime();
}

void Critter::play(int fun)
{
cout << "WHEEEE! THIS IS FUN!\n";
m_boredom -= fun;
if (m_boredom < 0)
m_boredom = 0;
PassTime();
}

void Critter::stats()
{
cout << "Creature's Happiness level is: ";
cout << Critter::GetMood() << "\n";
cout << "Creature's Hunger level is: \n";
cout << Critter::m_hunger << "\n";
cout << "Creature's Boredom level is: \n";
cout << Critter::m_boredom << "\n";
}

string getchoice(string& choice);

int main()
{
Critter crit;
crit.talk();
int choice;

do
{

cout << "\nCritter Caretaker\n\n";
cout << "0 - QUIT\n";
cout << "1 - LISTEN TO YOUR CRITTER\n";
cout << "2 - FEED YOUR CRITTER\n";
cout << "3 - PLAY WITH YOUR CRITTER\n\n";

cout << "(DEVELOPERS MENU)\n";
cout << "4 - (LIST CREATURES STATISTICS)\n";

cout << "Please type a number to choose an action\n";
cout << "Choice: ";
string line;
getchoice(line);
// We set 'choice' to an invalid value first. That way,
// if the input is garbage, nothing is read in, so it's still
// invalid, and the default case of the switch is triggered.
choice = -1;
stringstream parser(line);
parser >> choice;
// If you want, you can do additional checking that there is
// no extra text at the end of the line, e.g. "76 trombones":
char c;
if (parser >> c)
{
choice = -1;
}
// That way lets the user put spaces and tabs at the end, which
// I think is reasonable. If you want to be even stricter, try
// using parser.get().


switch (choice)
{

case 0:
cout << "Good-bye.\n";
break;
case 1:
crit.talk();
break;
case 2:
crit.eat();
break;
case 3:
crit.play();
break;
case 4:
crit.stats();
break;
case 5:
cout << "ERROR!\n";
break;
default:
cout << "\nSorry, but " << line << " is not a valid choice.\n";

}



}while(choice != 0);
return 0;
}

string getchoice(string& choice)
{
string line;
getline(cin, line);
choice = line;

return choice;
}



I have some questions for you again.

- Say for example I type 546 as my choice.
Is parser >> choice; getting the value of line (546) and seeing if it is an integer value (choice)? I'm still not entirely sure how the parser works.

----------------------

Nobodynews, thankyou for your explanation, unfortunately though, i'm still a little lost. So i'm going to ask a few more questions about your explanation which might help me understand your post a bit better.

- Firstly, what is the difference between an "internal string" and "data from a keyboard"?

- You said "Both of these differences can make stringstream more useful for converting text to an integer than cin". What is the purpose of converting text into an integer?

I probably could ask more, but i'll just leave it at that for now.

Thankyou again Nobodynews for your explanation, i'm sorry that I STILL could not make sense of it all though. I'm sure I will soon enough lol.

Share this post


Link to post
Share on other sites
Quote:
Original post by otreum
- Firstly, what is the difference between an "internal string" and "data from a keyboard"?
That was bad terminology on my part. By internal string I meant that stringstream contains a hidden member that stores string data. That data is supplied by you passing in a string. That string could come from any other source. On the other hand, cin also has a method of storing string data, except this string data is supplied from what was typed on the keyboard. cin only gets its string data from the keyboard.

Quote:
- You said "Both of these differences can make stringstream more useful for converting text to an integer than cin". What is the purpose of converting text into an integer?
This might be where some of your confusion comes from. When you do "cin >> choice;" cin takes text from the keyboard and converts it to whatever type of variable you made 'choice'. If choice is an int (which in your case it is) then cin will take the text it took from the keyboard try to convert it to an int. stringstream can also take a string of characters and try to convert it to an int, except it can do it with any string supplied to it and not just from the keyboard.

The point is to separate what are really two different activities. Reading text from the keyboard and converting that text to the type of variable you want.

Share this post


Link to post
Share on other sites
Uh oh, confused again! But I will keep trying to understand...at least until you give up.

Ok...so, stringstream CAN get data from the input on the keyboard, ASWELL as any other source, such as a default value of a variable?

Where as cin can ONLY get input from the keyboard (unless I do an operator overload on cin)?

------------------

Getting back to the conversion topic again.

When I input something like "H" into choice, and I then output choice, does it output that strange negative number (-85372395 etc) because the compiler is trying to convert a character into an integer?

(more questions to come when my brain doesn't feel like it's falling apart from trying to understand this stuff aswell as something like operator overloading).

Thanks :)

Share this post


Link to post
Share on other sites
Quote:
Original post by otreum
1. Creates a string variable called line. This will serve as a temporary value holder.

2. Getline reads/gets the user input and stores/writes it to 'line'.


Yes.

Quote:

3. THIS IS WHERE I HIT A BUMP.
Choice is then set to a non-valid value. So that if the string in 'line' is not an integer, then choice will go to the default arguement in the switch statement.
(But i'm stuck wondering how the compiler knows to not change the value of choice if the user input for line is something like 'h' or 'bobs your uncle')


First off, "the compiler" doesn't "change" anything here; it produces a program. The program then has the "knowledge" of whether or not to change the value.

It works, briefly, because of how the action of reading is described, using the operator>>. Basically, you are calling a function that has already been set up to do exactly that.

Quote:

4. THIS IS WHERE I HIT A BRICK WALL.

stringstream parser(line);
parser >> choice;

I really don't understand what a parser is

[/quote]

Then look up the word "parser" in a dictionary, or with Google, or something.

But that's not relevant. You know how the line "string line;" tells you that you are declaring a variable called 'line' of type 'string'? And "int x;" is declaring a variable called 'x' of type 'int'? And how "Watermelon my_melon;", a variable called 'my_melon' of type 'Watermelon'?

OK, so we haven't defined the type Watermelon, but that's the point: there is nothing special about the words 'string' or 'int'. They are names of types.

Similarly, 'stringstream' names a type that is defined in the <sstream> header. Thus, 'stringstream parser(line);' is creating a variable of type 'parser' which is of type 'stringstream'.

The only part that's unfamiliar to you here at this point is the '(line)' bit. This is a parameter for the stringstream constructor. You've heard of constructors, right?

I called the variable 'parser' because I am using it to parse the input. The word 'parse' is a perfectly ordinary English word that is used by non-programmers, by the way. (Just, perhaps, more-educated-than-average non-programmers.) You can look it up in an ordinary English dictionary.

Quote:


char c;
if (parser >> c) {
choice = -1;
}



You know std::cin? That thing you use to read the user input? It's a stream. When you write something like '{variable of stream type here} >> {some other variable here}', you are requesting to read from the stream's data "into" the other variable. Specifically, the stream data is treated as text, and the stream looks at whatever data is at the beginning of the stream, and tries to interpret it as a human-readable representation of a value that can fit in the other variable.

So if you read into an int, it looks for text that represents digits, and converts the resulting base-10 number into something that will fit into the variable. It goes one character at a time and looks at what symbol they represent.

In the first stage, it will just skip past any spaces, tabs or newlines, because those are "invisible" and not really relevant to human-readable formatted data.

Then it looks at characters one by one, to see if they represent digits - i.e., the symbols '0' through '9'.

If the first symbol it encounters isn't a digit, then the data obviously isn't an integer. So it gives up: it leaves the destination variable alone, leaves the stream data alone (so that you can try reading it into another kind of variable, or doing something else), and it marks itself as having encountered an error (so that you can check).

When you wrap that whole process with an 'if ()', you are basically checking whether such an error occurred. There is a bunch of cleverness that the standard library does for you in order to make that work.

So, the above code uses the same principles, except that:

1) We are reading from a stringstream, which is also a kind of stream, but which uses a string as its data source. This means there's another way for reading to fail: we can run out of data.

2) We are reading into a 'char'. This means that any symbol will work, and we will only ever read one symbol - but we still skip whitespace before looking for the symbol to read.

So what the code above does is: starting at the current position in the string (which is just after having read a number), we skip whitespace, and then try to read any symbol. If we succeed at this, then that means the string was not empty beyond the number, i.e. it had some garbage text after the number. So then we enter the if-block and set choice to -1, to signal "I am not happy with this input; it started with a number, but then there was other stuff after the number".

Share this post


Link to post
Share on other sites
Quote:
Original post by otreum
Uh oh, confused again! But I will keep trying to understand...at least until you give up.

Ok...so, stringstream CAN get data from the input on the keyboard, ASWELL as any other source, such as a default value of a variable?


A stringstream gets its data from one place: the string that you put into it.

But you can get that string from anywhere.

Quote:
Where as cin can ONLY get input from the keyboard


std::cin gets its input from the "standard input" to your program.

When you run your program from the console, there are three programs involved: your program, the console, and the operating system. The operating system reads the keyboard and translates key-presses into characters, which it then passes to the console. The console does some more translation (for example, when it sees a "backspace" character, it cancels that off against the previous character; and it builds up text a line at a time in a buffer), and then, normally, feeds that data to the standard input of your program. However, when you run the program, you can instead tell the console to open a file, and use the contents of the file to supply the standard input for your program. (Similarly, you can tell it to put the standard output from your program into a file, instead of displaying the text in the console window.)

Operator overloading is not relevant to this. The purpose of operator overloading, in this context, is to tell the stream classes how to interpret text as an instance of your own class, or how to represent an instance of your own class as text.

Quote:
When I input something like "H" into choice, and I then output choice, does it output that strange negative number (-85372395 etc) because the compiler is trying to convert a character into an integer?


No. It outputs "that strange number" because that's the value that 'choice' already had before the attempt at input. The attempt at input failed, so the variable was not changed. That's part of how the stream input works.

A variable in C++ always has a value. There is no special state for the 'choice' variable that represents "nothing was ever put here". The program reserves some bytes in memory to represent the variable, and that's it.

For primitive types like ints, if you didn't assign anything, then whatever happened to be in that chunk of memory ahead of time gets used.

For objects (instances of classes or structs), some kind of constructor normally gets called when you declare the variable. This is responsible for initializing the variable with an initial value. You can initialize ints, too: 'int foo = 0;' initializes the variable. Conceptually, it is different from 'int foo; foo = 0;' - although not in a way that you can actually observe in the final running program.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this