I'm trying to make do while loop what will validate data! When wrong data got should ask again. BUT when wrong data got program do loop again with skipping cin >> a;
Here two validation codes what I already tried:
1st one [Pic of console]
int a;
do
{
a = NULL;
cout << "Press some number: ";
cin >> a;
} while (a>=0 || a<=0);
2nd one: [Pic of console]
int a;
do
{
cin.clear(); cin.sync();
cout << "give me number: "; cin >> a;
} while (cin.fail());
This way you can check input is number or not:
int a;
bool flag=false;
while (true)
{
flag=false;
std::string input;
std::cout << "Press some number: ";
std::getline(std::cin,input);
try
{
a = stoi(input);
}
catch(const std::exception& e)
{
std::cout <<"Invalid number" << std::endl;
flag=true;
}
if (!flag)
break;
There are other ways to do this but i didn't mess your head with vectors or other things.
Related
I am trying to practice my input validation in C++. How can i let the program validate the user input when a user is asked to enter a number or string?
Here is a sample of my code.
public:
void CreateProduct() {
inputProduct:
system("cls");
cout << "\n\n\n\n\n\n\n\t\t\t\tPLEASE PROVIDE ACCURATE INFORMATION";
cout << "\n\n\t\tPRODUCT NUMBER: ";
cin >> ProductNumber;
if (!cin) {
cout << "\nPlease provide an integer";
cin.clear();
cin.end;
goto inputProduct;
//when enter a string i should enter this if statement and exit
// to be asked for another entry but am getting stuck in a loop.
}
system("cls");
cout << "\n\n\n\n\n\n\n\t\t\t\tPRODUCT NAME: ";
cin >> ProductName;
system("cls");
cout << "\n\n\n\n\n\n\n\t\t\t\tPRICE: ";
cin >> Price;
system("cls");
}
Please help me understand this input validation.
You can check whether input is number or not by checking ascii value of each character in input .
#include <iostream>
#include <cstring>
#include <string>
int main(void)
{
std::string str;
std::cin>>str;
bool isNumeric = true;
for(size_t i=0;i<str.length();++i)
{
if(str[i]< '0' || str[i] > '9')
{
isNumeric = false;
break;
}
}
if(!isNumeric)
{
std::cout<<"Input is not an integer";
exit(1);
}
return 0;
}
I can't see why this fails. Why does it loop forever after throwing the error?
bool undone;
do
{
undone = false;
try
{
o.spr(); // function throwing error E object
}
catch(E &r)
{
undone = true;
cout << r.reason << endl;
}
}
while(undone);
Here is the function:
void spr()
{
E r;
int n;
cout << " put n : "<<endl;
cin >> n;
if (cin.fail())
{
r.reason="fail !!";
throw r;
}
cout << " your n is : "<< n;
}
Your problem is recovering after the error.
First you have to clear the error flag from cin using cin.clear(). Then you have to read the bad input so it doesn't cause an error next time:
void spr()
{
E r;
int n;
cout << " put n : "<<endl;
cin >> n;
if (cin.fail())
{
cin.clear(); // clear the error flag
std::string bad_input;
cin >> bad_input; // skip over bad input
// now it is safe to re-use cin
r.reason="fail !!";
throw r;
}
cout << " your n is : "<< n;
}
Probably a better way to skip the bad input:
void spr()
{
E r;
int n;
cout << " put n : "<<endl;
cin >> n;
if (cin.fail())
{
cin.clear(); // clear the error flag
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // skip over bad input
r.reason="fail !!";
throw r;
}
cout << " your n is : "<< n;
}
The cin.ignore() function skips over the maximum possible number of input characters until it gets to an end of line '\n' character.
In case o.spr() throws, you set undone to true. Then condition in while() is checked, and it's true, so it loops, tries to call o.spr() again, and so on... Reconsider your undone flag and its value.
I'm struggling with a vector push_back function.
The goal is to have a function which pushes n number of elements until you decide to stop.
So my idea of a 'stop', is cin.fail().
The faulty function is
void pushbackVector(vector<double> &data)
{
double input;
cin >> input;
for (int i = 0; i < 100; i++)
{
if (cin.fail())
{
cout << "Ending input.\n";
return;
}
else
{
data.push_back(input);
}
}
Problem is that when I attempt to use it, I enter a infinite loop.
I have yet to sort the first vector in ASC order, second in DESC order and concatenate the first and second into the third vector. However I'm confident that I can manage this on my own.
Anyway the whole code....
#include<iostream>
#include<vector>
#include<algorithm>
#include<cctype>
using namespace std;
// function prototypes
void menu();
void printVector(const vector<double> &data);
void pushbackVector(vector<double> &data);
void sortVector (vector<double> &data);
int main()
{
menu();
vector<double> row1;
vector<double> row2;
/* not yet used
vector<double> row3;
*/
int input;
cin >> input;
bool exit = 0;
while (!exit)
{
switch (input)
{
case 1:
pushbackVector(row1);
break;
case 2:
pushbackVector(row2);
break;
case 3:
printVector(row1);
break;
case 4:
printVector(row2);
break;
case 5:
cout << "Printing out the contents of row 1\n";
printVector(row1);
cout << "Printing out the contents of row 2\n";
printVector(row2);
cout << "Printing out the contents of row 3\n";
// printVector(row3);
break;
case 6:
cout << "Exitting\n";
exit = 1;
break;
default:
cout << "Invalid choice\n";
}
}
return 0;
}
void menu()
{
cout << "Choose an option\n";
cout << "1) Enter first vector\n";
cout << "2) Enter second vector\n";
cout << "3) Print out the first vector\n";
cout << "4) Print out the second vector\n";
cout << "5) Print out all three vectoros\n";
cout << "6) Exitting the program\n";
}
void printVector(const vector<double> &data)
{
for(int i = 0; i < data.size(); i++)
{
cout << data[i] << ", ";
}
cout << "\n";
}
void pushbackVector(vector<double> &data)
{
double input;
cin >> input;
for (int i = 0; i < 100; i++)
{
if (cin.fail())
{
cout << "Ending input.\n";
return;
}
else
{
data.push_back(input);
}
}
}
void sortVector (vector<double> &data)
{
cout << "Sorting your vector \n";
sort(data.begin(), data.end());
}
You're only reading once, move the read inside the loop:
void pushbackVector(vector<double> &data)
{
double input;
// cin >> input; --------------
//
for (int i = 0; i < 100; i++) //
{ //
cin >> input; // <---------
if (cin.fail())
{
cout << "Ending input.\n";
return;
}
else
{
data.push_back(input);
}
}
That'll make sure that you actually get input. Now, if you're not going to enter 100 values, you need to somehow notify the stream. That's done by insert "EOF character" in it. Press CTRL+Z on windows or CTRL+D on unix terminals.
When this gets read from the stream, it enters a fail (and eof) state and it'll stay like that unless you clear the error flags by calling cin.clear() when appropriate.
You've made the same mistake also in main. You only read once before the while loop, so input keeps the value you initialy entered and keeps entering the same choice. I think that's the infinite loop you're talking about. To fix it, move the read statement just before the switch.
Hope that helps.
Also, this is how I'd write the function:
double input;
for (int i = 0; (cin >> input) && i < 100; ++i) {
data.push_back(input);
}
cout << "Ending input.\n";
Streams can be used in boolean expression - they convert to the result of !fail() - and such are a convenient and idiomatic way to control a loop.
The infinite loop is cause by the fact that you are reading:
cin >> input;
once and then entering a while loop (in your main) that will keep going forever (unless the input is initially equal to 6).
Change:
cin >> input;
bool exit = 0;
while (!exit)
{
// ...
to:
bool exit = 0;
while (!exit)
{
cin >> input;
// ...
Depending on what your logic is, the same is happening in the pushbackVector function at:
double input;
cin >> input;
for (int i = 0; i < 100; i++)
{
// ...
You might want to change that to:
double input;
for (int i = 0; i < 100; i++)
{
cin >> input;
// ...
Do something like this instead:
void pushbackVector(vector<double> &data)
{
double input;
while (cin >> input) //will return true when there's valid input, otherwise false
{
if (input == -1)
{
cout << "Ending input.\n";
return;
}
else
{
data.push_back(input);
}
}
This will read the input until you enter -1 or enter invalid input.
I think relying on cin.fail() is just not a good idea. The proper way to use fail() is explained in the link. It is not what you may expect.
Putting aside the reading which is misplaced, if you enter something you should not, you need to purge the input.
Add in the block of te first if
cin.clear();
cin.ignore( numeric_limits<streamsize>::max(), '\n' );
I would write the function the following way
void pushbackVector( std::vector<double> &data )
{
cin.clear();
cin.ignore( std::numeric_limits<streamsize>::max(), '\n' );
data.insert( data.end(), std::istream_iterator<double>( std::cin ), std::istream_iterator<double>() );
}
I was done some days before but I forgot to post my answer.
Who knew that I could just say if the cin fails, stop the input but don't end the program, lol.
#include<iostream>
#include<vector>
#include<algorithm> // for sort algorithms
#include<iomanip> // for setprecision
using namespace std;
// function prototypes
void menu();
void printVector(const vector<double> &data);
void pushbackVector(vector<double> &data);
void sortVector (vector<double> &data);
int main()
{
vector<double> row1;
vector<double> row2;
vector<double> row3;
int input;
bool exit = false;
while(!exit)
{
menu();
cin >> input;
switch (input)
{
case 1:
cout << "Entering vector 1\n";
pushbackVector(row1);
sortVector(row1);
cout << "\n";
break;
case 2:
cout << "Entering vector 2\n";
pushbackVector(row2);
sortVector(row2);
reverse(row2.begin(), row2.end());
cout << "\n";
break;
case 3:
cout << "Printing out vector 1\n";
printVector(row1);
cout << "\n";
break;
case 4:
cout << "Printing out vector 2\n";
printVector(row2);
cout << "\n";
break;
case 5:
// reserve enough space for all of row1's and row2's elements
row3.reserve(row1.size() + row2.size());
// insert row1's elements at the end of row3
row3.insert(row3.end(), row1.begin(), row1.end());
// insert row2's elements at the end of row3
row3.insert(row3.end(), row2.begin(), row2.end());
cout << "Printing out the contents of vector 1\n";
printVector(row1);
cout << "Printing out the contents of vector 2\n";
printVector(row2);
cout << "Printing out the contents of vector 3\n";
printVector(row3);
cout << "\n";
break;
case 6:
cout << "Exitting\n";
exit = true;
break;
default:
cout << "Invalid choice\n";
}
}
return 0;
}
void menu()
{
cout << "Choose an option\n";
cout << "1) Enter first vector\n";
cout << "2) Enter second vector\n";
cout << "3) Print out the first vector\n";
cout << "4) Print out the second vector\n";
cout << "5) Print out all three vectoros\n";
cout << "6) Exitting the program\n";
}
void printVector(const vector<double> &data)
{
for(int i = 0; i < data.size(); i++)
{
cout << setprecision(4) << data[i] << " ";
}
cout << "\n";
}
void pushbackVector(vector<double> &data)
{
double input;
int numOfItems;
cout << "How many items you want to add into vector?: ";
cin >> numOfItems;
for (int i = 0; i < numOfItems; i++)
{
cin >> input;
if (cin.fail())
{
cout << "Ending input.\n";
return;
}
else
{
data.push_back(input);
}
}
}
void sortVector(vector<double> &data)
{
cout << "Sorting your vector \n";
sort(data.begin(), data.end());
}
I tried to prompt user for input and do the validation. For example, my program must take in 3 user inputs. Once it hits non-integer, it will print error message and prompt for input again. Here is how my program going to be look like when running :
Enter number: a
Wrong input
Enter number: 1
Enter number: b
Wrong input
Enter number: 2
Enter number: 3
Numbers entered are 1,2,3
And here is my code:
double read_input()
{
double input;
bool valid = true;
cout << "Enter number: " ;
while(valid){
cin >> input;
if(cin.fail())
{
valid = false;
}
}
return input;
}
My main method:
int main()
{
double x = read_input();
double y = read_input();
double z = read_input();
}
When my first input is non-integer, the program just exits by itself. It does not ask for prompting again. How could I fixed it? Or am I supposed to use a do while loop since I asking for user input.
Thanks in advance.
When the reading fails, you set valid to false, so the condition in the while loop is false and the program returns input (which is not initialized, by the way).
You also have to empty the buffer before using it again, something like:
#include <iostream>
#include <limits>
using namespace std;
double read_input()
{
double input = -1;
bool valid= false;
do
{
cout << "Enter a number: " << flush;
cin >> input;
if (cin.good())
{
//everything went well, we'll get out of the loop and return the value
valid = true;
}
else
{
//something went wrong, we reset the buffer's state to good
cin.clear();
//and empty it
cin.ignore(numeric_limits<streamsize>::max(),'\n');
cout << "Invalid input; please re-enter." << endl;
}
} while (!valid);
return (input);
}
Your question did get myself into other issues like clearing the cin on fail() --
double read_input()
{
double input;
int count = 0;
bool valid = true;
while(count != 3) {
cout << "Enter number: " ;
//cin.ignore();
cin >> input;
if(cin.fail())
{
cout << "Wrong Input" <<endl;
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
else
count++;
}
return input;
}
The problem is in the while condition
bool valid = true;
while(valid){
You loop until you get a non valid input, this absolutly not what you want! loop condition should be like this
bool valid = false;
while(! valid){ // repeat as long as the input is not valid
Here is a modified version of your read_double
double read_input()
{
double input;
bool valid = false;
while(! valid){ // repeat as long as the input is not valid
cout << "Enter number: " ;
cin >> input;
if(cin.fail())
{
cout << "Wrong input" << endl;
// clear error flags
cin.clear();
// Wrong input remains on the stream, so you need to get rid of it
cin.ignore(INT_MAX, '\n');
}
else
{
valid = true;
}
}
return input;
}
And in your main you need to ask for as may doubles as you want, for example
int main()
{
double d1 = read_input();
double d2 = read_input();
double d3 = read_input();
cout << "Numbers entered are: " << d1 << ", " << d2 << ", " << d3 << endl;
return 0;
}
You may also want to have a loop where you call read_double() and save the returned values in an array.
I'd like to catch exception which occurs when somebody gives not a number value on the cin so the program will read next value.
#include <iostream>
using namespace std;
int main()
{
int x = 0;
while(true){
cin >> x;
cout << "x = " << x << endl;
}
return 0;
}
If you really want to use exception handling, you could do something like this:
cin.exceptions(ios_base::failbit); // throw on rejected input
try {
// some code
int choice;
cin >> choice;
// some more code
} catch(const ios_base::failure& e) {
cout << "What was that?\n";
break;
}
Reference: http://www.cplusplus.com/forum/beginner/71540/
There is no exception being thrown at all. Instead, cin sets a "bad input" flag of sorts. What you want is this:
while ((std::cout << "Enter input: ") && !(std::cin >> x)) {
std::cin.clear(); //clear the flag
std::cin.ignore (std::numeric_limits<std::streamsize>::max(), '\n'); //discard the bad input
std::cout << "Invalid input; please re-enter.\n";
}
This series of questions explains it really well.
Links:
clear()
ignore()
Add something like:
if(cin.fail())
{
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(),' ');
cout << "Please enter valid input";
}
int main()
{
int x = 0;
cin.exceptions(ios::failbit);
while(true){
try
{
cin>>x;
}
catch(ios_base::failure& e)
{
//..
}
cout<<"x = "<<x<<endl;
}
return 0;
}
This should work.