C++ Infinite Loop causing a stack overflow error? - c++

Okay, so I've been working on my calculator. I am currently trying to get it to tell the difference between a valid integer and a character. As an easy workaround I did:
int calc()
{
cout << "Number 1:"; cin >> fnum;
cout << "Number 2:"; cin >> snum;
if (snum <= -1000 || fnum <= -1000)
{
cout << ("Error: Invalid Number!") << endl;
calc();
}
else
{
ff();
}
return 0;
}
And whenever I enter in a character it goes into an infinite loop saying:
SymbolHere:Number 1:Number 2:
ff(); is calling in the calculation function.
I was wondering how to fix this and prevent a stack overflow/ infinite loop? Pastebin Link: http://pastebin.com/GxN2uJAQ

EDIT: ok, there are a number of things with this code.
wait = 0;
while (wait <= 5)
{
wait++;
}
will do absolutely nothing, your program will increment so fast this is undetectable to the human mind. I would recommend removing this entirely.
if (snum >= 0 || fnum >= 0)
{
cout << ("Error: Invalid Number!") << endl;
wait = 0;
while (wait <= 5)
{
wait++;
}
system("CLS");
calc();
}
why are you sending an error message if these numbers are valid? Unless you are only adding negative numbers, this should have a different range.
your function calls also never resolve back into main, instead they call each other (ff and calc) infinity, the program honestly has too many flaws and bad programming practices. Drop whichever tutorial/book you have and try finding a more up to date list(sorry for being harsh, but it has to be said).
C++ Primer Plus
CPlusPlus.com
TheNewBoston(Recommended)
You probably have an input fail by entering say a char for an int, you need to make sure to catch anything thrown by cin and clear the state:
std::string err = "error!";
try {
std::cin >> x;
if(!cin)
throw err;
//....
}
catch(std::string& ee)
{
std::cout << ee << std::endl;
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(),'\n');
}
make sure to include <limits> in your file.

Related

std::cin failure leading to looped if statement in while loop

So I figure I'll put this here since I had to traverse a lot of docs and forums to find the definitive answer. I was trying to get input from the user and check if the input was an integer using isdigit() in an if statement. If the if statement failed the program would output an error message. Although, when a nondigit character was entered the program would loop through the error message endlessly. Here's that code:
int guess = -1;
while (game.getCurQuestion() <= 4) {
std::cout << "Guess: " << game.getCurQuestion() + 1 << std::endl;
std::cin >> guess;
if(isdigit(guess))
{
game.guess(guess);
else
{
std::cout << "Error\n"; //this would be looped endlessly
}
}
std::cout << "You got " << game.getCorrect() << " correct" << std::endl;
return 0;
}
NOTE: Solved, only posted to include my solution. Feel free to correct if I stated anything incorrectly.
The posted way will fail sometimes and will cast the doubles to integers if any doubles are input.
Use something like the following
int getIntInput() {
try {
std::string input;
std::cout << "\nPlease Enter a valid Integer:\t";
std::cin >> input;
size_t takenChars;
int num = std::stoi(input, &takenChars);
if (takenChars == input.size()) return num;
} catch (...) {}
return getIntInput();
}
Problem: The program kept hold of the non-integer value stored in the cin buffer. This leads to the program never leaving the error message.
Solution:
Use std::cin.fail() to check if the input matches the variable data type. I.E. int was the expected input but the user entered a char. In this case std::cin.fail() would be true.
In the case of std::cin.fail(), use std::cin.clear() and std::cin.ignore(std::numeric_limits<int>::max(), 'n') std::cin.clear() will clear the error flag. The std::cin.ignore(std::numeric_limits<int>::max(), 'n') will ignore any other input that is not an integer and will skip to the new line. Effectively progressing the program.
The solution implemented in my code looks like this:
int guess = -1;
while (game.getCurQuestion() <= 4) {
std::cout << "Guess: " << game.getCurQuestion() + 1 << std::endl;
std::cin >> guess;
if (std::cin.fail())
{
std::cout << "Please enter a valid number\n";
std::cin.clear();
std::cin.ignore(std::numeric_limits<int>::max(), '\n');
}
game.guess(guess);
}
Hope this helps and that it saves some people the tedious research because of never learning std::cin error handling! Note: I'm aware my implementation skips the current move, call it punishment ;)

Random number generator for C++ popping up with an error?

