What is the relevance of if (!(cin >> variableName)) in this loop - c++

I'm a self taught developer trying to learn c++, I found this exercise on google and I wrote the code for it, though all my conditions were correct, it wouldn't work, when I checked their answer, I found this line of code- if (!(cin >> guess)). I honestly don't see the relevance, I don't know why it made my loop not to work. Here is my code:
int main(int argc, char* argv[])
{
int nUserRandNum = 0;
int randomNumber=0;
srand (time(NULL));
randomNumber = rand() % 100 + 1;
printf("Please enter a random number between 1 - 99 \n");
scanf("%d", &nUserRandNum);
do
{
if (randomNumber < nUserRandNum)
{
printf("Try to go a little higher than \n", nUserRandNum);
}
else
{
printf("You might want to go a little lower than \n", nUserRandNum);
}
}
while (randomNumber != nUserRandNum);
printf("You got it!!!");
system("Pause");
return 0;
}
When I checked the answer they had:
int random_number, guess;
// Initialize random seed.
srand (time(NULL));
// Generate random number between 1 and 100
random_number = rand() % 100 + 1;
cout << "Guess our number (1 to 100) ";
cin>>guess;
do
{
if (!(cin >> guess))
{
cout << "Please enter only numbers" << endl;
}
else
{
if (random_number < guess)
cout << "The secret number is lower than " << guess << endl;
else if (random_number > guess)
cout << "The secret number is higher than " << guess << endl;
}
} while (random_number != guess);
cout << "Congratulations!" << endl;
what does that if statement do {if (!(cin >> guess)) }? And are there other reasons my loop didn't work?

The difference between scanf and cin >> is not relevant here, that's not what makes it work.
Here's what you have:
scanf("%d", &nUserRandNum);
do
{
... print ...
}
while (randomNumber != nUserRandNum);
Your scanf is outside of the loop. Therefore, when the do...while condition is satisfied, the same number that the user already entered is checked again.
This needs to be inside the loop body, like so:
do
{
scanf("%d", &nUserRandNum);
... print ...
}
while (randomNumber != nUserRandNum);
Reading input from cin rather than using scanf is probably a good idea, as it's less easy to get wrong. (Although the code you've shown still manages to do so.)
Checking whether a number was successfully read is probably a good idea too. When the user enters random garbage, you shouldn't treat that as if the user had entered a number.
But neither of those is the cause of your problem.

You can understand that if (!(cin >> guess)) statement as "if inputting the number was unsuccessful", so (cin >> x) is true if the type entered by the user really is an int.
Nitpick: you switched "go lower" with "go higher" by the way.

Related

For Loops (C++)

Assignment:
The program should ask the user to enter a positive number and display all numbers from 1 to the input value. If the number is not positive, an error message should show up asking the user to re - enter the number.
My specific problem:
For my program, if the user enters an incorrect number and then re - enters a positive number, it does not display all the numbers from 1 to the input value. The program just ends.
#include <iostream>
using namespace std;
int main()
{
int userChoice;
int i = 1;
cout << "Enter a positive integer" << endl;
cin >> userChoice;
if (userChoice > 0)
{
for (i = 1; i <= userChoice; i++)
{
cout << "Loop 1:" << endl;
cout << i << endl;
}
}
else if (userChoice < 0)
cout << "Please re - enter" << endl;
cin >> userChoice;
system("pause");
return 0;
}
You need some sort of loop at the top of your program, that keeps asking for input until the user provides something valid. It looks like a homework assignment, so I will provide pseudo-code, not something exact:
std::cout << "Enter a number:\n";
std::cin >> choice;
while (choice wasn't valid) { // 1
tell the user something went wrong // 2
ask again for input in basically the same way as above // 3
}
// after this, go ahead with your for loop
It is actually possible to avoid the duplication here for step 3, but I worry that might be a little confusing for you, so one duplicated line really isn't such a big problem.
As an aside, you may wish to reconsider your use of what are often considered bad practices: using namespace std; and endl. (Disclaimer - these are opinions, not hard facts).

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.

Using do while loop and while loop to write a program that will run random guessing game...i stuck at the do while loop

