Program won't quit if user enters -1 while using return 0; - c++

Here's one of the return 0; sections I have in my main() function:
cout << "Would you like to remove a Pokemon? (Y/N): ";
cin >> removePokemonChoice;
cin.ignore(5, '\n');
if (toupper(removePokemonChoice) == 'Y')
{
deletePokemon();
cout << "New list:" << endl;
displayPokemon();
}
if (removePokemonChoice == -1)
return 0;
currently, it won't exit out of the program if the user enters -1. I can't use an else statement because I want the program to loop (there's a similar question after this bit that I want to come after) until -1 is entered.

Your program asks "(Y/N)" so I suppose removePokemonChoice is a char type... it is strange to expect -1 value from char data. By the way "-1" need 2 characters, so it must be string :-)

Think of it this way:
You're writing a program that asks you whether or not you want to remove a Pokemon. Normally, like in the actual game itself when Prof. Oak prompts you with a confirmation of do you want Charmander (and the answer is yes, you always go with the fire type, no exceptions). The choices the game will always give you is "Yes" or "No".
Would you ask a yes/no question and expect a numerical answer back? While it is true the compiler converts and does numerical stuff in the background, what you really should be thinking about is, is it intuitive to the user?

Related

Proper use of EOF (can it be used multiple times in a program?)

