how to make cin only take integer inputs - c++

i new to programming and we are required to create a program that dont exit when the user inputs the wrong input, but i only learned the basics so far.. i already solved when the number is above and below 100 but when the user accidentally inserted a non integer it will go into a error loop. btw this is an average calculator.
#include <iostream>
using namespace std;
int main()
{
int num[100];
int n;
double sum, average;
cout << "how many numbers will you input?: ";
cin >> n;
while ( n > 100 || n <= 0 )
{
cout << "Error! number should in range of (1 to 100) only." << endl;
cout << "Enter the number again: ";
cin >> n;
}
for ( int i = 0; i < n; ++i )
{
cout << i + 1 << ". Enter number: ";
cin >> num[i];
sum += num[i];
}
average = sum / n;
cout << "Average = " << average;
}

If std::istream::operator >> fails, it will set failbit. Therefore, you should check failbit (for example by calling std::cin.fail()) to see whether the conversion was successful, before using the result of the conversion.
If the conversion fails due to bad input, then the next call to std::istream::operator >> will automatically fail due to failbit being set. That is why you are getting stuck in an infinite loop. If you want to attempt input again after a conversion failure, you will first have to clear failbit, by using the function std::cin.clear().
Also, you will have to discard the bad input that caused the conversion to fail, because otherwise, the next time you call std::istream::operator >>, the conversion will fail again for the same reason. In order to clear the bad input, you can use std::cin.ignore(), like this:
std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );
In order to use std::numeric_limits, you will have to #include <limits>.
After performing these fixes on your code, it should look like this:
#include <iostream>
#include <limits>
using namespace std;
int main()
{
int num[100];
int n;
double sum, average;
bool input_ok;
//repeat until input is valid
do
{
cout << "How many numbers will you input? ";
cin >> n;
if ( cin.fail() )
{
cout << "Error: Conversion to integer failed!\n";
input_ok = false;
}
else if ( n > 100 || n <= 0 )
{
cout << "Error: Number should in range of (1 to 100) only!\n";
input_ok = false;
}
else
{
input_ok = true;
}
//clear failbit
cin.clear();
//discard remainder of line
cin.ignore( numeric_limits<streamsize>::max(), '\n' );
} while ( !input_ok );
for ( int i = 0; i < n; ++i )
{
do
{
cout << i + 1 << ". Enter number: ";
cin >> num[i];
if ( cin.fail() )
{
cout << "Error: Conversion to integer failed!\n";
input_ok = false;
}
else
{
input_ok = true;
}
//clear failbit
cin.clear();
//discard remainder of line
cin.ignore( numeric_limits<streamsize>::max(), '\n' );
} while ( !input_ok );
sum += num[i];
}
average = sum / n;
cout << "Average = " << average;
}
This program has the following behavior:
How many numbers will you input? 200
Error: Number should in range of (1 to 100) only!
How many numbers will you input? -31
Error: Number should in range of (1 to 100) only!
How many numbers will you input? test
Error: Conversion to integer failed!
How many numbers will you input? 4abc
1. Enter number: 1
2. Enter number: 2
3. Enter number: 3
4. Enter number: 4
Average = 2.5
As you can see, the program now works in that it can now handle bad input such as test. It rejects that input and reprompts the user for new input.
However, one problem with this program is that it accepts 4abc as valid input for the number 4. It would probably be appropriate to reject such input instead. One way to fix this would be to inspect the remainder of the line, instead of simply discarding it.
Another issue is that this solution contains a lot of code duplication. Apart from the range check, both do...while loops are nearly identical. Therefore, it would be better to put this loop into a function, which can be called from several places in your code.
However, I generally don't recommend that you use std::istream::operator >>, because its behavior is not always intuitive. For example, as already pointed out above:
It does not always read a whole line of input, so that you must explicitly discard the remainder of the line.
It accepts 4abc as valid input for the number 4.
In my experience, if you want proper input validation of integer input, it is usually better to write your own function that reads a whole line of input using std::getline and converts it with std::stoi. If the input is invalid, then the function should automatically reprompt the user.
In my example below, I am calling this function get_int_from_user.
If you want to additionally ensure that the input is in a certain range, then you can call the function get_int_from_user in an infinite loop, and break out of that loop once you determine that the input is valid.
#include <iostream>
#include <string>
#include <sstream>
#include <cctype>
int get_int_from_user( const std::string& prompt );
int main()
{
int nums[100];
int n;
double sum;
//repeat loop forever, until input is good
for (;;) //equivalent to while(true)
{
n = get_int_from_user( "How many numbers will you input? " );
if ( 1 <= n && n <= 100 )
//input is good
break;
std::cout << "Error! Number should in range of (1 to 100) only.\n";
}
//read one number per loop iteration
for( int i = 0; i < n; i++ )
{
std::ostringstream prompt;
prompt << "Enter number #" << i + 1 << ": ";
nums[i] = get_int_from_user( prompt.str() );
sum += nums[i];
}
std::cout << "Average: " << sum / n << '\n';
}
int get_int_from_user( const std::string& prompt )
{
std::string line;
std::size_t pos;
int i;
//repeat forever, until an explicit return statement or an
//exception is thrown
for (;;) //equivalent to while(true)
{
//prompt user for input
std::cout << prompt;
//attempt to read one line of input from user
if ( !std::getline( std::cin, line ) )
{
throw std::runtime_error( "unexpected input error!\n" );
}
//attempt to convert string to integer
try
{
i = std::stoi( line, &pos );
}
catch ( std::invalid_argument& )
{
std::cout << "Unable to convert input to number, try again!\n";
continue;
}
catch ( std::out_of_range& )
{
std::cout << "Out of range error, try again!\n";
continue;
}
//The remainder of the line is only allowed to contain
//whitespace characters. The presence of any other
//characters should cause the entire input to get rejected.
//That way, input such as "6sdfj23jlj" will get rejected,
//but input with trailing whitespace will still be accepted
//(just like input with leading whitespace is accepted by
//the function std::stoi).
for ( ; pos < line.length(); pos++ )
{
if ( !std::isspace( static_cast<unsigned char>(line[pos]) ) )
{
std::cout << "Invalid character found, try again!\n";
//we cannot use "continue" here, because that would
//continue to the next iteration of the innermost
//loop, but we want to continue to the next iteration
//of the outer loop
goto continue_outer_loop;
}
}
//input is valid
return i;
continue_outer_loop:
continue;
}
}
This program has the following behavior:
How many numbers will you input? 200
Error! Number should in range of (1 to 100) only.
How many numbers will you input? -31
Error! Number should in range of (1 to 100) only.
How many numbers will you input? test
Unable to convert input to number, try again!
How many numbers will you input? 4abc
Invalid character found, try again!
How many numbers will you input? 4
Enter number #1: 1
Enter number #2: 2
Enter number #3: 3
Enter number #4: 4
Average: 2.5
As you can see, it now correctly rejects the input 4abc.
I believe that using the function get_int_from_user makes the code in main much cleaner.
Note that the code above uses one goto statement. Under most circumstances, you should avoid using goto, but for breaking out of nested loops, it is considered appropriate.

