While loop meant to verify user input constantly loops - c++

I am trying to verify the user input, but I have tried two compilers and I either have one of two things happen. Either it will:
-Constantly loop the error message without asking for user input
OR
-Wait for user input, and if the input is incorrect, will constantly loop the error message.
Here is the code:
cout << "Input number of the equation you want to use (1,2,3): " ;
cin >> userInput;
cout << endl;
while (userInput <= 0 || userInput >= 4)
{
cout << "Please enter a correct input (1,2,3): " ;
cin >> userInput;
cout << endl;
}
if (userInput == 1)
{
userInput is declared as an integer. Is there an easier way to verify user input, or a while loop is necessary? I am still very new to coding.

While using int userInput seems straight forward, it fails when the user inputs non-numeric values. You can use a std::string instead and check, if it contains a numeric value
std::string userInput;
int value;
std::cout << "Input number of the equation you want to use (1,2,3): " ;
while (std::cin >> userInput) {
std::istringstream s(userInput);
s >> value;
if (value >= 1 && value <= 3)
break;
std::cout << "Please enter a correct input (1,2,3): " ;
}
std::istringstream is similar to other input streams. It provides input from an internal memory buffer, in this case the value provided by userInput.

I would add an additional check to make sure that if the user enters non-integral input, the stream is cleared before attempting the next read.
cout << "Input number of the equation you want to use (1,2,3): " ;
cin >> userInput;
cout << endl;
while (userInput <= 0 || userInput >= 4)
{
if ( !cin.good() )
{
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
cout << "Please enter a correct input (1,2,3): " ;
cin >> userInput;
cout << endl;
}

I would suggest using a do loop instead so you have less repeated lines
int userInput = 0;
do
{
cout << "Input number of the equation you want to use (1,2,3): " ;
cin >> userInput;
cout << endl;
if ( !cin.good() )
{
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
} while (userInput <= 0 || userInput >= 4);

You don't want to cin >> int, if you are to perform any error checking. If the user enters a non-integer, you'll end up in difficult-to-recover-from situations.
Rather, cin into a string, perform any error checking you want and convert the string to a integer:
long x;
string sx;
cin >> sx;
x = strtol(sx.c_str(), NULL, 10);

Related

Why does this do-while-loop only write to the arrays every other loop?

The purpose of this do while loop is to enter coordinates(or points) into two arrays: points_x[] and points_y[]. The loop is to stop when the user enters a non integer input. For some reason only every other cin actually writes to the arrays. Does anyone know why?
cout << "Enter a list of points(x y): ";
do
{
cin >> points_x[v];
cout << points_x[v];
cin >> points_y[v];
cout << points_x[v];
howMany++;
v++;
} while (cin >> points_x[v] && cin >> points_y[v]);
Here you are reading twice (once for each coordinate, x and y)
cin >> points_x[v];
cout << points_x[v];
cin >> points_y[v];
cout << points_x[v];
I assume that you mean this to be "one cin".
Then you increase the index you use while writing the results to the array.
v++;
Then you read again once into each coordinate, while evaluating the loop condition:
while (cin >> points_x[v] && cin >> points_y[v])
I assume that you mean that to be the second "cin".
The readings during the condition (i.e. the second "cin") write already to the next index,
but the reading inside the body then writes to that same index again (overwriting the values from the condition read).
So in the end you enter each xy twice, once ignored during the condition, once "surviving" inside the loop body.
As the input can be multiple digits, prefer to enter as string, check each digit to be numbers and assign after converting to integer. See snippet:
bool IsAlpha(string s) {
for (const auto& c : s)
if (isalpha(c)) return true;
return false;
}
void main()
{
string str;
cout << "Enter a list of points(x y):";
while(true)
{
cout << "\n Enter X ";
cin >> str;
if (IsAlpha(str)) break;
points_x[v] = std::stoi(str);
cout << " " << points_x[v] ;
cout << "\n Enter Y ";
cin >> str;
if (IsAlpha(str)) break;
points_y[v] = std::stoi(str);
cout << points_y[v] << " ";
howMany++;
v++;
};
}

input validation in loop

I'm trying to make a validation loop in C++ that checks the user's input until they enter a number between 0 and 100 and however my loop only checks the first condition. Any guidance is appreciated!
#include <iostream>
using namespace std;
int main()
{
const int max_num = 100;
const int min_num = 0;
int num;
cout << "Enter a number between 0 and 100" << endl;
cin >> num;
do {
if (!(cin >> num))
{
cout << "ERROR:The value provided was not a number" << endl;
cin.clear();
cin.ignore(1024, '\n');
cout << "Enter a number between 0 and 100" << endl;
cin >> num;
}
else if (num<min_num || num>max_num)
{
cout << "ERROR: value out of range" << endl;
cin.clear();
cin.ignore(1024, '\n');
cout << "Enter a number between 0 and 100" << endl;
cin >> num;
}
} while (!(cin >> num) || (num<min_num || num>max_num));
return 0;
}
Add lots of logging to your code so that you know what it's doing. This will help you find the problem. For example, instead of:
cout << "Enter a number between 0 and 100" << endl;
cin >> num;
Try:
cout << "Enter a number between 0 and 100" << endl;
cerr << "About to read into num outside the loop" << endl;
cin >> num;
cerr << "Read into num outside the loop, got: " << num << endl;
And so on, throughout your code. This should give you enough information to find the bug. Alternatively, use a debugger with a single step function to accomplish the same thing.
Check that in the part of while:
instead of
while (!(cin >> num) || (num<min_num || num>max_num));
this:
while (!cin || (num<min_num || num>max_num));
the same for the upper if
cin >> num means putting user input to the variable num . So you are trying to take user inputs 2 times in the loop. Maybe the check condition: (num == (int)num)will solve your problem. It will try to verify the number you have stored in num is really of the type int

If-Else Statement Returning Same Feedback

So for some reason no matter what I enter into this If-Else statement it returns with a "Program Aborted" as if I entered the wrong requested answers...very confused and I can't seem to find anything relevant enough around the site!
int ch;
cout << "Do you have any extra credit points? (Enter Y/y or N/n)" << endl;
cin >> ch;
int ExtraCredit;
if (ch == 'Y' || ch== 'y')
{
cout << "Enter the number of extra credit points: ";
cin >> ExtraCredit
}
else if (ch!='n' || ch!='N' || ch != 'y' || ch != 'Y')
{
ExtraCredit=0;
cout<< Invalid entry. Program Aborted." << endl;
return 0;
}
The issue appears very early:
int ch; // are you sure this should be an int?
cout << "Do you have any extra credit points? (Enter Y/y or N/n)" << endl;
cin >> ch;
cin behaves differently on int typed variables than on chars. When you enter "y" or "n" at the keyboard, cin will fail.
You can check whether cin failed by calling its fail() method, like so:
int num;
std::cout << "Enter a number: ";
std::cin >> num;
if (std::cin.fail()) {
std::cout << ":(" << std::endl;
} else {
std::cout << "Your number was " << num << std::endl;
}
ints and chars are separate types, even though they can be compared based on the ASCII value of the char in C++. Because they are defined as separate types, when your code gets to the line cin >> ch and ch is of type int, it waits for something to be entered. The prompt tells the user to enter a char, and they do. The code sees the char, and as it wasn't an int, nothing is read in and the value of ch is correctly determined by your code to be not y, Y, n, or N. If you'd like to cin a char, declare char ch;. If you'd like to have an int, prompt the user to enter a number.

Using a while loop to check for input errors within a switch case

I have a switch in which one case asks the user for several inputs to use for constructing a class object. One of these inputs should be in the form of a number. If a number is not entered it breaks the switch and ends up terminating the program. I want to set up a while(){} condition so that if a non integer is entered it will prompt the user to enter an integer and then continue on with the program.
int main(){
int in_yob, ranking;
string in_first_name, in_last_name, in_genre, in_fact, last_name, in_composer;
char selection, choice;
do {
DisplayMenu();
cin >> selection;
cout << endl;
while (!cin || selection < 48 || selection > 53){
cin.clear();
cout << "Please make a valid selection" << endl;
DisplayMenu();
cin >> selection;
}
switch (selection) {
case 49 : {
cout << "First Name: ";
cin >> in_first_name;
cout << "Last Name: ";
cin >> in_last_name;
cout << "Genre: ";
cin >> in_genre;
cout << "Year of Birth: ";
cin >> in_yob;
cout << "Fact: ";
cin >> in_fact;
last_name = in_last_name;
transform(last_name.begin(), last_name.end(), last_name.begin(), ::tolower);
Composer& last_name = myDB.AddComposer(in_first_name, in_last_name,
in_genre, in_yob, in_fact);
cin.clear();
} break;
...
default:
cout << "Please make a valid selection" << endl;
}
} while (selection != 48);
}
I have tried inserting a while loop after cin >> in_yob; as:
while(!cin || in_yob > 1){
cin.clear();
cout << "Enter a positive enter for year of birth: ";
cin >> in_yob;
}
but the result is an infinite loop of "Enter a positive enter for year of birth: ". I know this construct for error checking works outside of a switch case so what is the reason that within a switch case i'm getting this result? Also how would you go about fixing this so that I can check for and prevent an input error? Thanks.
[To explain my self with more space and better formatting better than in a comment I post this as an answer instead as of a comment.]
When you enter input, like for example
1
the input buffer actually contains two characters, firs the digit '1' and then the newline '\n'.
When you read a single character, the input operation extracts the first character, the digit, and writes it to your variable.
If you then read another character, it will read the newline, and not whatever comes after.
There is a trick to "ignore" characters until, for example, a newline, and that is done by using the std::istream::ignore, and if you follow the link to the reference you will see a very good example on how to ignore anything up to and including the newline.
So in your case it's not enough to just call clear you need to call ignore as well in your input validation loop. And if you continue to read single characters, you need to call ignore before that as well.
You needed to clear the input stream.
#include <iostream>
#include <string>
int in_yob = 0;
int main()
{
while(std::cin.good() && in_yob < 1){
std::cin.clear();
std::cout << "Enter a positive enter for year of birth: ";
if( !(std::cin >> in_yob) ) {
std::cin.clear();
std::cin.ignore(10000,'\n');
}
}
std::cout << "YOB " << in_yob << std::endl;
}

Trouble with do-while-loop

I'm trying to write a program which calculates prime numbers and I have issues with a do-while-loop I am using.
Code:
#include <iostream>
#include <conio.h>
using namespace std;
int main()
{
unsigned long int lower_limit;
unsigned long int upper_limit;
cout << "\n" << "Program calculates prime numbers in a given range between 2 and 4.294.967.295.";
cout << "\n" << "Input range in which prime numbers are to be calculated... ";
do
{
cout << "\n\n" << "Lower Limit:\t"; cin >> lower_limit;
cout << "\n" << "Upper Limit:\t"; cin >> upper_limit;
if(lower_limit >= upper_limit)
{
cout << "\nInvalid Input: Value of Upper Limit has to be bigger than value of Lower Limit.";
cout << "\nSelect new numbers.";
}
if(!(cin >> lower_limit) || !(cin >> upper_limit))
{
cout << "\nInvalid Input: Values of Lower Limit and Upper Limit have to be integers.";
cout << "\nSelect new numbers.";
}
}while(lower_limit >= upper_limit || !(cin >> lower_limit) || !(cin >> upper_limit));
return(0);
}
If I input values to trigger Lower Limit >= Upper Limit it triggers the first error properly, but doesn't repeat the do-while-loop afterwards and doesn't close the program (return(0)) either... So the program is not repeating the do-while-loop, neither is the program exiting it. I really have no clue what it is actually doing there.
If I input values to trigger !(cin >> lower_limit) || !(cin >> upper_limit) ("adfd" or the like) the whole program just goes mental and rapidly repeats the do-while-loop, even ignoring the cin >> lower_limit; and cin >> upper_limit; statements.
Does anybody have an idea that can help me out?
Cheers!
One point is that if you get invalid input, you need to clear the error state by:
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
Your loop should be changed to something like:
do
{
while ( !(cin >> lower_limit >> upper_limit) ) {
cout << "Invalid input, Please re-enter\n";
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
if(lower_limit >= upper_limit)
{
cout << "\nInvalid Input: Value of Upper Limit has to be bigger than value of Lower Limit.";
cout << "\nSelect new numbers.";
}
} while(lower_limit >= upper_limit);