Validating Integer input using booleans - c++

In my c++ code, I would like to validate my user input to be an int between 1,10 using a do while loop. I am able to validated for integers outside of the range. However if user inputs a float or a letter, it becomes an infinite loop. My idea is to add a condition in my while loop for if the input is not an integer to keep asking for input.
the CAPITAL letters is where I am having trouble.
#include <iostream>
using namespace std;
int main(){
cout << "Welcome, ";
int steps;
int count=0;
do{
cout << "How many? \n";
cin >> steps;
IF (STEPS IS NOT INTEGER==TRUE){
COUNT=1;
}
if (steps <1)
{
cout << "not enough...\n";
}
if (steps > 10){
cout << "too many steps.\n Please pick a lower number of steps.\n\n";
}
} while (steps < 1|| steps >10 || COUNT==1);
//doing stuff with valid input
return 0;
}
Essentially I am trying to add another condition that just returns a boolean. and if the boolean implies that the input is not valid, then it reassigns count to make sure the do while loops continues until the input is valid.
The problem i am working on asks for a max and min steps, since all of them were having a similar problem i tried to simplify it and forgot some of the edits.

You can check whether the input failed, i.e. the user entered something that could not be read as an int like this:
if (cin.fail()) { // in place of IF (STEPS IS NOT INTEGER==TRUE)
cin.clear();
cin.ignore();
cout << "not an integer, try again\n";
continue;
}
This avoids the need for the COUNT variable.
Also, your while condition doesn't appear to match the checks inside the loop. What happens when step is either 9 or 10? You should be consistent with the checks inside the loop.

You could use the ! operator.
For example:
if ( !(std::cin >> steps) )
{
std::cin.clear();
std::cin.ignore();
std::cout << "Incorrect entry. Try again: ";
}
Also consider not using using namespace std;.

Related

For Loops (C++)

Assignment:
The program should ask the user to enter a positive number and display all numbers from 1 to the input value. If the number is not positive, an error message should show up asking the user to re - enter the number.
My specific problem:
For my program, if the user enters an incorrect number and then re - enters a positive number, it does not display all the numbers from 1 to the input value. The program just ends.
#include <iostream>
using namespace std;
int main()
{
int userChoice;
int i = 1;
cout << "Enter a positive integer" << endl;
cin >> userChoice;
if (userChoice > 0)
{
for (i = 1; i <= userChoice; i++)
{
cout << "Loop 1:" << endl;
cout << i << endl;
}
}
else if (userChoice < 0)
cout << "Please re - enter" << endl;
cin >> userChoice;
system("pause");
return 0;
}
You need some sort of loop at the top of your program, that keeps asking for input until the user provides something valid. It looks like a homework assignment, so I will provide pseudo-code, not something exact:
std::cout << "Enter a number:\n";
std::cin >> choice;
while (choice wasn't valid) { // 1
tell the user something went wrong // 2
ask again for input in basically the same way as above // 3
}
// after this, go ahead with your for loop
It is actually possible to avoid the duplication here for step 3, but I worry that might be a little confusing for you, so one duplicated line really isn't such a big problem.
As an aside, you may wish to reconsider your use of what are often considered bad practices: using namespace std; and endl. (Disclaimer - these are opinions, not hard facts).

How to display a specific error to the user, requiring him/her to provide input again using a loop?