I am having trouble with my number generator. Syntax wise, everything is working properly. I mainly wanted to use functions to see if they would work properly. When I run the program, a message pops up and says that my variable "guess" is not initialized. Can anyone give insight as to why this may be happening?
Also note that even though I didn't include my libraries in the code below, they are present in the actual program itself.
using namespace std;
int game();
string playAgain();
int main(){
game();
playAgain();
return 0;
}
int game(){
int guess;
int guessesTaken = 0;
int number = rand() % 10 + 1;
int count = 0;
cout << "I am thinking of a number between 1 and 10, can you guess it? " << endl;
while (guessesTaken < count){
cout << "Take a guess: " << endl;
cin >> guess;
if (guess > number)
cout << "Too High. Try again!" << endl;
if (guess < number)
cout << "Too Low! Try again!" << endl;
if (guess == number)
break;
}count++;
if (guess == number)
cout << "Congratulations!" << endl;
return 0;
}
string playAgain(){
string play;
cout << "Want to play again?: " << endl;
if (play == "y" || "Y")
main();
else
cout << "Thanks for playin" << endl;
return 0;
}
It happens because you did not initialise guess, precisely as the warning says.
Sure, if you assume that the cin >> guess operation will always succeed, then initialisation becomes largely irrelevant as the variable will take on a deterministic value.
But:
the compiler does not know this when it warns you, and
you have no error checking on your cin >> guess operation; not only can you not assume that it will always succeed, but your program has no clue whether it actually did.
Furthermore, the entire loop may not be executed at all if your other variables have the right values, so the compiler is completely right in its observation.
Initialise your variables and put error checking around your stream operations.
Furthermore, that count++ should obviously be in the loop body, and your loop otherwise needs refactoring in general because it begins with the 0 < 0 case. You should think hard about what you intend the semantics of your program to be.

Assert function causes program to crash

I have used assert function to ensure that the first number input is between 1 and 7 (inclusive). However, when I execute the program and enter an invalid number, it causes the program to crash. So, how is the assert function being of any use here if that's the case?
Please correct my implementation where required.
Code:
#include <iostream>
#include <assert.h>
using namespace std;
int main() {
int num;
int n;
int max;
cout << "Please enter a number between 1 & 7 \n";
cin >> num;
assert(num >= 1 && num <= 7);
for (int i = 0; i < num; i++) {
cout << "Please enter number " << (i + 1) << ": ";
cin >> n;
if (i == 0) {
max = n;
}
max = (n > max) ? n : max;
}
cout << "The maxmum value is: " << max << endl;
system("pause");
return 0;
}
Assert is not what you want here. What you need is validation. Assertions are for debugging, for identifying completely invalid program states. The user entering invalid input is not invalid program state, it's just invalid user input.
To perform validation, you need an if-test. You will also need some code ready to handle the case of invalid user input. There's absolutely no way to prevent the user from providing invalid input (short of insanely aggressive dynamic validation where you capture keyboard events as they occur and prevent those keystrokes from translating into character input to your program, but now we're just getting ridiculous), so you need to react to it when it happens, say, by printing an error message and then asking for more input.
One way of doing this is as follows:
do {
cin >> num;
if (!(num >= 1 && num <= 7)) {
cerr << "invalid number; must be between 1 and 7!" << endl;
num = -1;
}
} while (num == -1);
Just to expand on that point about assertions, they are supposed to make the program crash. An assertion failure means your code is broken and must be fixed before it can be used in real life. Assertion failures should never be triggered in production code; they simply aid in testing and catching bugs.
What does the "crash" does? According to me, assert will abort the program execution, maybe as another value other than 0.

Making an if condition return if its true or while return if its true