I have been run a random guessing game. The game secret numbers is from min to max that input by user, the guesser is ask guess the secret number and at the end is supposed to be asked if they would like to play again. There also has to be multiple options for print outs if the guesser is to high or low. Anyways, I want it to check and make sure that the user is inputting numbers, not something silly. So I have been going in circles trying to figure this part out. I am sure it is a easy fix, but I am new to programming and this has got me stumped. Any help would be appreciated.
my code should similar to below output images :
[1]http://i62.tinypic.com/wjvuqb.png
[2]http://i57.tinypic.com/2nq9jwm.png
[3]http://i62.tinypic.com/210zss7.png
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <iomanip>
#include <string>
using namespace std;
int main()
{
int min, max, secret=0, deposit, bet, guess;
bool again= true;
string name;
char reply;
cout<< setw(80)<< setfill('=')<<"\n\n";
cout<< setw(45)<< "NUMBER GUESSING GAME!"<<"\n\n";
cout<< setfill('=')<< setw(80)<<"\n\n";
cout<< "What ur name?\n";
getline(cin,name);
Again:
cout<< "Pls enter the min & max number\n";
while(!(cin>>min)||min<0)
{
cout<<"Min? ";
cin.clear();
cin.ignore();
}
while(!(cin>>max)||max<0)
{
cout<<"Max? ";
cin.clear();
cin.ignore();
}
while(!(max> min))
{
cout<<"Min is larger than Max\n";
goto Again;
}
cout<< "\nMin: "<<min<<"\nMax: "<<max<<"\n";
secret= rand() % max+min;
cout<<"Enter ur deposit: ";
cin>> deposit;
AA: cout<< setw(45)<< "\n\n\n\nRULES OF THE GAME"<<"\n\n";
cout<< setfill('-')<< setw(80)<<"\n\n";
cout<< "Guess number between "<< min<< " to "<< max;
cout<< "\nIf ur guess match, 10 times ur deposit!!";
cout<< "\nIf ur guess mismatch, lose ur betting amount!!";
cout<< "\n\n"<< setfill('-')<< setw(80)<<"\n\n\n";
cout<< "Current Balance: "<<deposit;
cout<< "\nWhat is ur betting amount? ";
cin>> bet;
do{
cout<< "\n\nEnter a guess to bet: ";
cin >> guess;
if (guess > max)
{
cout << "Too high!\n\n";
cin.clear();
cin.ignore();
}
else if (guess < min)
{
cout << "Too low!\n\n";
cin.clear();
cin.ignore();
}
}while (guess != secret);
if(guess != secret){
deposit-=bet;
cout << "\nThat's it! You got it!\n";
cout<<"Sorry, U lose RM "<< bet;
}
else{
bet*=10;
deposit+=bet;
cout << "\nThat's it! You got it!\n";
cout<<"Congratulation! U earn RM "<< bet;
}
cout<<"\n\nThe secret number was : "<< secret;
cout<< "\n\n\tCurrent Balance: "<<deposit<< "\n\n\n";
do{
cout<< "Wanna play again (y/n)? ";
cin>> reply;
if( reply=='y'){
again= true;
goto AA;
}
else
cout<<"\nReally? Ok, try again! ";
cin>>reply;
}while(again==false && reply=='n');
if(reply=='n'){
cout<<"\n\n\n"<< setw(80)<< setfill('+')<<"\n\n";
cout<< setw(30)<< "THX FOR PLAYING! UR CURRENT BALANCE IS RM "<< deposit<<"\n\n";
cout<< setfill('+')<< setw(80)<<"\n";
}
return 0;
}
You are using goto, and if you are using goto, raptors will tear you to pieces. Do not, under any circumstances use goto!
But you can use functions to make your code a bit clearer. This wall of text and copy paste is really hard to read.
First of all the formula you are using to calculate the random number is wrong. Suppose that min is 10, and max is 12. Then the rand() % max could be, let's say, 10. Adding min (10), the number to guess would be 20 - far greater than max... It should be secret = rand() % (max-min +1) + min; (if your interval is [min, max]).
Now to your question - as far as I understood you want to know if the entered guess is a number. Here is what you can do:
while(1)
{
cin >> guess;
if(cin){
if (guess > max){
cout << "Too high!\n\n";
cin.clear();
cin.ignore();
continue;
}
else if (guess < min){
cout << "Too low!\n\n";
cin.clear();
cin.ignore();
continue;
}
else if(guess != secret){
deposit-=bet;
cout<< "Sorry, U lose RM "<< bet;
}
else if(guess == secret){
bet*=10;
deposit+=bet;
cout<< "\n\nCongratulation! U earn RM "<< bet;
}
break;
}
else
{
cin.clear();
cin.ignore();
cout << "Error! You did not enter a number!" << endl;
continue;
}
}
If the user didn't enter a number, the cin's fail flag will be up and you can use that.
Also, when trying again (goto AA;) you do not compute the random value again and you should. In order to get a different sequence of random numbers from rand() every time you start the program, you should seed the random generator from the current time. In the beginning of main, put srand((unsigned int)time(NULL)); What this does is that it gives the random generator a number and on its base it will generate random numbers. If the number is the same every time the program is started, the same numbers will be generated. But given the always changing current time, every time the sequence will be different.
Using goto can make your code very messy and can make bugs very hard to notice. Yes, it is a part of the language and it is there to be used, but one should be very careful with it. Especially if you are new to programming, try to refrain from using it. You could use while(1) or for(;;) if you need endless loops - you can get to the next iteration with continue; and stop them with break;.
Something is also wrong with the guessing loop. It seems that you cannot lose. You should decrease the deposit in the while loop and check if it is 0.
Edit: In the edited code you can see that whenever the user needs to enter the number again, you just skip the iteration with continue. This is also an example how you should deal with endless loops instead of using goto. With practice, you will get he hang of it. ;)
Edit 2:
do{
cout<< "Wanna play again (y/n)? ";
cin>> reply;
if( reply!='y'&& reply!='n')
cout<< "\nReally? Ok, try again! \n";
}while(reply!='n' && reply!='y');
if( reply =='y')
goto AA;
if(reply=='n'){
cout<< "\n\n\n"<< setw(80)<< setfill('+')<< "\n\n";
cout<< setw(30)<< "THX FOR PLAYING! UR CURRENT BALANCE IS RM "<< deposit<< "\n\n";
cout<< setfill('+')<< setw(80)<< "\n";
}
This should make the reply cycle work. Your program should consist of different chunks of code for different purposes, and in this cycle you mixed up checking the correctness of the answer with what will happen if the answer is correct. It's easier first to do the first, and then to do the second thing. Using functions can generally help you with this.
Edit 3: In that new code you have a lot of problems with if statement. Firstly, what is !> ? I think you meant < or <= , !> does not exist, it won't even compile. Another thing - what happens when max or min is 0? You haven't covered that.
You use if-else chains a lot and in this case it is not necessarily needed. For example you don't need if(min>0) , you don't even need the else before it. If you don't enter one of the if statement - the input is correct and you can break, if you enter one of them - it has continue; in it and the code below is not executed. The same goes for the last if statement in the max if-else chain executed if the input is a number.
Anyway, you could do it a lot simpler. For example the min loop can be:
cout << "Pls enter the min of secret number\n";
while (!(cin >> min) || min<=0){
cout << "Pls enter the min of secret number\n";
cin.clear();
cin.ignore();
}
You could see that this will work if you realize that you should break if (cin && min>0). Now when you negate that in order to place it as the while condition it becomes (!cin || min<=0).
Anyway, I didn't see any other problem in the code, I tested it and it worked. And now without goto it looks a lot better.

