My while statement is getting infinite loop? [closed] - c++

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
#include "stdafx.h"
#include <iostream>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
//this program will let the user input their assignment score and see their letter grade
int main() {
int score;
cout << "Input your score: ";
//to make the while loop
int x = 1;
while (x == 1) {
cin >> score;
if (score >= 90){
cout << "\nA";
break;
}
else if (score >= 80) {
cout << "\nB";
break;
}
else if (score >= 70) {
cout << "\nC";
break;
}
else if (score >= 60) {
cout << "\nD";
break;
}
else if (score >= 0) {
cout << "\nF";
break;
}
else
cout << "\nInvalid input";
}
}
I'm trying to write a program that let the user input their score for an assignment and display their resulting letter grade. If the user input is not a valid score, it prints "Invalid input" and should ask for user input again. However, when I actually run the program and type in an invalid value, it goes into an infinite loop of printing "Invalid input". Why is this? Thanks in advance.

When the user enters invalid input, cin >> score fails and leaves an error flag set on the stream.
Subsequent read operations just don't do anything until you clear that flag with std::basic_ios::clear().
Furthermore, since the read failed, score has some unspecified value (as you did not initialise it), and apparently on your test runs that unspecified value happens not to match any of those continues, so you never hit a break.
Instead of just:
std::cin >> score;
Try this:
if (!(cin >> score)) {
// If reading into an int failed, we come here
cout << "Invalid value! Try again" << endl;
// Clear error flag
cin.clear();
// Restart the loop
continue;
}
You may also need to ask the stream to eat up newlines in the input buffer. If you get the "Invalid value!" message twice, look up on SO how to do that.

you set x=1 and check if x==1. For the compiler it seems that it could be an infinite loop because it's unsure if a break would happen, that's why it's only a Warning and not an Error. For that behaviour you don't even need to vast the variable x , you could use while(true) too.

Related

how to allow multiple inputs in case of an incorrect data type entry in cpp?

I have a program which generates random number and asks user to keep guessing it until he/she gets it right. I want it to keep accepting new values even if i incorrectly enter any other data type by handling the error cases.
My problem is that when i am trying to run the below program, as soon i input a character and hit enter, it goes into an infinite loop. I tried using cin.ignore() and cin.clear() but that just makes the program stop after the first entry.
Can anyone please help me understand what is going on and how to achieve the desired output? Thanks in advance.
#include <iostream>
#include <cstdlib>
#include <time.h>
using namespace std;
int main()
{
int secret_num, guess;
srand(time(NULL));
secret_num=rand() % 101 + 0;
cout<<"Enter your guess between 0 and 100: ";
do
{
if(!(cin>>guess))
{
cout<<" The entered value is not an integer"<<endl;
}
else if( isnumber(guess))
{
if(guess>secret_num)
cout<<"Too high";
else if(guess<secret_num)
cout<<"too low";
cout<<endl;
}
}
while(secret_num!=guess);
if((guess==secret_num)| (isnumber(guess)))
{
cout<<"yes the correct number is "<<secret_num<<endl;
}
return 0;
}
Edit: Here is a screenshot of what the output looks like with cin.clear() and cin.ignore(1000,'\n') in my code, when i enter a number after entering character twice.
if (!(cin >> guess))
{
cout << " The entered value is not an integer" << endl;
cin.clear(); // clear must go before ignore
// Otherwise ignore will fail (because the stream is still in a bad state)
cin.ignore(std::numeric_limits<int>::max(), '\n');
}
By default cin.ignore will ignore a single character. If they type more than 1 char, it won't be enough, that's why I've modified it a bit.
if ((guess == secret_num) | (isnumber(guess)))
| is a bitwise operator [OR]
|| is the logical operator [OR]
But I think what you actually want is && (AND)
if ((guess == secret_num) && (isnumber(guess)))
There're several problems.
You should use cin.clear() and cin.ignore() as #José suggested.
What's isnumber()? I guess it's returning false so no hint message (i.e. "Too high" and "too low") is printed out, looks like it stops although it's just waiting the next input. And isnumber() doesn't make sense to me. guess has been declared as an int, it has to be a number, doesn't it?
if((guess==secret_num)| (isnumber(guess))) is unnecessary here. The loop won't end until the user input the correct number, this condition should have been statisfied.
You can use clear and flush
if(!(cin>>guess))
{
cout<<" The entered value is not an integer"<<endl;
cin.clear();
fflush(stdin);
}
This works if you are reading from console. Otherwise you can go with #José answer.
I would change the logic inside your loop as there are some useless tests. This works for me:
#include <iostream>
#include <limits>
#include <cstdlib> // You may take a look at <random> and <chrono>
#include <time.h>
using std::cout;
using std::cin;
int main() {
srand(time(NULL));
int secret_num = rand() % 101;
cout << secret_num << '\n';
cout << "Enter your guess between 0 and 100:\n";
int guess = -1;
do {
cin >> guess;
if ( cin.eof() )
break;
if ( cin.fail() ) {
cout << "The entered value is not an integer, please retry.\n";
// clear the error flag
cin.clear();
// ignore the rest of the line
cin.ignore(std::numeric_limits<int>::max(),'\n');
// clear the value of the variable
guess = -1;
continue;
}
// now we know that guess is a number
if ( guess > secret_num )
cout << "Too high\n";
else if ( guess < secret_num )
cout << "Too low\n";
else {
cout << "Yes the correct number is " << secret_num << std::endl;
break;
}
} while ( true );
return 0;
}