When the condition is true or false, how can I make it return back and ask the question again, making the user re-enter the value?
Here is what I want to implement:
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main()
{
int n;
cout<<"Enter numbers. Press 5 to stop: ";
cin>>n;
bool tr=true;
while(tr)
{
if(n!=5)
cout<<"You entered "<<n; //How to make it return again, since its false? I keep getting infinite loops :( ;
else
tr=false;
}
return 0;
}
You need to prompt the user in the while loop, so that it occurs in each iteration:
int n;
bool tr = true;
while(tr)
{
cout << "Enter numbers. Press 5 to stop: ";
cin >> n;
if(n!=5) {
cout << "You entered " << n;
} else {
tr = false;
}
}
Just put all your code (except 'n' and 'tr' definition) in while loop as follow:
int main()
{
int n;
bool tr=true;
while(tr)
{
cout<<"Enter numbers. Press 5 to stop: ";
cin>>n;
if(n!=5)
cout<<"You entered "<<n;
else
tr=false;
}
return 0;
}
The other answers all work, and there is something to be learned about improving program flow from them, but I believe the trick you're asking for is the continue keyword, which skips the remainder of this iteration of the loop.
bool tr = true;
int n;
while (tr)
{
cout << "Enter numbers...";
cin >> n;
if (n != 5)
continue;
else
tr = false;
}
EDIT Part 1: On the continue keyword.
You want to make your code as readable as possible. In this example, its use is unnecessary (as the other posters have shown); but it is the answer to the question "How do I skip the rest of processing in this iteration of my loop and continue to the next iteration?". Usually, such flow-breaking directives actually make code harder to read; but sometimes the opposite is true. Anything (or, at least, almost anything) that can be accomplished with continue or break, can be accomplished without them, so if you're going to use them, you want to have a definite reason for doing so. Usually, when I use continue, it's because I'm looping through a collection of inputs and I want to skip processing the loop whenever the input isn't in the format I'm expecting. Something like this (pseudo-code)...
foreach (Input i in ReceivedInputs)
{
if (i.isBad())
{
cout << "Bad input";
continue;
}
// Do massive block of calculating here.
}
is easier to read than this...
foreach (Input i in ReceivedInputs)
{
if (i.isBad())
cout << "Bad input";
else
{
// Do massive block of calculating here.
}
}
because the second version makes it harder to track what scope you're in, if you're looking toward the end of the massive block of calculating. In this case, I gain code readability by continue, so I use it. But simple code probably shouldn't use it. The break keyword is similar, though it's a lot easier to come up with examples where break is beneficial.
EDIT Part 2: On multiple iterations
This is just an issue of setting up the loop; there are no magic keywords here. The shortest way I can come up with, is probably something like this:
int n = 0;
int numberToTake = 10;
for ( int numbersTaken = 0; numbersTaken < numberToTake; ++numbersTaken)
{
cout << "Enter numbers...";
int n = 0;
for (cin >> n; n != 5; cin >> n)
cout << "Try again.";
// Do whatever processing on n you want to do here.
}
Though I should point out that, doing it this way, the only value you will ever get from the user will be 5, and if he inputs anything that doesn't fit in an integer, you will get unexpected behavior.
EDIT 3: After reading the comment more thoroughly, I think you're just looking for is the more traditional use of the for loop.
No need for the exra bool variable.
The idiom can be: Infinitely loop until the user enters 5:
for(;;) { // Loops infinitely
cout << "Enter numbers. Press 5 to stop: ";
cin >> n;
if(n == 5)
break; // Exits the loop
cout << "You entered " << n; // Before the if if you want to print 5 as well
}

What is the better implementation for this loop?

I need to implement a loop where I have to ask the user, and then check the validity of the input (in this case it is necessary to print that is an invalid number). What is the better way to implement it?
Our programming professor does not let us use break, and for(;;) since, as he says, it is a bad practice. Is that correct?
Example 1:
int i = 0;
while(i == 0) {
cout << "...: ";
cin >> i;
/*... Loop body ...*/
if (i == 0)
cout << "Not a valid number" << endl;
}
Example 2:
int i = 0;
do {
cout << "...: ";
cin >> i;
/*... Loop body ...*/
if (i == 0)
cout << "Not a valid number" << endl;
} while (i == 0) // Better while(true) and use break ?
Example 3:
int i = 0;
for ( ;; ) {
cout << "...: ";
cin >> i;
/*... Loop body ...*/
if (i == 0)
cout << "Not a valid number" << endl;
else
break;
}
In your case the second construct (do..while) is the most intuititve for the reader to look at what the code does, and this is important.
The first one isn't so bad, the last one is poor a "for" construct is usually used where there are a limited number of iterations with the limit set in advance. It doesn't have to be, but intuitively that is how a for loop is used.
(Incidentally if the user entered a string that isn't a number you would have to clear the fail flag on cin, but that is not really the question being asked here).
Don't you need to accept zero as an integer? It's good practice to not rely on input numbers having a special meaning.
If the meaning of the loop is to loop infinitely until the task is done there's nothing wrong with clearly saying while(true). I would probably do something more like this (requires C++11): (or use boost lexical_cast)
#include <iostream>
#include <string>
#include <stdexcept>
int infini_asker(){
while (true) {
std::cout << "...: ";
std::string tmp;
std::cin >> tmp;
int i;
try{
i=std::stoi(tmp);
}catch(std::invalid_argument){
continue;
}catch(std::out_of_range){
continue;
}
return i;
}
}
int main(){
int num=infini_asker();
std::cout << " got:" <<num << std::endl;
}
A modification of Example 1 looks to be the best form:
while(true) {
cout << "...: ";
cin >> i;
/*... other stuff ...*/
// Do your input validation here:
// Note that it's much better to whitelist what is
// acceptable input as opposed to checking all of the
// possible cases of invalid input
if (...) { // where .. is the condition for valid input
break
}
}
do-while loops should be reserved for special cases where you want to get the point across that the nested logic should be executed at least once. Anything you can do with do-while, you can do with while(...)
for(;;) is less familiar syntax for a lot of programmers (I didn't know what it meant a year ago), whereas while(true) is much more obvious.
They all work. Like Shmiddty says a for(;;) is not a good programming habit. I would do it like example 2, but I am not a professional programmer.