How can I cin an unsigned long long without error? - c++

OK, so this is my code:
cout << "What is your p value?" << endl;
unsigned long long p;
cin >> p;
cin.ignore();
cout << endl;
cout << "What is your q value?" << endl;
unsigned long long q;
cin >> q;
cin.ignore();
cout << endl;
I put the first huge value--that is, p--in, and something gets put in to q automatically even with these cin.ignore()'s. What issues am I not seeing here? Please let me know if you need more information if it's not obvious to you.
[Adding information from a comment: the input value was 92896134244099469431, which exceeds 266.]

You say you entered a "huge value". If that value exceeds the upper bound of unsigned long long, then cin >> p; will fail.
A quick experiment indicates that once that happens, cin >> q; doesn't do anything, and no value is stored in q. The value of p will probably be 18446744073709551615, or 264-1.
You need to check whether each input operation succeeded or failed, and decide how to handle any errors.
You also need to update your question to indicate exactly what input you provided to your program.

Related

Validating Input C++ [duplicate]

This question already has answers here:
How to test whether stringstream operator>> has parsed a bad type and skip it
(5 answers)
Closed last year.
int num = 0;
while(true){
cout << "enter num: ";
cin >> num;
if(!(num)){
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "num must be an int" << endl;
}else if(num <= 0){
cout << "num must be greater than 0" << endl;
}else if(static_cast<double>(static_cast<int>(num)) != num){
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "num must be an int" << endl;
}else{
break;
};
};
I've been looking through SO and I found some threads that addressed similar issues, but nothing that is specific to what I'm trying to achieve. I'm only trying to accept integer inputs, no decimals, no strings, no characters. If I enter in a negative number or 0, it'll throw me an error saying "num must be greater than 0." If I enter in a, it'll throw me an error saying "num must be an int." If I enter 1.0, it'll throw me an error saying "num must be an int."
The problems I'm running into with this is when I enter in 0 for example, instead of executing the conditional statement that checks (num <= 0), it runs the conditional statement that says (!(num)). The other problem I'm running into is when I enter in a value that has a decimal, like 2.0, it'll truncate the numbers after the decimal and send in 2 as the value, completely glossing over the check to see if it's a decimal value and telling the program that it's a valid integer when it's not.
Does anyone have a solution for this, or an article link that solves problem like mines? Thank you!
This:
cin >> num;
if(!(num))
Should be this:
if (!(cin >> num))
You are checking the value of num when you should instead be checking the error state of cin. operator>> returns a reference to the input stream, which is then implicitly convertible to bool, where false means the stream encountered an error.
Also, this is completely useless:
else if(static_cast<double>(static_cast<int>(num)) != num)
Casting an int value to an int is a no-op, and casting an int value to a double back to an int will get you the original int value.
num is an int, it can't read in anything else. So, by the time your code reaches this point, you know num must be holding a valid int value. However, if the user had actually entered a floating-point number instead, operator>> would have stopped reading at the decimal point, leaving it and the remaining fractional value in cin's input buffer for later reading.
Also, the 2nd call to cin.ignore() is wrong. By that point, operator>> was able to read in an int value, it just wasn't satisfactory to you. So don't ignore subsequent input yet.
If you really need to differentiate between integer and floating-point input, you will have to read in the input as a string first, and then parse it to see what it actually holds, eg:
int num = 0;
string s;
size_t pos;
while (true){
cout << "enter num: ";
if (!(cin >> s)){
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "input error, try again" << endl;
}
else{
try{
num = stoi(s, &pos);
if (pos != s.size()) throw invalid_argument("");
if (num > 0){
break;
}
cout << "num must be greater than 0" << endl;
}
catch (const exception &){
cout << "num must be an int" << endl;
}
}
}
Online Demo

Code breaks after anwser with a dot and skips the rest of the code

If i don't use dots like 1.5 it will break but if it's whole number like 15 it works perfectly
I tried to looking for it in the internet but didn't find the fix it
#include <iostream>
using namespace std;
int main()
{
int n,sk,i,a,p,b,c;
int kiek=0;
cout << "insert how many shops did he went to" << endl;
cin >> n;
b=n;
cout << "how many thing did he buy in every shop" << endl;
cin >> p;
c=p;
for(int n=0; b>n; n++)
{
a=0;
for (int i=1; i<=c; i++)
{
cout << "insert "<< i << " product price"<< endl;
cin >> sk;
a=a+sk;
}
cout<< "spent " << a<< " pmoney"<< endl;
}
return 0;
}
it should let me type how much did he spent with every product but if i add a . it skips everything and shows only one
Problem
An integer type cannot store decimal values.
When you execute int sk; cin >> sk; and you enter "1.5", the operator >> will store 1 in sk and leave .5 in the stream. The next time you execute cin >> sk, the stream will try to read the next integer with what is left in the stream, but will fail because "." cannot be converted to an integer, leaving your stream in a 'fail' state. For this point, all cin instructions will fail to read the next integer.
Solution
To fix the problem, I suggest to declare price values as doubles: double a,sk. However, the same problem will occur if you enter an invalid floating point value. I strongly suggest to correctly manage stream errors and react accordingly. You can access the state using rdstate() or its related methods (good, fail, bad, eof).

Infinite loop without accepting input