How to ask for Age and set everything else as invalid?

I'm trying to set a basic program that asks for Age, And if the Number entered by the user is less than 99, It will say "Perfect". If the number is MORE than 99, it will say "You Can't be that old, Try again". Additionally, if the user enters something that is not a number (like a letter "m, r" or anything else like "icehfjc") then it will say "That is not a number."
This is my code so far:
#include <iostream>
#include <string>
using namespace std;
int main()
{
int age;
backtoage:
cout << "How old are you?\n";
cin >> age;
if (age < 99)
{
cout << "Perfect!\n";
system("pause");
}
if (age > 99)
{
cout << "You can't be that old, Try again.\n";
system("pause");
system("cls");
goto backtoage;
}
Else
{
cout << "That is not a number, Please Enter a Valid Number\n";
system("pause");
system("cls");
goto backtoage;
}
}
I know "Else" doesn't work because C++ treats letters as integers as well, so
if I write "m" it will take it as a >99 number (because of the integer value of "m") therefore displaying the "you can't be that old" message. but how can I fix this so the program displays "Please enter a number" when a letter is entered? (If anyone could fix the code and write it in a way that works, I'd
be forever grateful).
Any suggestions, tips or hints are very welcome.
so if I write "m" it will take it as a >99 number (because of the integer value of "m")
No, "m" can't be inputted into an int, cin will fail here. So what you should do is to check the status of cin, such as
if (cin >> age) {
// ok
if (age < 99)
{
...
} else
{
...
}
}
else
{
// failed
cout << "That is not a number, Please Enter a Valid Number\n";
system("pause");
system("cls");
cin.clear(); // unset failbit
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // skip bad input
goto backtoage;
}
Check the behavior of std::basic_istream::operator>>
If extraction fails (e.g. if a letter was entered where a digit is expected), value is left unmodified and failbit is set.
BTW: goto is almost obsolete in modern c++ programming. It should be easy to implement the same logic with a loop.
LIVE
You can Try it.It will validate numeric input in C++.Here cin.good() function is return true if the input is valid, if it is not valid it will return fase. cin.ignore() is used to ignore the rest of the
input buffer, which contains the erroneous input and cin.clear() is
used to clear the flag.
#include <iostream>
#include<string>
#include <limits>
using namespace std;
int main() {
backtoage:
int age = 0;
cout << "How old are you?\n";
cin >> age;
if(cin.good()){
if (age < 99){
cout << "Perfect!\n";
system("pause");
}
else if (age > 99){
cout << "You can't be that old, Try again.\n";
system("pause");
system("cls");
goto backtoage;
}
}
else{
cout << "That is not a number, Please Enter a Valid Number\n";
system("pause");
system("cls");
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
goto backtoage;
}
return 0;
}
Input/Output:
How old are you?
k
That is not a number, Please Enter a Valid Number
How old are you?
120
You can't be that old, Try again.
How old are you?
10
Perfect!
first of all , if the users can enter characters like 'm' 'k' or anything else , I suggest using string , then if you want to change to number just substract '0' , so you can work with numbers, secondly programmers , usually do not use goto statement because it can be dangerous and make underfiend behaivor appear into your program.
Sorry for my bad english.
#include<iostream>
#include <string>
using namespace std;
int main()
{
string input;
getline(cin, input);
unsigned int lenght = input.size(),age=0;
for (int i = 0; i < lenght; ++i) {
if (input[i] >= '0' && input[i] <= '9') {
age = age*10+(int)input[i]-'0';
}
}
if (age > 99)
cout << "Nice try , you can`t be that old\n";
else
cout << "perfect!\n";
return 0;
}