In my intro to programming course (c++), the instructor told us to:
"Write a program that inputs an unspecified number of integer ("int")
values and then outputs the minimum value and the maximum value that
were entered. At least one value will always be input. (read all input
until EOF). For extra credit make your program also work when the user
doesn't enter any ints at all (just the EOF.)"
I wanted to get fancy, so, in my solution, when just EOF is entered, the program responds with "Oops! You didn't enter anything. Please try again, this time entering at least one integer: " and prompts for input again.
My instructor is saying that this answer is wrong because
After the EOF, there should be no more input to a program (neither
expected by the user nor the program) — using the EOF to switch from
“one mode” of input to another mode of input isn’t supporting the
standards.
Every definition of EOF I've found on the internet doesn't seem to support my professor's definition. EOF, from what I can tell, is simply defined as the end of the current file. It seems perfectly valid to accept input from a user until EOF, do something with that input, and then ask for additional input until EOF again.
Because this is an online course, I was able to review everything we learned relating to EOF and we were only told that EOF meant "End of File" and could be 'used to signal an end to user input' (important, because, even if my professor was wrong, one could argue that I should have adopted his standards if he had specifically told us to. But he didn't tell us to).
What is the proper way to use EOF with user input? Is my professor's statement that "After the EOF, there should be no more input to a program" the standard
and expected way to use EOF? If a program accepts a variable amount of input, does something with it, and then accepts more variable input, is it not acceptable to use EOF with those inputs (aka don't use while(cin >> user_input) in that scenerio)? If so, is there a standard for what should be used to signal end of input in a scenario where you're accepting variable input multiple times?
My exact solution to the assignment is below. My solution to the main assignment "Write a program that inputs an unspecified number of integer ("int") values and then outputs the minimum value and the maximum value that were entered" was considered correct, by the second part of the assignment "make your program also work when the user doesn't enter any ints at all (just the EOF.)" was deemed incorrect ("make the program also work" is the only prompt we were given).
Thanks so much for any feedback!! Obviously, I'm skeptical of my professors feedback / decision, but, in general, I'm just trying to get a sense of C++ community standards.
#include <iostream>
#include <iomanip>
#include <string>
#include <stdlib.h>
using namespace std;
int main(){
string user_input;
int int_input, min_user_input, max_user_input;
bool do_it = true;
cout << "Hi John," << endl;
cout << "Please enter a few integers (signal EOF when finished): ";
while(do_it) {
cin.clear();
cin >> user_input;
if (user_input.empty()) {
cout << endl;
cout << "Oops! You didn't enter anything. Please try again, this time entering at least one integer: ";
}
else {
try {
int_input = atoi( user_input.c_str() );
min_user_input = int_input;
max_user_input = int_input;
while(cin >> int_input) {
if (min_user_input > int_input) {
min_user_input = int_input;
}
if (max_user_input < int_input) {
max_user_input = int_input;
}
}
cout << endl;
cout << "The max user input was: " << max_user_input << endl;
cout << "The min user input was: " << min_user_input << endl;
do_it = false;
}
catch (std::invalid_argument) {
cout << endl;
cout << "Oops! You didn't enter an integer. Please try again, this time only entering integers: ";
do_it = true;
}
}
}
return 0;
}
Note: additional feedback I got on this submission was: to not use c libraries (apparently stdlib.h is one) and that, on some computers (though, apparently, not mine), #include <stdexcept> will be needed to compile.
Answer
Short answer: my instructor is correct. When used with cin, no additional user input should follow an EOF signal. Apparently, in some cases the program won't let you enter more information, but, as #hvd points out
Although your system may let you continue reading from the same file
in the specific case that it is coming from a TTY, due to EOF being
faked there, you shouldn't generally rely on that.
Aka, because I'm using a terminal to enter user input, the program happens to work. In general, it won't work though.
As #RSahu answers, EOF just shouldn't be used to signal the end of variable length cin multiple times in a program. Importantly
There is no standard means, or commonly practiced coding standard, of
indicating when user input has ended for the time being. You'll have
to come up with your own mechanism. For example, if the user enters
"end", you can use it to deduce that the user has ended input for the
time being. However, you have to indicate to the user that that's what
they need to enter. Of course, you have to write code to deal with
such input.
Because this assignment required the use of EOF, what I was attempting to accomplish was, unintentionally, prohibited (aka receive input, check it, possibly receive more input).
Proper use of EOF (can it be used multiple times in a program?)
There is no single EOF. There is EOF associated with every input stream.
If you are reading from a file, you can reset the state of the std::ifstream when it reaches EOF to allow you to read the contents of the file again.
However, if you are reading data from std::cin, once EOF is reached, you can't read from std::cin any more.
In the context of your program, your professor is right. They are most likely talking about reading from std::cin.
EOF, from what I can tell, is simply defined as the end of the current file.
It is. Note that in particular, what it doesn't mean is the automatic start of a new file.
Although your system may let you continue reading from the same file in the specific case that it is coming from a TTY, due to EOF being faked there, you shouldn't generally rely on that. Try program </dev/null and see happens when you try to automate your program.

While loop acting weird in regards to input

Been working on a simple school project but I've run into a small problem in regards to validation of user input via the use of a while loop. The following code is used to do so:
cout << "How much woud you like to bet?[100, 300, 500]" << endl;
cin >> int_input;
if (cin.fail()){
int_input = 0;
}
//Validate check
while(int_input!=100 && int_input!=300 && int_input!=500){
cout << "Please enter a valid bet [100, 300, 500]" << endl;
cin >> int_input;
if (cin.fail()){
int_input = 0;
}
}
The issue arises when a non-integer is entered and the loop ends up spitting out the cout msg over and over again, skipping the request for new input. I assume that a non-integer always returns true for the while loop, but the program should still ask for user input, right?
The cin.fail is a recent addition and might not be necessary as it doesn't solve the problem, although I leave the code as it as it is.
If you have an error on the stream, you set your value to 0. So the loop is run again... and the error's still on the stream. Repeat.
You need to clear the error flag.
cin.clear();
Then extract enough "bad" data to get to the good part, or you'll just be right back where you started.

How to stop an infinite loop due to invalid input C++

So I want to accept two inputs, a string and an int, and when the user enters "end" to exit out of the loop.
My problem is when "end" is entered that it gets stuck in a loop, since (I'm assuming) it is expecting two inputs when the user only types in one.
I've done some research and found stuff on discarding the input and resetting it with cin.ignore() and cin.clear(), however, these seem to only apply when accepting a single input, where as I'm asking for two separate inputs on one line, and it doesn't seem to work.
What my code is doing is basically asking for a list of things (name value), storing it in an array in a class, and is capped at 10 items. So, when "end" in entered, it only needs to exit the while loop. Everything else seems to work fine, i.e. when I enter 10 items it exits the loop and the rest of the code executes like it should. So there just seems to be a problem when typing in 'end'. (p.s. a is a string and b in an int type).
The section of code is:
do {
cout << "Enter the item and value (enter 'end' to stop): ";
cin >> a >> b;
items1.set_name(a, i);
items1.set_price(b, i);
i++;
} while ( i < 10 && a != "end" );
This seems like it should be very simple, and I'm sorry if its a stupid question, but I can't figure it out hahah.
Thanks in advance for helping me out.
You need to test the value of a BEFORE proceeding to read b; something like this:
cin >> a;
if(a == "end")
break;
cin >> b;
To get out of the loop, use
if (a == "end" || b == "end") break;

Variable doesn't change to last input for that variable

I am trying to make this program currently output the character that they enter, after they enter an error. Currently if you enter a wrong character, I usually just do z, it will give you the desired out of "Error! Please enter a correct type!" and then go back to the start and have you enter the value again. If you enter lower case p it will then prompt for amount of checks written, i usually just say 1. After the checks written input it will then finish by outputting the Account Type that you entered. The problem I am getting is it outputs the z that I entered first and not the p.
How do I go about making the output of the Account Type the last input for that variable. (Global variables aren't allowed)
Code is this:
http://pastebin.com/1DrNcmrR
Jumping right back to the top of the function is bad practice, I woulnd't recommend trying to solve errors by calling the function again, instead how about you enter a while until the input is good?
while(true) {
cin >> answer;
if(toupper(answer) == 'P' || toupper(answer) == 'C') //#include <cctype>
break;
cout << "Error! Please enter a correct type!" << endl;
}
//switch, no default needed

Strange behaviour when reading in int from STDIN

Suppose we have a menu which presents the user with some options:
Welcome:
1) Do something
2) Do something else
3) Do something cool
4) Quit
The user can press 1 - 4 and then the enter key. The program performs this operation and then presents the menu back to the user. An invalid option should just display the menu again.
I have the following main() method:
int main()
{
while (true)
switch (menu())
{
case 1:
doSomething();
break;
case 2:
doSomethingElse();
break;
case 3:
doSomethingCool();
break;
case 4:
return 0;
default:
continue;
}
}
and the follwing menu():
int menu()
{
cout << "Welcome:" << endl
<< "1: Do something" << endl
<< "2: Do something else" << endl
<< "3: Do something cool" << endl
<< "4: Quit" << endl;
int result = 0;
scanf("%d", &result);
return result;
}
Entering numerical types works great. Entering 1 - 4 causes the program to perform the desired action, and afterwards the menu is displayed again. Entering a number outside this range such as -1 or 12 will display the menu again as expected.
However, entering something like 'q' will simply cause the menu to display over and over again infinitely, without even stopping to get the user input.
I don't understand how this could possibly be happening. Clearly, menu() is being called as the menu is displayed over and over again, however scanf() is part of menu(), so I don't understand how the program gets into this error state where the user is not prompted for their input.
I originally had cin >> result which did exactly the same thing.
Edit: There appears to be a related question, however the original source code has disappeared from pastebin and one of the answers links to an article which apparently once explained why this is happening, but is now a dead link. Maybe someone can reply with why this is happening rather than linking? :)
Edit: Using this example, here is how I solved the problem:
int getNumericalInput()
{
string input = "";
int result;
while (true)
{
getline(cin, input);
stringstream sStr(input);
if (sStr >> result)
return result;
cout << "Invalid Input. Try again: ";
}
}
and I simply replaced
int result = 0;
scanf("%d", &result);
with
int result = getNumericalInput();
When you try to convert the non-numeric input to a number, it fails and (the important part) leaves that data in the input buffer, so the next time you try to read an int, it's still there waiting, and fails again -- and again, and again, forever.
There are two basic ways to avoid this. The one I prefer is to read a string of data, then convert from that to a number and take the appropriate action. Typically you'll use std::getline to read all the data up to the new-line, and then attempt to convert it. Since it will read whatever data is waiting, you'll never get junk "stuck" in the input.
The alternative is (especially if a conversion fails) to use std::ignore to read data from the input up to (typically) the next new-line.
1) Say this to yourself 1000 times, or until you fall asleep:
I will never ever ever use I/O functions without checking the return value.
2) Repeat the above 50 times.
3) Re-read your code: Are you checking the result of scanf? What happens when scanf cannot convert the input into the desired format? How would you go about learning such information if you didn't know it? (Four letters come to mind.)
I would also question why you'd use scanf rather than the more appropriate iostreams operation, but that would suffer from exactly the same problem.
You need to verify if the read succeeded. Hint: it did not. Always test after reading that you successfully read the input:
if (std::cin >> result) { ... }
if (scanf("%d", result) == 1) { ... }
In C++ the failed state is sticky and stays around until it gets clear()ed. As long as the stream is in failed state it won't do anything useful. In either case, you want to ignore() the bad character or fgetc() it. Note, that failure may be due to having reached the end of the stream in which case eof() is set or EOF is returned for iostream or stdio, respectively.