using namespace std;
int main(){
// Variable declarations
string hours = "";
double empHours = 0;
bool cont = true;
do{
// Get input of how much employee worked in a week.
cout << "Enter hours worked in a week: " ;
getline(cin, hours);
// Convert the input using string stream for easier validation.
stringstream hours_input(hours);
for(int i = 0; i <= hours[i]; i++)
// Check if input contains any alphabets e.g 90abc, if yes than repeat loop and ask user for input again.
if(isalpha(hours[i]))
cont = true;
// If the input successfully converts to double type
else if(hours_input >> empHours)
// Check if values are values >= 0, if yes than exit the loop
if(empHours >= 0){
hours_input >> empHours; // Assign value to empHours and exit loop
cont = false;
}
// Check if input contains special characters or any other form of bad input, if yes than repeat loop and ask user for input again.
else
cont = true;
}while(cont);
cout << "Value is: " << empHours << endl;
return 0;
}
This is what I have got so far. I am just not sure on how to display the error "That is not a valid option, please try again." and ask for input again. The code works however instead displaying the error mentioned, it displays "Enter hours worked in a week: ".
Simply, keep looping the error "That is not a valid option, please try again." and asking for input, until a valid input is provided.
The valid input should be any integer or float number >= 0.
Invalid inputs are any special characters, alphabets and any form of negative numbers.
You could just use a while loop.
It could go something like this:
while(true){
cin>>foo;
if(check if foo is a valid input){
break; //if the input is valid
}
cout<<"error, try again";
}
Currently, your code doesn't contain anything to print your error message. You already seem to be handling the error scenario though, so adding it isn't that hard.
If you change the else case in your for loop like this, it should work:
for(int i = 0; i <= hours[i]; i++)
// Check if input contains any alphabets e.g 90abc, if yes than repeat loop and ask user for input again.
if(isalpha(hours[i]))
{
cout << "That is not a valid option, please try again." << endl;
cont = true;
}
// If the input successfully converts to double type
else if(hours_input >> empHours)
// Check if values are values >= 0, if yes than exit the loop
if(empHours >= 0){
hours_input >> empHours; // Assign value to empHours and exit loop
cont = false;
}
// Check if input contains special characters or any other form of bad input, if yes than repeat loop and ask user for input again.
else
{
cout << "That is not a valid option, please try again." << endl;
cont = true;
}
You should however consider refactoring your code a bit to prevent some duplication. If you validate the input in a separate function for example, you can have one clear place of error handling instead of the duplication you have now.

Need some help finding a logical error in my while loop

I am learning C++, and I am doing some exercises in the book I am using. One of them asks to write a program that asks a user how many numbers they want to add up. Then prompt for the numbers the user wants to add or to enter '|' once finished. The numbers are then pushed into a vector. Part of the program asks to check if the size of the vector is equal to the original number of input items and that is where I keep getting an error.
cout << "Please enter the numbers and | once you are done: ";
while(true)
{
for(int num; cin >> num; )
{
if(num == '|')
{
break;
}
ints.push_back(num);
}
if(ints.size() != n)
{
cout << "There are more or less numbers in the vector than originally specified\n"
<< "Vector will be cleared; please re-enter the values: ";
ints.clear();
continue;
}
else
{
break;
}
}
The problem is that if the number of input is off, the message goes into an infinite loop and I am not sure how to fix it.
EDIT: n is the variable that holds in the number of values user wanted to enter.
Thanks!
num is an integer and cin >> num won't extract | symbol. Comparison num == '|' may not work as expected because num could have the numeric value of | ascii symbol even when user did not input any | symbol. You should properly handle end marker reading:
// loop will break when user enters `|` because it is not an integer
// setting failbit of cin
for(int num; cin >> num;)
{
ints.push_back(num);
}
cin.clear(); // reset failbit making cin able to read again
// check the end marker entered by user
{
string end_marker;
cin >> end_marker;
if("|" != end_marker)
{
// use of endl will flush the stream ensuring that
// printed text won't stuck in the buffer
cout << "Please use | as end marker" << endl;
continue;
}
}
Here is how I implemented it. I am worried about the logic in your while loop. I had been taught to avoid while(true) whenever possible. You know the logic behind how your code should work. With more practice you'll start to recognize the conditions you need to use. I am sure there are better ways to do it. But this is the way I tried it.
But to answer your question, the main reason it is failing is because integers cannot compare themselves with characters.
if(num == '|')
That does not work since num is an integer and not a character.
Normally I would implement this in a class and since global variables are not highly looked upon I created my own namespace. You'll have to finish the rest of the logic yourself however:
#include <iostream>
#include <vector>
#include <string>
namespace global
{
std::vector<std::string> strings;
std::vector<int> ints;
std::string a = " ";
int num = 0;
}
void doWork()
{
std::cout << "Please enter the number of integers you would like to add up: ";
std::cin >> global::num;
std::cout << "Please enter the numbers and | once you are done: ";
while (global::a != "|")
{
std::cin >> global::a;
global::strings.push_back(global::a);
}
global::strings.pop_back();
for(auto &e : global::strings)
{
global::ints.push_back(std::stoi(e));
}
}
int main()
{
doWork();
if(global::ints.size() != global::num)
{
std::cout << "Size of vector does not match the size specified. Clearing vector" << std::endl;
global::ints.clear();
global::strings.clear();
global::num = 0;
global::a = " ";
doWork();
}
}
I made a vector of char's and converted those into integers so that way you could add them up. The while loop should be checking for | rather than always running true. It then will check the size of the vector in the end, clear it if it does not match, and ask you to do it again. This is the best way that I could think of doing it.
EDIT: as VTT pointed out, char can only do one character at a time. I have converted it into a string in order to handle the conversion.
EDIT 2: reset the values of global::num and global::a to their default at the end of the failure in order to prevent crashing.