Why does the loop loop itself when "else" is triggered? Is this because of things called memory allocation? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I'm just a beginner and trying out some code that my teacher taught us to use and things from the textbook.
This program is designed to be for the user to enter in their name and enter in the password as what the system asks them to put down.
Can somebody explain to me why this loop keeps looping itself infinitely when else is triggered?
Also, what does the cin.ignore do to the memory of the char name? Why is 80 better than 20?
AND, why aren't the random numbers actually random? Every time I run it, the numbers are the same.
Thank you all so much!
#include <iostream>
#include <cstdlib>
using namespace std;
int main ()
{
char name[20];
int pwd, rand1, rand2;
for (int i=0;i<1; i++)
{
cout<<"Name: ";
cin.get(name, 20);
cin.ignore(80, '\n');
cout<<endl;
srand(rand() % 1000);
rand1 = (rand() % 21);
rand2 = (rand()%6);
cout<<"Password: "<<rand1<<"*"<<rand2<<"= ";
cin>>pwd;
if(pwd == rand1*rand2)
{
cout<<endl<<"Welcome to our main page, "<<name<<"."<<endl;
}
else
{
cout<<"Wrong password, type again." <<endl;
i--;
}
}
return 0;
}
First up formatting of code will help you understand better.
Also avoid using namespace std, its bad practice and clutters the global scope with names. Instead use using std::xxxx if you dont want to write std::cout, std::cin, etc every time.
Reformatted code:
#include <iostream>
#include <cstdlib>
using std::cin;
using std::cout;
using std::endl;
int main ()
{
char name[20];
int pwd, rand1, rand2;
for (int i = 0; i < 1; i++) {
cout << "Name: ";
cin.get(name, 20);
cin.ignore();
cout << endl;
srand(rand() % 1000);
rand1 = (rand() % 21);
rand2 = (rand() % 6);
cout << "Password: " << rand1 << "*" << rand2 << "= ";
cin >> pwd;
cin.ignore();
if(pwd == rand1*rand2) {
cout << endl << "Welcome to our main page, " << name << "." << endl;
} else {
cout << "Wrong password, type again." << endl;
i--;
}
}
return 0;
}
Secondly as you can see in the above code the line cin.ignore(); has been added after cin >> pwd. Before your code was getting cin >> name, leaving '\n' in the input, ignoring '\n', getting cin >> pwd, leaving '\n' in input, looping and reading input as empty with a '\n', leaving another '\n' in input, first '\n' is removed by ci.ignore(), second '\n' read by cin >> pwd, ... etc. Or at least this is how I understand it.
Somebody has answered the first question:Because when you i--, the i in the for loop keeps decreasing and then increasing.-By Gasim
Then, if your input is longer than 20, the program may stop. So you need cin.ignore(80, '\n') to ignore the excess input. The number 80 is just a big number. You can replace it with another number-only if it's big enough.
You are supposed to use srand with time. srand(time(null)) may help.

C++ Infinite Loop causing a stack overflow error?

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.

Refine my code/program where did I go wrong?

#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
int LordIronhead = 0;
char answer;
cout<<"Is Lord Ironhead present? Y/N.\n";
cin >> answer;
if (answer == 'Y')
{
LordIronhead=0;
}
else if (answer == 'N')
{
LordIronhead= LordIronhead+1;
}
cout<< ""<<LordIronhead<<"\n";
system("PAUSE");
return 0;
}
Every time I run the program and If I answer NO (N)
the result is always 0 instead of 1 (LordIronhead = LordIronhead + 1)
May I know where my error is?
Your code is fine in principle, but you might run into issues with the two-valued logic of 'answer' being checked against 'Y' and against 'N' with no fall-through case. I suspect you are running into EOL or case or character conversion issues, falling through both if's and thereby never changing the Lord.
For showing the problem, try an else statement:
else if (answer == 'N')
{
LordIronhead= LordIronhead+1;
} else {
std::cout << "Invalid answer '" << answer << "'" << std::endl;
}
Your code is correct but is sensitive to the case of user input (it treats user input of N and n differently). You'd remove a possible source of user confusion by converting the input to a known case before checking it. You can do this using either toupper or tolower
cin >> answer;
answer = toupper(answer);
I just tried this myself and found that if I answered N I got the expected answer (1). If I hit n, however, it came back as 0. Are you sure you're hitting N and not n?
Better using 1 and 0 instead of N and Y. Its more recognizable to the system