C++ input not being read

I just started with c++ (coming from java) and I'm trying to do some basic exercises. The idea is to ask for any input other than 5, if the user inputs 5, display a message, and if the user inputs anything other than 5 ten times, display another message. Here's the code:
void notFive () {
int count = 0;
while (count < 10) {
int input = 0;
cout << "Enter any number other than 5." << endl;
cin >> input;
if (input == 5)
break;
count++;
}
if (count == 10)
cout<<"You are more patient than I am, you win.";
else
cout << "You weren't supposed to enter 5!";
}
}
My problem is that all this code does is print out "Enter any number other than 5." 10 times, then say "You are more patient that I am, you win." any ideas what is wrong?
if you guys want all my code (to make sure I'm not just being an idiot) here it is:
#include <iostream>
#include <stdio.h>
using namespace std;
class Hello {
public:
void notFive () {
int count = 0;
while (count < 10) {
int input = 0;
cout << "Enter any number other than 5." << endl;
if ( ! (cin >> input) ) {
cout << "std::cin is in a bad state! Aborting!" << endl;
return;
}
if (input == 5)
break;
count++;
}
if (count == 10)
cout<<"You are more patient than I am, you win.";
else
cout << "You weren't supposed to enter 5!";
}
}hello;
int main() {
Hello h;
h.notFive();
return 0;
}
Your code works perfectly for me (in Visual Studio 2012) when I change notFive to main. Your problem must lie outside this code (possibly because cin is in a broken state, as others have suggested).
Change this line:
cin >> input
To this:
if ( ! (cin >> input) ) {
cout << "std::cin is in a bad state! Aborting!" << endl;
return;
}
The behavior you describe is what would happen if Something Bad happened to cin before this code was run.
Edit:
Add this same code to earlier uses of cin to find out where it's entering a bad state.
An example of this happening would be if the code tried to read an int, and the user typed a letter of the alphabet.
You can also call cin.clear(); to restore the working state of cin.
Here are my comments:
fflush(stdin) is not valid. The stdin cannot be flushed. Also,
this may not be the same input as cin.
You need to check for cin.fail after cin >> input. If I enter a
letter, your input statement will fail.

Is there a way to not include a negative number in an average, when entering a negative number is how you terminate the program?

Sorry about last time for those who saw my previous thread. It was riddled with careless errors and typos. This is my assignment:
"Write a program that will enable the user to enter a series of non-negative numbers via an input statement. At the end of the input process, the program will display: the number of odd numbers and their average; the number of even numbers and their average; the total number of numbers entered. Enable the input process to stop by entering a negative value. Make sure that the user is advised of this ending condition."
And here is my code:
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
int number, total1=0, total2=0, count1=0, count2=0;
do
{
cout << "Please enter a number. The program will add up the odd and even ones separately, and average them: ";
cin >> number;
if(number % 2 == 0)
{
count1++;
total1+=number;
}
else if (number >= 0)
{
count2++;
total2+=number;
}
}
while (number>=0);
int avg1 = total1/count1;
int avg2 = total2/count2;
cout << "The average of your odd numbers are: " << avg1 << endl;
cout << "The average of your even numbers are " << avg2 << endl;
}
It seems to be working fine, but when I enter a negative number to terminate the program, it includes it with the rest of the averaged numbers. Any advice to get around this? I know it's possible, but the idea escapes me.
Your main loop should be like this:
#include <iostream>
for (int n; std::cout << "Enter a number: " && std::cin >> n && n >= 0; )
{
// process n
}
Or, if you want to emit a diagnostic:
for (int n; ; )
{
std::cout << "Enter a number: ";
if (!(std::cin >> n)) { std::cout << "Goodbye!\n"; break; }
if (n < 0) { std::cout << "Non-positve number!\n"; break; }
// process n
}
After here:
cout << "Please enter a number. The program will add up the odd and even ones seperately, and average them: ";
cin >> number;
Immediately check if the number is negative
if(number < 0) break;
Now you wouldn't need to use your do-while loop in checking if the number is negative. Thus, you can use an infinite loop:
while(true) {
cout << "Please enter a number. The program will add up the odd and even ones seperately, and average them: ";
cin >> number;
if(number < 0) break;
// The rest of the code...
}
ADDITIONAL:
There is something wrong in your code. You aren't showing the user how much the number of even and odd numbers are, and the total number of numbers entered.
ANOTHER ADDITIONAL: You should use more meaningful variable names:
int totalNumEntered = 0, sumEven = 0, sumOdd = 0, numEven = 0, numOdd = 0;
Of course I am not limiting you to these names. You can also use other similar names.
FOR THE INTEGER DIVISION PROBLEM:
You must cast your expression values to the proper type (in this case, it is float). You should also change the averages variables' types to float:
float avg1 = float(total1) / float(count1);
float avg2 = float(total2) / float(count2);
Immediately after cin >> number, check for < 0, and break if so. Try to step through the program line by line to get a feel for the flow of execution. Have fun learning, and good luck!