how to allow multiple inputs in case of an incorrect data type entry in cpp?

I have a program which generates random number and asks user to keep guessing it until he/she gets it right. I want it to keep accepting new values even if i incorrectly enter any other data type by handling the error cases.
My problem is that when i am trying to run the below program, as soon i input a character and hit enter, it goes into an infinite loop. I tried using cin.ignore() and cin.clear() but that just makes the program stop after the first entry.
Can anyone please help me understand what is going on and how to achieve the desired output? Thanks in advance.
#include <iostream>
#include <cstdlib>
#include <time.h>
using namespace std;
int main()
{
int secret_num, guess;
srand(time(NULL));
secret_num=rand() % 101 + 0;
cout<<"Enter your guess between 0 and 100: ";
do
{
if(!(cin>>guess))
{
cout<<" The entered value is not an integer"<<endl;
}
else if( isnumber(guess))
{
if(guess>secret_num)
cout<<"Too high";
else if(guess<secret_num)
cout<<"too low";
cout<<endl;
}
}
while(secret_num!=guess);
if((guess==secret_num)| (isnumber(guess)))
{
cout<<"yes the correct number is "<<secret_num<<endl;
}
return 0;
}
Edit: Here is a screenshot of what the output looks like with cin.clear() and cin.ignore(1000,'\n') in my code, when i enter a number after entering character twice.
if (!(cin >> guess))
{
cout << " The entered value is not an integer" << endl;
cin.clear(); // clear must go before ignore
// Otherwise ignore will fail (because the stream is still in a bad state)
cin.ignore(std::numeric_limits<int>::max(), '\n');
}
By default cin.ignore will ignore a single character. If they type more than 1 char, it won't be enough, that's why I've modified it a bit.
if ((guess == secret_num) | (isnumber(guess)))
| is a bitwise operator [OR]
|| is the logical operator [OR]
But I think what you actually want is && (AND)
if ((guess == secret_num) && (isnumber(guess)))
There're several problems.
You should use cin.clear() and cin.ignore() as #José suggested.
What's isnumber()? I guess it's returning false so no hint message (i.e. "Too high" and "too low") is printed out, looks like it stops although it's just waiting the next input. And isnumber() doesn't make sense to me. guess has been declared as an int, it has to be a number, doesn't it?
if((guess==secret_num)| (isnumber(guess))) is unnecessary here. The loop won't end until the user input the correct number, this condition should have been statisfied.
You can use clear and flush
if(!(cin>>guess))
{
cout<<" The entered value is not an integer"<<endl;
cin.clear();
fflush(stdin);
}
This works if you are reading from console. Otherwise you can go with #José answer.
I would change the logic inside your loop as there are some useless tests. This works for me:
#include <iostream>
#include <limits>
#include <cstdlib> // You may take a look at <random> and <chrono>
#include <time.h>
using std::cout;
using std::cin;
int main() {
srand(time(NULL));
int secret_num = rand() % 101;
cout << secret_num << '\n';
cout << "Enter your guess between 0 and 100:\n";
int guess = -1;
do {
cin >> guess;
if ( cin.eof() )
break;
if ( cin.fail() ) {
cout << "The entered value is not an integer, please retry.\n";
// clear the error flag
cin.clear();
// ignore the rest of the line
cin.ignore(std::numeric_limits<int>::max(),'\n');
// clear the value of the variable
guess = -1;
continue;
}
// now we know that guess is a number
if ( guess > secret_num )
cout << "Too high\n";
else if ( guess < secret_num )
cout << "Too low\n";
else {
cout << "Yes the correct number is " << secret_num << std::endl;
break;
}
} while ( true );
return 0;
}

