While using the boolean check for the int num this loop doesn't work. The lines after it go unrecognized. Enter and integer like 60 and it just closes. Did I use isdigit wrong?
int main()
{
int num;
int loop = -1;
while (loop ==-1)
{
cin >> num;
int ctemp = (num-32) * 5 / 9;
int ftemp = num*9/5 + 32;
if (!isdigit(num)) {
exit(0); // if user enters decimals or letters program closes
}
cout << num << "°F = " << ctemp << "°C" << endl;
cout << num << "°C = " << ftemp << "°F" << endl;
if (num == 1) {
cout << "this is a seperate condition";
} else {
continue; //must not end loop
}
loop = -1;
}
return 0;
}
When you call isdigit(num), the num must have the ASCII value of a character (0..255 or EOF).
If it's defined as int num then cin >> num will put the integer value of the number in it, not the ASCII value of the letter.
For example:
int num;
char c;
cin >> num; // input is "0"
cin >> c; // input is "0"
then isdigit(num) is false (because at place 0 of ASCII is not a digit), but isdigit(c) is true (because at place 30 of ASCII there's a digit '0').
isdigit only checks if the specified character is a digit. One character, not two, and not an integer, as num appears to be defined as. You should remove that check entirely since cin already handles the validation for you.
http://www.cplusplus.com/reference/clibrary/cctype/isdigit/
If you're trying to protect yourself from invalid input (outside a range, non-numbers, etc), there are several gotchas to worry about:
// user types "foo" and then "bar" when prompted for input
int num;
std::cin >> num; // nothing is extracted from cin, because "foo" is not a number
std::string str;
std::cint >> str; // extracts "foo" -- not "bar", (the previous extraction failed)
More detail here:
Ignore user input outside of what's to be chosen from
Related
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);
}
I'm trying to only allow integer values into my program, so I've made the following function. The function is similar to other ones I've seen online, and mine seems to work just fine up until I add an ! in front of it to check if something is not an int.
Function to check if input is an integer:
bool isInteger(std::string s)
{
for (int i = 0; i < s.length(); i++)
{
if (isdigit(s[i]) == false)
{
return false;
}
return true;
}
}
Function being put to use:
int getLevel()
{
int level;
std::cout << "Level One\n";
std::cout << "Level Two\n";
std::cout << "Level Three\n";
std::cout << "Level Four\n";
std::cout << "Level Five\n";
std::cout << "Enter your level (1-5): ";
std::cin >> level;
while (!isInteger(std::to_string(level)) || level < 1 || level > 5)
{
std::cout << "Enter an integer value between 1-5 inclusive: ";
std::cin >> level;
}
clrscr();
return level;;
}
I believe the function works just fine until I put the ! in front of it. I am trying to only allow integer input into my program, and when I enter a double or string, the console becomes flooded with the message "Enter an integer value between 1-5 inclusive: " and doesn't give any time to enter an input. I am fairly new to c++ programming and could use some advice. Thank you!
std::cin >> level;
will try to read an integer and it will never read anything other than an integer. If this fails std::cin's failbit is set and further input operations (like std::cin >> level; inside the loop) are skipped.
You need to check if the reading succeeded and ignore the current input if not. Like this for example:
std::cout << "Enter your level (1-5): ";
while(!(std::cin >> level) || level < 1 || level > 5) {
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
std::cout << "Enter an integer value between 1-5 inclusive: ";
}
As little semi-related hint: level will always be an integer. Converting it to a string will always be the string-representation of an integer, so isInteger(std::to_string(level)) will always be true, unless level is negative, because you don't check for the sign.
Also that return true; in isInteger must be outside the loop, else you only check the first character.
Thanks to all the replies and clarification, I've managed to come up with a solution of my own.
New isInteger function that now checks for everything that is needed including inputs like "0004" that a user suggested above:
bool errorCheck(std::string s)
{
int intLevel;
std::stringstream tempLvl(s);
tempLvl >> intLevel;
for (int i = 0; i < s.length(); i++)
{
if (isdigit(s[i]) == false || s[0] == '0' || intLevel < 1 || intLevel > 5)
{
return false;
}
}
return true;
}
The method in action:
std::cout << "Enter your level (1-5): ";
std::cin >> stringLevel;
while (!errorCheck(stringLevel))
{
std::cout << "Enter an integer value between 1-5 inclusive: ";
std::cin >> stringLevel;
}
std::stringstream lvl(stringLevel);
lvl >> level;
clrscr();
return level;
}
Please let me know if you spot any problems with the code or have any easier solutions. Thanks for all the help!
ok i am gonna tell u the fact that console input extracts the input from console so if u ever tried to do something like that
i.e read string in place of integer the cin is going to be in bad state you can check this fact by putting an if like this
if(!cin>>level) break;
and u will find it working actually stream takes input from the console and convert it to boolean value so u can always check it's state bad state return false else true...... ..
SO,finally the bug is in cin>>level...
I hope u understood.... also check out that return true statement..
i am gonna put u reference link for more answer on this bug...
user enters String instead of Int
This code works fine if I enter something that isn't a number in, e.g. F: it will print the error message. However, if I enter e.g. 2F2 or , it will take the 2 and pass the check, continue in my code and on the next cin >> statement it will put the F in, and then it loops back and puts the 2 in.
How do I make it so it only accepts a single number e.g. 2 and not e.g. 2F2 or 2.2?
int bet = 0;
// User input for bet
cout << " Place your bet: ";
cin >> bet;
cout <<
// Check if the bet is a number
if (!cin.good())
{
cin.clear();
cin.ignore();
cout << endl << "Please enter a valid number" << endl;
return;
}
bool Checknum(std::string line) {
bool isnum = true;
int decimalpoint = 0;
for (unsigned int i = 0; i < line.length(); ++i) {
if (isdigit(line[i]) == false) {
if (line[i] == '.') {
++decimalpoint; // Checks if the input has a decimal point that is causing the error.
}
else {
isnum = false;
break;
}
}
}
if (decimalpoint > 1) // If it has more than one decimal point.
isnum = false;
return isnum;
}
If you take a string from the user, this should work. You can convert the string to an integer or a float(stoi or stof, respectively). It may not be the best solution there is, but this is what I have. Excuse the indentation.
Do getline to read one whole line of input from cin.
Create a stringstream to parse the string you got.
In this parser, read the number; if it fails - error
Read whitespace; if it doesn't arrive to the end of string - error
#include <sstream>
...
int bet = 0;
std::cout << " Place your bet: ";
while (true)
{
std::string temp_str;
std::getline(cin, temp_str);
std::stringstream parser(temp_str);
if (parser >> bet && (parser >> std::ws).eof())
break; // success
cout << endl << "Please enter a valid number" << endl;
}
This code keeps printing the error message until it receives valid input. Not sure this is exactly what you want, but it's pretty customary UI.
Here >> ws means "read all the whitespace". And eof ("end of file") means "end of the input string".
Ok, here's the code to add indefinite numbers and present the sum in c++. But error is that addition taking place is of first number and the last digits of all the other numbers. For example if i want to add 30 + 40 + 55 + 70, my program counts 30 + 0 + 0 + 5 + 0 = 35. What am I doing wrong?
#include <iostream>
using namespace std;
int main()
{
int num = 0;
int sum = 0;
cout << "Please enter numbers you want to add and end with N or n: ";
for (;;)
{
cin >> num;
sum += num;
cout << endl;
char indicator ('q');
cin >> indicator;
if (( indicator == 'n') || (indicator == 'N'))
break;
}
cout << "The sum is: " << sum << " ";
return 0;
}
I'm not sure I fully understand what you are trying to do, but if you want to add a list of integers terminated by an N (or n) character, then you should read each entity as a string, see if it's the terminating character, and if it's not, then convert it to an integer:
int sum = 0;
while (true) {
std::string s;
std::cin >> s;
if (tolower(s[0]) == 'n')
break;
sum += std::stoi(s);
}
Of course, the above code is only a skeleton -- in production code, you should always check if I/O operations succeeded and sanitize your input. A more complete example would be:
std::string s;
while (std::cin >> s) {
int ch = s[0];
if (ch > 0 && tolower(ch) == 'n')
break;
try {
sum += std::stoi(s);
} catch (const std::invalid_argument &e) {
// handle conversion error
break;
} catch (const std::out_of_range &e) {
// handle out-of-range error
break;
}
}
When you read the indicator, you extract the next non-blank character from the input stream; if the user has entered a number, this is the first digit. There are several ways of working around this.
The simplest is simply to loop on:
while ( std::cin >> num ) {
sum += num;
}
The input will fail if the next input doesn't have the form of a number (without extracting it). (This also has the advantage that you don't use the input if it fails for some reason.) This is more or less the standard idiom.
If you really do want to check for the 'n', you can use std::cin.peek() to look ahead one character, without extracting it. This doesn't skip white space, however, so you might want to do std::cin >> std::ws first. In this case, you'd probably want to wrap it in a function:
bool
terminationRequested( std::istream& source )
{
source >> std::ws;
return source.peek() == 'n' || source.peek() == 'N';
}
and then
while ( ! terminationRequested( std::cin ) ) {
int num;
std::cin >> num;
if ( ! std::cin ) {
// error...
}
sum += num;
}
You still have to check for a possible error after std::cin >> num. Otherwise, if the user enters "a", you'll end up in an endless loop, adding an undefined value to sum.
Alternatively, another frequent idiom is too use putback to return the indicator to the stream:
while ( std::cin >> indicator && indicator != 'n' && indicator != 'N' ) {
std::cin.putback( indicator );
std::cin >> num;
if ( ! std::cin ) {
// error...
}
sum += num;
}
Again, you'll have to handle the errors somehow. Using num if std::cin >> num fails is undefined behavior.
It's because you read the indicator character which will remove and ignore the next input digit by the user from the input stream.
I have what seems like a pretty simple, beginner question that I must be missing something obvious. I am just trying to prompt the user to input a 4 digit number and then take in the input as an array, splitting up the digits to be by themselves. I thought it hade something to do with "cin >> input[4]" I just can't seem to get the right answer.
int main()
{
int input[4]; //number entered by user
cout << "Please enter a combination to try for, or 0 for a random value: " << endl;
cin >> input[4];
}
When I go to run it, I get an error message "Stack around the variable was corrupted.
I tried looking at similar examples in other questions but I just can't seem to get it right. I need the input as one 4 digit number and then split it up to a 4 position array.
If anyone could help I would greatly appreciate it.
Your array is of size 4, so elements have indicies 0 .. 3; input[4] is located behind the end of your array so you are attemping to modify memory not allocated or allocated for other stuff.
This will work for you:
cin >> input[0];
cin >> input[1];
cin >> input[2];
cin >> input[3];
You do not need an arry to input 4 digit number.
int in;
int input[4];
cin >> in;
if(in>9999 || in < 1000) {
out << "specify 4 digit number" << endl;
return;
}
input[0] = in%1000;
input[1] = (in-1000*input[0])%100;
input[2] = (in-1000*input[0]-100*input[1])%10;
input[3] = in-1000*input[0]-100*input[1]-input[2]*10;
The problem is that you are trying to read in a character that does not exist (the one at index 4).If you declare input as int input[4];, then it doesn't have any characters at index 4; only indices 0...3 are valid.
Perhaps you should just use an std::string and std::getline(), and you could then parse the user input to integers however you like. Or you can try
std::cin >> input[0] >> input[1] >> input[2] >> input[3];
if you can live with the constraint that the numbers must be whitespace-separated.
This includes a small bit of error checking:
int n = 0;
while( n < 1000 || n >= 10000 ) // check read integer fits desired criteria
{
cout << "enter 4 digit number: ";
cin >> n; // read the input as one integer (likely 10 digit support)
if( !cin.good() ) // check for problems reading the int
cin.clear(); // fix cin to make it useable again
while(cin.get() != '\n'); // make sure entire entered line is read
}
int arr[4]; // holder for desired "broken up" integer
for( int i=0, place=1; i<4; ++i, place *= 10 )
arr[i] = (n / place) % 10; // get n's place for each slot in array.
cout << arr[3] << " " << arr[2] << " " << arr[1] << " " << arr[0] << endl;