Infinite loop without accepting input - c++

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?

Related

if/else statement with arrays is failing

So the code is really simple, its just a main(), but there is something wrong in the if/else statement in the while cycle and I dont't know what it is, I thought this is how it supposed to work, but clearly its not.
The code is creating a 11-element array, but the 0th element of the array is typed in by the user. So for example I type in 5, the array have the numbers from 5 to 15. Then the program shows you the numbers in the array. Then you can type in any numbers, and if your number is equal to any of the numbers in the array, then the program should say: "YEES!!!".
The problem is, the program always says, what it should only if the input number is not equal to any number in the array...
So can please someone explain me why the if/else statement is failing?
I also wrote this in Code::Blocks if that changes something...
The code:
#include <iostream>
using namespace std;
int main(){
int numbers[11];
int input;
cout << "Type in a number: ";
cin >> input;
for (int i=0; i<11; i++){
numbers[i] = input +i;
}
for (int i=0; i<11; i++){
cout << numbers[i] <<endl;
}
while (true){
cout<<endl;
cout << "Type in a number:" <<endl;
cin.sync();
cin >> input;
if (input <= numbers[11] && input >= numbers[0])
cout << "YEES!!!" << endl;
else{
cout << "Number is out of range!" <<endl;
cout << "Please try again!" <<endl;
}
}
return 0;
}
Indexing starts with zero, so if you create an array with a size of N last index always will be N-1. In your case, the index of the last element is 10.
if (input <= numbers[10] && input >= numbers[0]) // accurate
The last element in your array should be 10, not 11 because you start at zero. Try doing
if (input <= numbers[10] && input >= numbers[0])
While the other answers clearly handle the indexing issue (array indexes start at 0 and the last index of an 11 element array is 10) there is a little bit of an XY problem happening here.
If you need to determine if an input number is within the range from 1 to 11, there is absolutely no need to use an array at all. You simply need to check that it's less than or equal to 11 and greater than or equal to 1.
if (input <= 11 && input >= 1) {
// ...
}
Your code is essentially trying to do this but storing the bottom of the range in numbers[0] and the top of the range in numbers[10] with the rest of the array being unused. If you want you could use two variables to store these limits.

how to store data into dynamic array