#include <iostream>
#include <limits>
using namespace std;
int avg(int sum, int n)
{
int average;
average = sum/n;
cout<<"Avg = "<<average;
}
int main()
{
int n;
cout << "how many numbers will you input?: ";
cin >> n;
int w = n;
int num[w];
int sum;
while(n>100||n<=0)
{
cout << "Error! number should in range of (1 to 100) only." << endl;
cout << "Enter the number again: ";
cin >> n;
}
for(int i = 0; i < n; ++i)
{
cout << i + 1 << "Enter number: ";
cin >> num[i];
if(!cin)
{
cout << "Wrong Choice. " << endl;
cin.clear();
cin.ignore( numeric_limits<std::streamsize>::max(), '\n' );
n++;
continue;
}
else
{
sum += num[i];
}
}
cout<<"Sum = "<<sum<<endl;
avg(sum,w);
}

Related

Hi I want user to enter 5 numbers and then output the sum in the end

I have used a loop for that:
int number1;
int sum=0;
for(int i =1; i<6; i++){
cout<<"Enter number:\n";
cin>>number1;
sum+=number1;
}
cout<<sum;
cout<<"Total Sum is = "<<sum<<"\n";
return 0;
}
My question is how can I print first statement like this ...
"Enter first number"
Enter Second number" and so on
Whenever you are reading numbers (or any value for that matter), you must check the stream-state (see: std::basic_istream State Functions). You have four stream states you must test following every input:
.bad() or .eof(). If badbit is set an unrecoverable error occurred, and if eofbit is set, there is nothing more to read (you can combine both into a single test that exits if either are set)
.fail() is set when a read error occurs, such as the user entering "FIVE" instead of 5 where integer input is expected. You handle failbit being set by calling .clear() to clear failbit and then call ignore() to empty the characters causing the failure before your next read attempt, and finally
.good() - valid input was received from the user, you can proceed to the next input.
By validating your input here, you can Require the user provide 5 valid integer values for you to sum. Do not use a for loop, instead use a while (or do .. while();) and only increment your counter when good input is received.
Putting that altogether, you can do:
#include <iostream>
#include <limits>
int main (void) {
int number = 0,
sum = 0;
const char *label[] = { "first", "second", "third", "fourth", "fifth" };
while (number < 5) /* loop continually until 5 int entered */
{
int tmp; /* temporary int to fill with user-input */
std::cout << "\nenter " << label[number] << " number: ";
if (! (std::cin >> tmp) ) { /* check stream state */
/* if eof() or bad() exit */
if (std::cin.eof() || std::cin.bad()) {
std::cerr << " (user canceled or unreconverable error)\n";
return 1;
}
else if (std::cin.fail()) { /* if failbit */
std::cerr << " error: invalid input.\n";
std::cin.clear(); /* clear failbit */
/* extract any characters that remain unread */
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}
else { /* on succesful read of int, add to sum, increment number */
sum += tmp;
number++;
}
}
std::cout << "\nsum: " << sum << '\n';
}
Now your code will gracefully handle an invalid input without exiting just because a stray character was entered.
Example Use/Output
When you write an input routine, go try and break it. Enter invalid data and make sure you handle all error cases correctly. If something doesn't work right, go fix it. Repeat until you input routine can handle all corner-cases as well as the cat stepping on the keyboard:
$ ./bin/sumintlabel
enter first number: 3
enter second number: four five six seven!!
error: invalid input.
enter second number: 4
enter third number: 5
enter fourth number: 6
enter fifth number: 7
sum: 25
Form good habits now regarding handling input, it will pay dividends for the rest of your programming career. Let me know if you have questions.
if you need to print the words "first"... untill "fifth" then I'd do it like this:
#include <iostream>
#include <iomanip>
using namespace std;
int main() {
int number1;
int sum=0;
string positions[5] = {"first", "second", "third", "fourth", "fifth"};
for(int i = 0; i<5; i++){
cout<<"Enter the " << positions[i] << " number:" << endl;
cin>>number1;
sum+=number1;
}
cout<<"Total Sum is = "<<sum<<"\n";
return 0;
}
I used an array of strings to display the words and changed the for loop to start at 0 so that we can go through the array positions and add the 5 numbers as well. If you just want to use: 1st, 2nd, 3rd... then you could change the for loop to what it was and do:
cout<<"Enter the " << i << "st" << " number:" << endl;
But for this you would have to use the if statement to print the right endings("st", "rd", "nd"). I think it would take longer for it to run but its miliseconds so we wouldn't even notice hahaha.
Hope it helped :)
You can use switch():
#include <iostream>
using std::cin;
using std::cout;
using std::string;
int main() {
int number1;
int sum = 0;
for(int i = 1; i < 6; i++) {
string num;
switch(i) {
case 1:
num = "first";
break;
case 2:
num = "second";
break;
//and 3 4 5 like this
}
cout << "Enter " << num << " number:\n";
cin >> number1;
sum += number1;
}
cout << "Total Sum is = " << sum << "\n";
return 0;
}
or you can use struct or containers like vector (in fact you have to use containers if you want to get a huge number of data.)