I am writing a simple C++ Program which allocates dynamic memory to my Program and then deletes this memory. Here is my Program:
#include <iostream>
#include <new>
using namespace std;
int main ()
{
int i,n;
int * p;
cout << "How many numbers would you like to type? ";
cin >> i;
p= new (nothrow) int[i];
if (p == nullptr)
cout << "Error: memory could not be allocated";
else
{
for (n=0; n<i; n++)
{
cout << "Enter number: ";
cin >> p[n];
}
cout << "You have entered: ";
for (n=0; n<i; n++)
cout << p[n] << ", ";
delete[] p;
}
return 0;
}
In the above program when I input the value of i (Number of inputs) equal to or less than 2 Billion than this program works as expected. However when I enter anything above 2 Billion like 3 Billion or higher, this program goes in an infinite loop without taking a number input in my for loop.
I am expecting this program to fail when I enter a very high value for i by saying it could not allocate the memory.
As per my understanding, I think when I enter a very high value of int i, I am going out of bound for integer data type but still in this case, it should take number input from me in for loop as I have a cin statement there instead of going in for loop or memory allocation should fail simply.
When I changed type of i from int to long then it works but I am curious to know for i of type int, why it goes in infinite loop instead of taking values when it sees cin in for loop?
I am running this program on Mac OS X and compiling it using g++ compiler.
1) You are trying assign to int value bigger than 2147483647, which is usually maximum value for this type.
Generally, if you want to handle such a large numbers, you should use long long int (or something from <cstdint> for better portability).
2) You don't clear state of cin after it fails.
The code bollow generate infinite loop:
int i = 0;
while (i <= 0)
{
std::cout << "Enter a number greater than 10..." << std::endl;
std::cin >> i;
}
You can solve it this way:
int i = 0;
while (i <= 0)
{
std::cout << "Enter a number greater than 10..." << std::endl;
if (!(std::cin >> i))
{
std::cin.clear(); // Clear error flag
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // Remove incorrect data from buffer
}
}
3) You are trying to create a really big array. You need a few GiB of
contiguous memory to this. Even if you succeed allocate the array, it is still a design issue. You should use many of smaller arrays or use/create a suitable container.
The maximum value of a 32 bit signed integer is 2^31-1, namely 2147483647.
Now, if you assign a higher value to an Int variable the behaviour is quite unexpected, try and see what i actually contains.
BTW, what do you mean by "infinite loop"? Does the program crash or does it never end executing?

C++ cin input stored directly to pass by reference variable - dangerous?

Is it dangerous to have cin input directly assigned to a double variable that is passed by reference? If so, what measures can I take to defend against dangerous input - aside from not passing by reference.
Example below:
void samplefunction(double &var1, double &var2)
{
cout << "Enter something: ";
cin >> var1;
cout << endl;
cout << "Enter something: ";
cin >> var2;
}
The short answer, is no, as the cin >> operator will only read as much data as it requires to fill the type. The rest is discarded until the next whitespace. You may not get correct values, for example if someone feeds in "ABCDEF" instead of "1.0," but you won't have to worry about a buffer overflow.

c++ loop runs forever without waiting for input

I am trying to write code that will loop and input user input to a class and print out a chart. This is my main method:
int main()
{
Company productMatrix;
int inputNumber = 0;
cout << "enter the salesman id or -1 to quit." << endl;
cin >> inputNumber;
while(inputNumber != -1)
{
int salesman = inputNumber;
cout << "enter the product id." << endl;
cin >> inputNumber;
int product = inputNumber;
cout << "enter the amount sold." << endl;
cin >> inputNumber;
double dollarValue = inputNumber;
productMatrix.inputSales(salesman, product, dollarValue);
cout << "enter the salesman id or -1 to quit." << endl;
cin >> inputNumber;
}
productMatrix.printChart();
cout << "Goodbye!";
return 0;
}
when I run the program, it will let me input one set of data and then loop forever without waiting for me to stop. This is what it looks like:
enter the salesman id or -1 to quit.
3
enter the product id.
2
enter the amount sold.
55.99
enter the salesman id or -1 to quit.
enter the product id.
enter the amount sold.
enter the salesman id or -1 to quit.
enter the product id.
enter the amount sold.
// etc...
I'm guessing there is something wrong with my loop. How can I fox this?
The problem is with following line.
double dollarValue = inputNumber;
inputNumber is a integer type and dollar value is a float. So there is a type mismatch. You can create another variable like dollarInput and store the dollar value there
You're writing a double 55.99 to an integer, so cin takes 55 and it has '.' in the buffer which is always !=-1 but never gets read into as integer.
inputNumber is an int. But you entered a value (55.99) that can not be interpreted as an int. This put cin into an error state. Until the error is cleared, all future operations with cin fail. So it doesn't wait for your input, and the variables retain their values, and you can never get that -1 that the loop needs to terminate.
To check for an error, just use a plain old if statement:
if (cin) {
// cin is okay
}
else {
// cin is not okay
}
You can also be a little more concise and put your input operation directly in an if statment:
if (cin >> inputNumber) {
To clear the error:
cin.clear();
You will also probably need to clear the input stream, otherwise the erroneous input will remain in the input buffer, and cin will just try to read it again:
cin.ignore(); // discard one character from the input buffer
// or
cin.ignore(N); // discard N characters from the input buffer
Anyway, that's the cause of the infinite loop. But if you had just input directly into a double, instead of an int, you wouldn't have seen this issue. Isn't that what you want anyway?
To add to prajmus's answer, you can see the additional 'junk' in the input stream by adding the following 'cin' read:
...
double dollarValue = inputNumber;
productMatrix.inputSales(salesman, product, dollarValue);
cout << "enter the salesman id or -1 to quit." << endl;
double myDbl;
cin >> myDbl;
cout << "read the following double:" << myDbl << endl;
...
The added "cin >> myDbl" will read the '.99' from the input stream and the added cout will yield:
0.99