I have to write a program that receives unsigned inputs and places them in an array of unsigned values. If a non-unsigned value is entered, I call a function called "die" to output an error message, and terminate the program. Here is the code I have written for my input function:
void input(unsigned a[], unsigned elements){
cout << "Enter unsigned numbers one at a time, each followed by enter." << endl;
for (unsigned i = 0; i < elements;i++){
cout << "[" << i << "]: "; // outputs each index as user is inputting
cin >> a[i];
if ( sizeof(a[i]) != sizeof(unsigned) || a[i]<0 ){
die("Invalid input. Program will now exit.");
}
}
}
I've checked and the die function performs its job properly on its own. Here is the output this code yields when a char is entered:
Enter unsigned numbers one at a time, each followed by enter.
[0]: d
[1]: [2]: [3]: [4]: [5]: [6]: [7]: [8]: [9]: Press any key to continue . . .
As you can see, the die function is never successfully called because the if statement preceding it does not evaluate to be false. Furthermore, I'm not sure why my program shows whitespace for the rest of the values in the array. How could I rewrite the if statement to call the die function whenever the input received is not an unsigned?
This is because your if() expression can never be mathematically evaluated as true.
Let's take a look:
if ( sizeof(a[i]) != sizeof(unsigned) || a[i]<0 ){
Let's break this down into two parts. Part 1:
a[i] is an unsigned. Therefore
sizeof(unsigned) != sizeof(unsigned)
will always be false.
Part 2. And because a[i] is unsigned, it can never be negative, therefore
a[i] < 0
will also always be false.
And that's what your die() will never execute.
Why the presented code doesn't work has been answered previously, I will try to react on MV94's comment how to solve this:
Instead of reading directly into the unsigned int variable, read to signed variable of a bigger size than unsigned int and perform the check before assigning into the a[i]. Exact type choice depends on your architecture (you can try intmax_t from <cstdint>). Of course this will only again handle numbers within some range, if user enters number big enough to exceed your signed type, you have similar problem. As someone mentioned before, check that your input conversion succeeded.
Related
Hey guys beginner in C++ and coding in general. I am currently making a tictactoe program. For the part of the program I am validating user input. Since it is a 3x3 table, I want to make sure their input is an integer and that they choose a number between 1~9.
To do this I wrote
//Validating user input
void move() {
std::cout << "It's Player" << player << "'s turn!\n";
while(!(std::cin >> position)){
std::cout << "Please choose a NUMBER between 1~9!\n";
std::cin.clear();
std::cin.ignore();
}
while(position < 1 || position > 9){
std::cout << "Please choose a number BETWEEN 1~9!\n";
std::cin.clear();
std::cin.ignore();
}
while(board[position - 1] != " ") {
std::cout << "Already filled please choose another number between 1~9!\n";
std::cin >> position;
}
}
It works but for some reason when I put in an input like 10, it would print Please choose a number BETWEEN 1~9! twice (for each digit) and if I input in for example "apple" it would print Please choose a NUMBER between 1~9! four times (for each character). How do i make it just print out the statement once?
Thank you!
Let me try to explain to you the problem. It is a little bit subtle and not that easy to understand. Both other answers adress only the obvious part.
Then, let us first recap that:
The boolean condition in the while statement is loop invariant. Meaning, it will not be modified within the loop. Whatever it was before the loop, will be the same after the loop body has been executed. The condition will never change.
So, for the case where you enter a wrong number:
If the input number is correct (1..9) and the while statement starts to evaluate the boolean expression, it will be false in this case and the loop will not be entered.
If the number is out of your selected bounds (<1 or >9), then the boolean condition is true. The while loop starts, but the condition relevant variable will not be changed in the loop boody and hence, the boolean expression is always true. The loop will run forever.
Additionally, and now comes the answer to your first question, the following will happen:
The text "Please choose a number BETWEEN 1~9!\n" will be shown (first time)
clear will be called for std::cin. The failbit was not set, but anyway. This does not harm
The ignore function is an unformatted input function. It will actively read the next character from the input buffer, which is the end of line `'\n' character.
We enter again the while statement. The condition is still true (position was not modified in the loop body), and we enter the loop again.
The text "Please choose a number BETWEEN 1~9!\n" will be shown (second time)
clear will be called for std::cin. The failbit was not set, but anyway. This does not harm
The ignore function is a formatted input function. It will actively read the next character from the input buffer. But there is none. So it will wait until a key is pressed. For example "enter". After that, it would go back to number 5.
By the way. If you would now enter "abc" then you would see the text 4 times for a,b,c and enter.
So, please remember: ignore is an input function!
Next. It is important to understand, that if you enter an unexpected value, like "apple" instead of "3", the formatted input function >> can do no conversion and sets the failbit. It will also not extract further wrong characters from the input stream (std::cinis a buffered stream). The characters that could not be converted are still in the buffer and wil be read next time.
Please read here about formatted/unformatted input. And especially read about the extraction operatpr >> here..
There you can read the following:
If extraction fails (e.g. if a letter was entered where a digit is expected), zero is written to value and failbit is set.
OK, understood. Then, what is going on here, if you enter "abc". Basically, the same as above.
Enter abc
The boolean condition !(std::cin >> position)will be evaluated to true, because an 'a' was read and cannot be converted to a number.
The std::cin's failbit will be set. The variable positionwill be set to 0.
"Please choose a NUMBER between 1~9!\n" will be shown
The failbit will be reset
Ignore will extract exactly the one wrong character and discard it
std::cin >> position`` will be called again and extract the next wrong character 'b'. 3., 4., 5., 6. will be done again. Until the last charcter in the buffer, the newline '\n' will be extracted. Then you may enter the next number.
The fix for that problem is simple:
ignore has a parameter, where you can specify, how many characters shall be ignored. So, not only one, but all until the end of line.
You should write:
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
This will ignore all bad input.
And to fix your whole program, you could write at the top:
while (!(std::cin >> position) or (position < 1 ) or ( position > 9)) {
std::cout << "Please choose a NUMBER between 1~9!\n";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
while(position < 1 || position > 9){
This while loop will continue running as long as position is less than 1 or greater than 9, that's what this says.
But there's nothing in the while loop itself that changes the value of position. For that simple reason, if position's value at this point is outside of the range of 1-9, this while loop will execute forever.
You always need to keep in mind The Golden Rule Of Computer Programming: your computer always does exactly what you tell it to do instead of what you want it to do. Here, you told your computer to execute this while loop as long as position is less than 1 or greater than 9, so this is what your computer will do until this is no longer the case.
You can change your code as this. With this you run your while loop ones for every input. Until you get the value as you like. If the value is as you wish, you get out of the loop with break
std::cout << "Please choose a NUMBER between 1~9!\n";
while(std::cin >> position){
std::cin.clear();
std::cin.ignore();
if(position < 1 || position > 9){
std::cout << "Please choose a number BETWEEN 1~9!\n";
}else{
break;
}
}
I'm very new to C++ programming, and have written a simple program to calculate the factorial of an integer provided by the user. I am attempting to account for inputs which would cause an error, or do not make sense (e.g. I have accounted for input of a negative number/-1 already). I want to print out an error if the user enters a number whose factorial would be larger than the maximum integer size.
I started with:
if(factorial(n) > INT_MAX)
std::cout << "nope";
continue
I tested this with n = ~25 or 26 but it doesn't prevent the result from overflowing and printing out a large negative number instead.
Second, I tried assigning this to a variable using a function from the 'limits.h' header and then comparing the result of factorial(n) against this. Still no luck (you can see this solution in the code sample below).
I could of course assign the result to a long and test against that but you wouldn't have to go very far until you started to wrap around that value, either. I'd prefer to find a way to simply prevent the value from being printed if this happens.
#include <iostream>
#include <cstdlib>
#include <limits>
int factorial(int n)
{
auto total = 1;
for(auto i = 1; i <= n; i++)
{
total = total * i; //Product of all numbers up to n
}
return total;
}
int main()
{
auto input_toggle = true;
auto n = 0;
auto int_max_size = std::numeric_limits<int>::max();
while(input_toggle = true)
{
/* get user input, check it is an integer */
if (factorial(n) > int_max_size)
{
std::cout << "Error - Sorry, factorial of " << n << " is larger than \nthe maximum integer size supported by this system. " << std::endl;
continue;
}
/* else std::cout << factorial(n) << std::endl; */`
As with my other condition(s), I expect it to simply print out that small error message and then continue asking the user for input to calculate. The code does work, it just continues to print values that have wrapped around if I request the factorial of a value >25 or so. I feel this kind of error-checking will be quite useful.
Thanks!
You are trying to do things backwards.
First, no integer can actually be bigger than INT_MAX, by definition - this is a maximum value integer can be! So your condition factorial(n) > int_max_size is always going to be false.
Moreover, there is a logical flaw in your approach. You calculate the value first and than check if it is less than maximum value allowed. By that time it is too late! You have already calculated the value and went through any overflows you might have encountered. Any check you might be performing should be performed while you are still doing your calculations.
In essence, you need to check if multiplying X by Z will be within allowed range without actually doing the multiplication (unfortunately, C++ is very strict in leaving signed integer overflow undefined behavior, so you can't try and see.).
So how do you check if X * Y will be lesser than Z? One approach would be to divide Z by Y before engaging in calculation. If you end up with the number which is lesser than X, you know that multiplying X by Y will result in overflow.
I believe, you know have enough information to code the solution yourself.
Consider the following code to calculate the sum of numbers which are inputted by user during runtime :
#include <iostream>
using namespace std;
int main()
{
int sum = 0; //stores sum of numbers
int taken; //stores the number inputted by the user
while(cin>>taken)
{
sum += taken;
}
cout<<"The sum is : "<<sum;
return 0;
}
Now, I expect the loop to exit on its own and display the sum of numbers inputted by user as soon as the user enters 0 because while(0) evaluates to false as a result of which the loop terminates and hence the statement printing sum of numbers should be executed.
But this does not occur.
So, why does the while loop does not exit when the user enters 0 as an input ?
Please consider my below sample run of program :
3
2
1
0
5
(Then finally pressing ctrl-z for indicating end-of-file)
The sum is : 11
Here is my doubt in above sample run :
After I had entered 0, I should not be prompted for further inputs because according to me, while(0) should evaluate to false, and therefore the statement telling the sum of numbers entered till 0 should be printed on the screen, which does not happen.
The value of cin>>taken is not the value of taken. That's your misunderstanding.
You could write this code
while (cin >> taken && taken != 0)
{
...
}
which would do what you want.
As a side note the value of cin >> taken reflects the stream state. Normally in a boolean context a stream evaluates to true, but if some kind of error has occured then the stream evaluates to false. This is why while (cin >> taken) effectively means read until no more integers can be read.
So, why does the while loop does not exit when the user enters 0 as an input ?
while (cin >> taken) doesn't evaluate to while (taken) but to while (bool(cin)). After reading into the variable, cin will be casted to bool, which checks if the stream has errors.
From the docs:
Return value
true if the stream has no errors, false otherwise.
I have received a task that does not actually specify, what range of input one of my functions should expect (only, that it is always going to be a positive integer), and the input is decided runtime. Can I somehow test if the type I selected can actually hold the value it was fed to?
An illustration of what I am hoping to do:
char test;
std::cin >> test;
if(MAGIC)
{
std::cout << "Error." << std::endl;
}
With the magical part (or even the preceeding line) being the test I'm looking for.
It should work like this:
stdin: 100 -> no output
stdin: 1000000 -> Error.
For most data types you can check the error state of the input stream as described here. However, this would not work for some other types, such as char from your post, because std::cin >> test would read data as a single character, i.e. '1' which is not what you need to achieve.
One approach is to read the number into std::string, and compare it to the max() obtained through limits:
std::string max = std::to_string(std::numeric_limits<char>::max());
std::string s;
std::cin >> s;
bool cmp = (s.size() == max.size()) ? (s <= max) : (s.size() < max.size());
std::cout << s << " " << cmp << std::endl;
Demo.
Note: The above code makes an assumption that the data entered is a number, which may be arbitrarily large, but must not contain characters other than digits. If you cannot make this assumption, use a solution from this Q&A to test if the input is numeric.
I think the answer may be in https://stackoverflow.com/a/1855465/7071399 to know where to get the limits, then refer to https://stackoverflow.com/a/9574912/7071399 to get inspiration to your code (given you can use a long int or a char array to store the number and then check if it fits in the integer value).
I'm building a program for the Euler projects question 3, and while that might not really matter as a result I'm current trying to make this code take a number and test if it is prime or not. Now then before I get to troubleshoot the function it gives me the error "floating point exception" right after inputting the number. Here's the code:
int main()
{
int input;
cout << "Enter number: " << endl;
cin>> input;
int i = input/2;
int c;
for (i>0; i--;) {
c= input%i;
if (c==0 || i == 1)
cout << "not prime" << endl;
else
cout << "prime" << endl;
}
return 0;
}
so essentially why is it giving me a floating point exception and what does that even mean?
A "floating point number" is how computers usually represent numbers that are not integers -- basically, a number with a decimal point. In C++ you declare them with float instead of int. A floating point exception is an error that occurs when you try to do something impossible with a floating point number, such as divide by zero.
for (i>0; i--;)
is probably wrong and should be
for (; i>0; i--)
instead. Note where I put the semicolons. The condition goes in the middle, not at the start.
Lots of reasons for a floating point exception. Looking at your code your for loop seems to be a bit "incorrect". Looks like a possible division by zero.
for (i>0; i--;){
c= input%i;
Thats division by zero at some point since you are decrementing i.
Since this page is the number 1 result for the google search "c++ floating point exception", I want to add another thing that can cause such a problem: use of undefined variables.
Problem is in the for loop in the code snippet:
for (i > 0; i--;)
Here, your intention seems to be entering the loop if (i > 0) and
decrement the value of i by one after the completion of for loop.
Does it work like that? lets see.
Look at the for() loop syntax:
**for ( initialization; condition check; increment/decrement ) {
statements;
}**
Initialization gets executed only once in the beginning of the loop.
Pay close attention to ";" in your code snippet and map it with for loop syntax.
Initialization : i > 0 : Gets executed only once. Doesn't have any impact in your code.
Condition check : i -- : post decrement.
Here, i is used for condition check and then it is decremented.
Decremented value will be used in statements within for loop.
This condition check is working as increment/decrement too in your code.
Lets stop here and see floating point exception.
what is it? One easy example is Divide by 0. Same is happening with your code.
When i reaches 1 in condition check, condition check validates to be true.
Because of post decrement i will be 0 when it enters for loop.
Modulo operation at line #9 results in divide by zero operation.
With this background you should be able to fix the problem in for loop.