I have this program that asks user to enter a number and ask the user if they want to view input history. So i was wondering if my code is correct. I want to know if doing cin>>num[count-1] is correct or is there a correct way to get the data the user inputs. Here it is:
#include<iostream>
using namespace std;
int main(){
const int size = 20;
int *num = new int[size];
char answer;
int count = 1;
while(true){
cout<<"ENTER NUMBER: \n";
cin>>num[count-1];
cout<<"TRY AGAIN? ";
cin>>answer;
switch(answer){
case 'y':
count++;
system("cls");
break;
default:
cout<<"INPUT HISTORY: \n";
for(int i=0;i<=count-1;i++){
cout<<num[i]<<endl;
}
count++;
}
}
delete [] num;
return 0;
}
I want to know is doing cin>>num[count-1]` is correct or is there a correct way to get the data the user inputs.
Your code is a c-style code. You have the std::array and std::vector to help you to write a more secure and clean code. Because your tag in your question is dynamic-arrays I suggest to use the std::vector.
Bellow you can check out your code could be with the replacement.
#include <iostream>
#include <vector>
using namespace std;
int main() {
//int *num = new int[size]; //normally you don't need to use new. Let the c++ manage it for you
vector<int> num;
char answer;
while (true) {
cout << "ENTER NUMBER: \n";
num.emplace_back(); //Create a new element to vector num
cin >> num.back(); //set this new element
cout << "TRY AGAIN? ";
cin >> answer;
if (answer == 'y')
system("cls");
else {
cout<<"INPUT HISTORY: \n";
for (auto& numEle : num) //It will interate over all elements of num
cout<< numEle <<endl;
//break; //Maybe you want to break the loop here
}
}
// delete [] num;
return 0;
}
I will first show you the problems in your code. I put in comments.
Then I will explain you, why your input is wrong. Also the answer from user TheArquitect is wrong and will finally lead to a memory overflow.
Your program will also have a desastrous result.
First see the code:
#include<iostream>
using namespace std; // In C++ we never use this statement. Why? See:
// You will find at least 1000 comments in Stackoverflow
int main() {
const int size = 20; // In C++ we use constexpr for compile time constants
int* num = new int[size]; // In C++ we
// Do not use raw pointers for owned memory
// Do not use new
// Do Not use C-Style arrays
// Generally: std::vector should be used
// Or at least std::unique_ptr and std::make_unique
// Also, this 2 lines are nonesense. It is the same as int num[20];
char answer; // All variables should always be initialized
// Variables should be in the scope, where they are necessary
int count = 1; // YOu could use uniform initialization
// Arrays start with index 0 in C++ (also in C )
while (true) { // You are creating an endless loop with desastrous effect
cout << "ENTER NUMBER: \n";
cin >> num[count - 1]; // No, this will not work. Explanation in text
cout << "TRY AGAIN? ";
cin >> answer; // No, this will not work. Explanation in text
switch (answer) { // Switch with only one case can always be expressed with if elese
case 'y':
count++;
system("cls"); // This is a non portable solution
break;
default:
cout << "INPUT HISTORY: \n";
for (int i = 0; i <= count - 1; i++) { // Nearly Never use <= in for loops
// Use for (int i = 0; i < count; i++)
// Do use ++i insted of i++
cout << num[i] << endl;
}
count++;
} // This is an endless loop. count will always be increased. If greater than 20
// then the memory will be corrupted. This will happen always
}
delete[] num; // Dead code. Will never be invoked
return 0;
}
OK. Now, besides the major bugs and the killing out of bounds problem, here the explanation for the problem with inputting data.
Rule: You must always check, if the input operation worked. For that you can check the state of the stream. Additionally, if you do not consume the input data (because of an erronous input by the user), this data is still in the input buffer. And in the next loop it will be read again (without waiting for new user input). The status of the input stream may still be wrong and it will also not read because of this.
Then the endless loop starts to run without user input and corrupts your memory.
You may check, by simply inputting a letter instead of a number.
How to fix?
Again, you must check the state of the stream after reading. This is usually done in the form:
if (std::cin >> number)
Why does this work? Because: The inserter operator returns a reference to the stream (so std::cin) and the boolean '!' not-operator for the std::istream is overwritten. It will show, if the state of the stream is still ok or not.
OK, understood. Now. What to do in case of error? 2 operations:
Clear all failure bits in the state of the stream --> std::cin.clear()
Eat up everything that is still in the input buffer --> std::cin.ignore()
You could write:
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
I assume that you are learing C++ in a class and learn about new and delete. As said, you should not use it. But because teacher request this often in the classes, I will show you now a better solution than yours, still using new, but without (most of) the problems.
#include<iostream>
#include <limits>
int main() {
// We want to create a dynamic array with 20 elements
constexpr size_t MaxArraySize{ 20U };
// Allocate a dynamic arry on the heap
int* numberArray = new int[MaxArraySize];
// Read maximum 20 numbers into our dynamic array
for (size_t currentArrayIndex{}; currentArrayIndex < MaxArraySize; ) {
// Inform the user that he should ent now a number
std::cout << "Enter number: \n";
// Read the number and check, if this worked
if (std::cin >> numberArray[currentArrayIndex]) {
// Now ask, if the user wants to continue or stop
std::cout << "Doy you want to enter more numbers? ('y' or 'n'): ";
// Define variable answer and get user input and check, if ok
if (char answer{}; std::cin >> answer) {
// Does the user want to continue?
if ('y' == answer) {
// Yes, continue. Increment array index
++currentArrayIndex;
}
else {
// No, the user does not want to continue. Show the values entered so far
std::cout << "Input History:\n";
for (size_t i{}; i <= currentArrayIndex; ++i) { // NOTE: <= becuase index has not yet been incrementet
std::cout << numberArray[i] << "\n";
}
break; // Stop the for loop and end the program
}
}
else {
// Strange, input of a character did not work. Should not happen. Terminate program
std::cerr << "\n*** Error: Problem with input!\n\n";
break; // Stop the for loop and end the program
}
}
else {
// The user entered someting wrong, or the input did not work for any other reason
// Inform user about problem
std::cerr << "\n*** Error: No number could be read!\n\n";
// Clear error flag and comsume whatever is in the input buffer
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
}
// Release dynamic allocated memory
delete[] numberArray;
return 0;
}

why does my calculator program start flashing and scrolling when i enter a large number

my program is a calculator that currently only does addition and subtraction, but when i input a large number it starts flashing and scrolling. it works fine for small numbers. the program isn't long so here it is. a youtube video of the problem https://youtu.be/Fa03WtgXoek
#include <iostream>
int GVFU()
{
std::cout <<"enter number";
int a;
std::cin >> a;
return a;
}
int add()
{
int x = GVFU();
int y = GVFU();
int z = x + y;
std::cout <<z <<std::endl;
return 0;
}
int subtract()
{
int x = GVFU();
int y = GVFU();
int z = x - y;
std::cout <<z << std::endl;
return 0;
}
int main()
{
for ( ; ; )
{
std::cout << "enter 1 for addition and 2 for subtraction";
int c;
std::cin >> c;
if (c==1)
{
add();
}
if (c==2)
{
subtract();
}
std::cout << "press 1 to end";
int e;
std::cin >>e;
if (e==1)
{
return 0;
}
}
}
If you try to read a value from cin and the value read doesn't match the expected format, it causes the stream to fail and all future read operations will instantly return without reading anything.
Independently, in C++ integer values for the int type have a minimum and maximum possible value that depends on what compiler and system you're using. If you exceed that value when entering a number, cin will consider it a failed read.
Putting this together, once you enter a value that's too large, the program will keep running through the main loop in your program, prompting for a value, instantly returning without actually getting user input, then calculating garbage values.
To fix this, you'll need to either (1) just hope the user doesn't type in anything unexpected or (2) get user input more robustly. There are a number of good explanations about how to do option (2) here on Stack Overflow, and now that you know what the root cause of the issue is you can hopefully get the code fixed and working!
Use
std::cout << std::numeric_limits<int>::max() << std::endl;
and include #include <limits> and you will find out max int value on your machine.
int on your system is likely a 32-bit signed two's complement number, which means the max value it can represent is 2,147,483,647.
If you add bigger number stream will fail and all next read operations will return without reading anything.
Use unsigned long long which will allow you to insert bigger numbers.
You are taking your inputs as " int " and value range for int is between -2,147,483,648 to 2,147,483,647.
Which means that if you exceed this value 2,147,483,647 it can not be stored as an integer(int) type.
You should probably use Long data type for such large numbers.
You can add a following check in your code if the user input more than int limit
int GVFU()
{
std::cout <<"enter number";
int a;
std::cin >> a;
if(cin.fail())
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Invalid input " << endl;
}
return a;
}
I would also add exit if invalid number
#include <iostream>
#include <cstdlib>
using namespace std;
int GVFU()
{
std::cout <<"enter number";
int a;
std::cin >> a;
if(cin.fail())
{
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "Invalid input " << endl;
std::exit(EXIT_FAILURE);
}
return a;
}
Note: You could also more info instead of just "Invalid input "
Output like size or limit info
enter 1 for addition and 2 for subtraction1
enter number4535245242
Invalid input
Program ended with exit code: 1

Array auto-filling itself in C++

I'm learning C++, doing some easy examples, and found this odd behavior.
When filling the elements of an array of integers, if any of the elements is set to something greater than 2147483647 (which I believe is the maximum integer value?), the rest of the elements in the array are set to that exact number, every one of them.
I understand that if one element goes beyond its type limit, the compiler caps it to that limit, but I can't get why it does the same thing with the other items, without even asking the user to fill them.
Here's a simple test I've run:
#include <iostream>
using namespace std;
int main()
{
int test[5];
int num = 0;
for (int i=0; i<5; i++)
{
cout << "Enter the number in position " << i << endl;
cin >> num;
test[i] = num;
}
cout << "Values in the array: " <<endl;
for (int i=0; i<5; i++)
cout << test[i] << endl;
}
Thanks for reading, commenting, and helping!
Documentation of std::istream::operator>>:
If extraction results in the value too large or too small to fit in value, std::numeric_limits<T>::max() or std::numeric_limits<T>::min() is written and failbit flag is set.
Once the failbit flag is set, subsequent input operations will have no effect, meaning that aux is left unchanged.
If you want to continue extracting items after conversion failure, you need to clear failbit:
cin.clear();
cin >> aux;

How to make the user type a value instead of storing a constant value?

I have made a simple program in C++ and this is the code:
#include <iostream>
using namespace std;
int main()
{
int number;
int square;
number = 5;
square = number * number;
cout << "The square is ";
cout << square;
return 0;
}
what it does is basically taking the integer "5" and get the square value on the screen and so on...
my question is:
how can I make the program take any value from the user instead of storing a value in the memory?
than Q.
Your code makes use of cout to print. C++ makes cin available for input from the console:
int x;
cin >> x;
"An example is worth a thousand words..."
Well cout takes some var. from memory and prints it out on the screen, right?
Well, cin does the exact opposite, it takes in some value from the keyboard and puts it in your memory..
You have to take in the value with the help of cin command, like this:
int a; //lets say you have a variable
cout << "Enter a value here: "; //prompts the user to enter some number
cin >> a; //this line will allow the user to enter some value with the keyboard into this var.
int square = a * a;
cout << "The square is: " << square;
Hope it helps...
Just replace:
number = 5;
with:
cout << "What's the number? ";
cin >> number;
You already know how to use cout to generate output, this simply uses cin to retrieve input.
Keep in mind that, while this may be okay for small test programs or learning, data input in real programs tends to be a little more robust (such as if you enter the string xyzzy when it's trying to input an int variable).