Making an if condition return if its true or while return if its true

When the condition is true or false, how can I make it return back and ask the question again, making the user re-enter the value?
Here is what I want to implement:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
int n;
cout<<"Enter numbers. Press 5 to stop: ";
cin>>n;
bool tr=true;
while(tr)
{
if(n!=5)
cout<<"You entered "<<n; //How to make it return again, since its false? I keep getting infinite loops :( ;
else
tr=false;
}
return 0;
}
You need to prompt the user in the while loop, so that it occurs in each iteration:
int n;
bool tr = true;
while(tr)
{
cout << "Enter numbers. Press 5 to stop: ";
cin >> n;
if(n!=5) {
cout << "You entered " << n;
} else {
tr = false;
}
}
Just put all your code (except 'n' and 'tr' definition) in while loop as follow:
int main()
{
int n;
bool tr=true;
while(tr)
{
cout<<"Enter numbers. Press 5 to stop: ";
cin>>n;
if(n!=5)
cout<<"You entered "<<n;
else
tr=false;
}
return 0;
}
The other answers all work, and there is something to be learned about improving program flow from them, but I believe the trick you're asking for is the continue keyword, which skips the remainder of this iteration of the loop.
bool tr = true;
int n;
while (tr)
{
cout << "Enter numbers...";
cin >> n;
if (n != 5)
continue;
else
tr = false;
}
EDIT Part 1: On the continue keyword.
You want to make your code as readable as possible. In this example, its use is unnecessary (as the other posters have shown); but it is the answer to the question "How do I skip the rest of processing in this iteration of my loop and continue to the next iteration?". Usually, such flow-breaking directives actually make code harder to read; but sometimes the opposite is true. Anything (or, at least, almost anything) that can be accomplished with continue or break, can be accomplished without them, so if you're going to use them, you want to have a definite reason for doing so. Usually, when I use continue, it's because I'm looping through a collection of inputs and I want to skip processing the loop whenever the input isn't in the format I'm expecting. Something like this (pseudo-code)...
foreach (Input i in ReceivedInputs)
{
if (i.isBad())
{
cout << "Bad input";
continue;
}
// Do massive block of calculating here.
}
is easier to read than this...
foreach (Input i in ReceivedInputs)
{
if (i.isBad())
cout << "Bad input";
else
{
// Do massive block of calculating here.
}
}
because the second version makes it harder to track what scope you're in, if you're looking toward the end of the massive block of calculating. In this case, I gain code readability by continue, so I use it. But simple code probably shouldn't use it. The break keyword is similar, though it's a lot easier to come up with examples where break is beneficial.
EDIT Part 2: On multiple iterations
This is just an issue of setting up the loop; there are no magic keywords here. The shortest way I can come up with, is probably something like this:
int n = 0;
int numberToTake = 10;
for ( int numbersTaken = 0; numbersTaken < numberToTake; ++numbersTaken)
{
cout << "Enter numbers...";
int n = 0;
for (cin >> n; n != 5; cin >> n)
cout << "Try again.";
// Do whatever processing on n you want to do here.
}
Though I should point out that, doing it this way, the only value you will ever get from the user will be 5, and if he inputs anything that doesn't fit in an integer, you will get unexpected behavior.
EDIT 3: After reading the comment more thoroughly, I think you're just looking for is the more traditional use of the for loop.
No need for the exra bool variable.
The idiom can be: Infinitely loop until the user enters 5:
for(;;) { // Loops infinitely
cout << "Enter numbers. Press 5 to stop: ";
cin >> n;
if(n == 5)
break; // Exits the loop
cout << "You entered " << n; // Before the if if you want to print 5 as well
}