Infinite loop when using exceptions in c++11

I would like to create a c++11 program that takes in 10 positive integers and gives the user the total. In the event of a negative number or a char input, the exception should be thrown and the user must re enter their value.
The program below works with negative numbers. However, when I enter a character like "a", the program goes into an infinite loop and I cannot figure out why.
Any and all help will be appreciated
#include <iostream>
int main(){
int array[10] = {0};
int total = 0;
for(int i =0; i < 10; i++){
std::cout<<"Number "<< i+1 << ": " <<std::endl;
std::cin >> array[i];
try{
if(array[i] < 0 || std::cin.fail())
throw(array[i]);
}
catch(int a){
std::cout<< a <<" is not a positive number! "<<std::endl;
i-=1; // to go back to the previous position in array
}
}
for(int k = 0; k < 10; k++)
total+=array[k];
std::cout<<"Total: " <<total<<std::endl;
}
If you get invalid input there are two things to thing you need to do:
Clear the stream status. This is done using the clear function.
Remove the invalid input from the buffer. This is usually done using the ignore function.
As for your program, you don't need exceptions here, just using unsigned integers and checking the status is enough:
unsigned int array[10] = { 0 };
...
if (!(std::cin >> array[i])
{
std::cout << "Please input only non-negative integers.\n";
// First clear the stream status
std::cin.clear();
// Then skip the bad input
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// Make sure the index isn't increased
--i;
}
To use exceptions similar to what you do now, the solution is almost exactly the same as above:
unsigned int array[10] = { 0 };
...
if (!(std::cin >> array[i])
{
throw i;
}
catch (int current_index)
{
std::cout << "The input for number " << current_index + 1 << " was incorrect.\n";
std::cout << "Please input only non-negative integers.\n";
// First clear the stream status
std::cin.clear();
// Then skip the bad input
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// Make sure the index isn't increased
--i;
}
Do not forget to include limits header file while using following line in your code :
std::cin.ignore(std::numeric_limits::max(), '\n');
because numeric_limits template is defined in this header file !

C++ Excluding non-integer user inputs

I am making a number-guessing game where the user is asked to input a four-digit number. It is possible, however, that the user inputs less or more than four digits and/or a non-integer input (i.e. invalid input). My code stores the user input into an integer-type array. I just realized now that my code will still recognize "invalid inputs" as valid since the array where the input is being stored is declared as an integer-type. Below is a portion of my code:
#include <iostream>
using namespace std;
void guess(int num_guess[], int size);
int main(){
int list[4];
guess(list, 4);
for(int i = 0; i < 4; i++){
cout << list[i];
}
cout << endl;
}
void guess(int num_guess[], int size){
int number;
cin >> number;
for(int i = size-1; i >= 0; i--){
num_guess[i] = number%10;
number /= 10;
}
}
cout << list[i]; isn't really part of the original code, but this was how I found out that invalid inputs are still accepted. I encountered a similar problem before when I was making a rational roots calculator program in Python, but it was much easier then to detect and exclude unwanted inputs. My question is, how do I fix my code so that it can detect invalid inputs and output something like "Invalid input" and then proceed to ask the user for another input.
The following is a function to check if a string is a 4 digit positive integer. If the number could be negative, you just need to check if the s[0] == '-'.
bool check(string &s){
if(s.size() != 4) return false;
for(int i=0; i < 4; i++){
if(s[i] < '0' || s[i] > '9') return false;
}
return true;
}
The following is a function to convert a string to an int:
#include <stringstream>
int strToInt(string &s){
stringstream ss(s);
int ans;
ss >> ans;
return ans;
}
To exclude non integer inputs try the following:
void skip_to_int(){
// if is not an integer
if(cin.fail()){
// check character type
cin.clear();
char ch;
while(cin>>ch){
// throw away non digits
if(isdigit(ch)){
// put back if digit to be written
cin.unget();
return;}
}
}
else error ("no input");
}
And your input prompt function will look like this:
cout << "Please enter an integer" << endl;
int n=0;
if(cin>>n){
// integer OK, proceed
}
else{
cout << "That was not a numeric value, try again." << endl;
skip_to_int();}
Here's my solution. Beware, it uses C++11. Certainly not necessary if you use std::stringstream, but this should work pretty well.
I presume you don't want negative numbers. I also presume that any number of 0's in front doesn't make the number a 4-digit number. It will cut off padded 0's, so 01234 is a 4 digit number, but 0123 isn't.
void guess(int num_guess[], int size)
{
int number;
// if the length of the number isn't 4, try again until it is
do {
std::cin >> number;
if(std::to_string(number).length() != size)
std::cout << "You messed up the input. How hard could it be? Try again..." << std::endl;
} while(std::to_string(number).length() != size);
// by now, the size is definitely 4. insert it by digit into num_guess
for(int i = size-1; i >= 0; i++) {
num_guess[i] = number%10;
number /= 10;
}
}
#include <iostream>
#include <limits>
int main() {
int i = 0;
std::cout << "Please enter a number with four digits: ";
while( !(std::cin >> i) || !(i / 1000.0f >= 1.0f) )
{
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout << "Invalid entry." << std::endl;
std::cout << "Please enter a number with four digits: ";
}
}
the std::cin.clear() clears all errors flags on current stream structure and std::cin.ignore() cleans up the input stream itself. Once we don't know the size of stream 'til this operation I have used the maximum possible value of a stream size to make sure any stream length could be cleaned.
add #include "math.h"
and change guess
void guess(int num_guess[], int size){
int number = 0;
bool firstTime = true;
do
{
if (!firstTime)
cout << " Error, try again " << endl;
firstTime = false;
cin >> number;
} while (number<pow(10, size-1) || number>=pow(10, size));
for(int i = size-1; i >= 0; i--){
num_guess[i] = number%10;
number /= 10;
}
}

Infinite while loop happens when asking user for 2 numbers

I'm trying to implement a simple game where user is asked for 2 valid integer coordinates between 0 and 10. (int row, int column)
An exemple of what I would realize is:
Insert coordinates: 4C
*Error, number of row and column must be integer
Insert coordinates: 44 2
*Error, number of row or column are too high
Insert coordinates: 4 3
The coordinates you entered are (4,3)
I realized all of these with a do-while cycle.
int r,c;
do{
cout<<"Insert coordinates: ";
cin>>r>>c;
if (cin.fail())
{
cout << "ERROR: Number of row and column must be integer." << endl << endl;
}
if ((r<0 || r>10) || (c<0 || c>10)
{
cout << "*Error, number of row or column are too high [0-10]" << endl << endl;
}
cout<<endl;
}
while (((r<0 || r>10)||(c<0 || c>10)) || cin.fail());
This code doesn't work properly. If I enter 2 numbers between 0 and 10, it works. If I enter a number bigger then 10, it also works. But if I entered a character the program goes into an infinite loop, and does not work properly.
How to implement this to handle errors with character input? Is there a way to recognize, and remain inside the while cycle, if user inputs a character?
If you enter a letter instead of a number, then that letter is not extracted from the input buffer, so your code will continue to fail forever.
If the input fails (why not use e.g. if (!(cin >> r >> c))?) then you can skip the line by doing calling the ignore function:
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
You also want to clear the failbit as it's not cleared automatically, this is done with the clear function.
You can also bypass this problem by getting the whole line, and using std::istringstream for the parsing:
do
{
std::string line;
if (!std::getline(std::cin, line))
... // Could not read from input
std::istringstream iss(line);
int r, c;
if (!(iss >> r >> c))
... // Failed to parse as numbers
...
} while (...);
You could simply check if characters were entered, for example:
if (x >= 0x41 && x <= 0x7A)
cout<<"error, you entered a letter";
(((r<0 || r>10)||(c<0 || c>10)) || cin.fail());
change to
(((r>0) && (r<10))||((c>0) && (c<10))) //It will work, no need to check cin.fail();
If cin fails then it might produce errors in buffer so better to quit the program..
The program goes into an infinite loop because you never clear the fail state. You can simplify your entire loop:
#include <iostream>
using namespace std;
int main()
{
int r = -1;
int c = -1;
bool valid = false;
do
{
cout<<"Insert coordinates: ";
if (cin >> r >> c)
{
if (r >= 0 && r <= 10 && c >= 0 && c <= 10)
{
valid = true;
}
}
else
{
cin.clear();
cin.ignore();
}
if (!valid)
{
cout << "ERROR: Number of row and column must be an integer between 0 and 10." << endl;
}
} while (!valid);
cout << "You entered (" << r << ", " << c << ")" << endl;
return 0;
}

Is there a way to not include a negative number in an average, when entering a negative number is how you terminate the program?

Sorry about last time for those who saw my previous thread. It was riddled with careless errors and typos. This is my assignment:
"Write a program that will enable the user to enter a series of non-negative numbers via an input statement. At the end of the input process, the program will display: the number of odd numbers and their average; the number of even numbers and their average; the total number of numbers entered. Enable the input process to stop by entering a negative value. Make sure that the user is advised of this ending condition."
And here is my code:
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
int number, total1=0, total2=0, count1=0, count2=0;
do
{
cout << "Please enter a number. The program will add up the odd and even ones separately, and average them: ";
cin >> number;
if(number % 2 == 0)
{
count1++;
total1+=number;
}
else if (number >= 0)
{
count2++;
total2+=number;
}
}
while (number>=0);
int avg1 = total1/count1;
int avg2 = total2/count2;
cout << "The average of your odd numbers are: " << avg1 << endl;
cout << "The average of your even numbers are " << avg2 << endl;
}
It seems to be working fine, but when I enter a negative number to terminate the program, it includes it with the rest of the averaged numbers. Any advice to get around this? I know it's possible, but the idea escapes me.
Your main loop should be like this:
#include <iostream>
for (int n; std::cout << "Enter a number: " && std::cin >> n && n >= 0; )
{
// process n
}
Or, if you want to emit a diagnostic:
for (int n; ; )
{
std::cout << "Enter a number: ";
if (!(std::cin >> n)) { std::cout << "Goodbye!\n"; break; }
if (n < 0) { std::cout << "Non-positve number!\n"; break; }
// process n
}
After here:
cout << "Please enter a number. The program will add up the odd and even ones seperately, and average them: ";
cin >> number;
Immediately check if the number is negative
if(number < 0) break;
Now you wouldn't need to use your do-while loop in checking if the number is negative. Thus, you can use an infinite loop:
while(true) {
cout << "Please enter a number. The program will add up the odd and even ones seperately, and average them: ";
cin >> number;
if(number < 0) break;
// The rest of the code...
}
ADDITIONAL:
There is something wrong in your code. You aren't showing the user how much the number of even and odd numbers are, and the total number of numbers entered.
ANOTHER ADDITIONAL: You should use more meaningful variable names:
int totalNumEntered = 0, sumEven = 0, sumOdd = 0, numEven = 0, numOdd = 0;
Of course I am not limiting you to these names. You can also use other similar names.
FOR THE INTEGER DIVISION PROBLEM:
You must cast your expression values to the proper type (in this case, it is float). You should also change the averages variables' types to float:
float avg1 = float(total1) / float(count1);
float avg2 = float(total2) / float(count2);
Immediately after cin >> number, check for < 0, and break if so. Try to step through the program line by line to get a feel for the flow of execution. Have fun learning, and good luck!