1. ## Random guessing game

I'm trying to program a simple game where the user has to guess a number between 1 and 1000. The game works for the most part, however it always displays the "You are correct! Play again? (y or n)" message twice. I don't understand why. Could someone here take a look at my code and point me in the right direction? I'd greatly appreciate it. The game is supposed to start over again, with a new random number if the user wins and presses 'y' - it's supposed to end if the user wins and presses 'n'.

Code:
```#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(){

int i = 1;
int ran = 0;
int input = 0;
char cont = 0;

srand( time( NULL ) );
ran = 1 + ( rand() % 999);

printf( "I have a number between 1 and 1000.\nCan you guess my number?\nPlease type your first guess.\n");

while( i != 0){
scanf( "%d", &input);
if( input != ran ){
if( input > ran)
printf("You're too high. Try again.\n");
if( input < ran)
printf("You're too low. Try again.\n");
}
if(input == ran){
printf("You're correct! Play again? (y or n)\n");
scanf("%c", &cont);
if( cont == 'y'){
cont = 0;
printf( "I have a number between 1 and 1000.\nCan you guess my number?\nPlease type your first guess.\n");
}
if( cont == 'n'){
printf("Ending game.\n");
i = 0;
}
}

}

return 0;
}```

2. You need to test for Y as well as y, then loop the question if y, Y, n, N is not pressed. Also, you'll need to get another random number when the user presses Yes. Reset your `input` also.

3. It's just another example of using broken scanf() to handle user input.

It doesn't handle errors gracefully, and you don't even check them at all.
Use fgets() and sscanf(), see the FAQ.

Also, there seems to be confusion over whether it is 'cont' or 'i' which is the exit condition. Perhaps better named variables would help.

Also, you don't calculate another 'ran' if yes is selected.

4. Originally Posted by Salem
It's just another example of using broken scanf() to handle user input.

It doesn't handle errors gracefully, and you don't even check them at all.
Use fgets() and sscanf(), see the FAQ.

Also, there seems to be confusion over whether it is 'cont' or 'i' which is the exit condition. Perhaps better named variables would help.

Also, you don't calculate another 'ran' if yes is selected.
cont is the variable that holds the input for one of the scanf functions. I used an if statement to check to see what cont was equal to after the scan - if it was equal to n, it set the continuation variable ( i ) to zero. That way it doesn't loop again.

Kennedy: That sounds like a switch statement. I'll try using that, but this should be simple enough to work without it, if I wasn't worried about looking for both the lowercase and captial of y and n, right?

I'd rather do this with the knowledge that I know from my book than with some functions that I don't know about yet. My book assumes I should be able to do it with scanf.

I'm just worried why my program breaks when I try to start a new game or end the game. It loops the "You are too high!" or the "You are too low!" message.

Should I try using getchar for y and n?

5. Let me guess -- you typed "yes" when asked if you wanted to play a new game.

Well, the scanf("%c") only reads the 'y' -- "es\n" is still in the input stream. The next scanf() comes looking for a number and finds an 'e'. It gets confused and returns an error code without doing anything. The next scanf() will do the same thing. You have an infinite loop there, as you have described.

There are two things you could do to rectify this problem. Either type only 'y', or fix it.

To fix it, first put a loop after the scanf("%c") that will read in the rest of the characters in stdin.
Code:
```int c;  /* must be int to hold EOF */
while((c = getchar()) != '\n' && c != EOF);```
You should also check the return value of scanf() to see if an error occured. scanf() returns the number of items successfully read, so if you pass it "%d", it will return 1 on success. Passing it "%i%i%i" could result in 0, 1, 2, or 3 (and possibly others). If it did encounter an error, clear stdin again with the above code.
Code:
```while(scanf("%d", &integer) != 1) {
while((c = getchar()) != '\n' && c != EOF);
printf("Invalid number, try again: ");
}```

6. Originally Posted by dwks
Let me guess -- you typed "yes" when asked if you wanted to play a new game.
No, I only typed y or n. The program still breaks, so I don't think making the changes you've suggested would fix the problem. I'll give it a try when I get home, but that's not what broke the program. Thank you very much for your help though.

Does anyone else see why the program would break when trying to start a new game?

7. I've fixed the program. I'm not completey sure, but I believe my problem was using scanf to read in the input expecting it to be a %c - I thought this stood for character, but apparently I needed to be reading it in as a %s for string. I've since re-written the program to use a switch statement. I realize that this still has no error checking, and it can be broken easily, I'm sure (because scanf seems to be poorly designed) but this completes what the excersize in the book calls for. My assignment is now complete.

Thank you all for helping me in the right direction. Here's a post of my code incase someone catches something that I did not. I'm new to programming, so if you see a goof I've made, or something that I've made too complicated, give me a heads up and help me learn. I'm sure there's plenty of room for improvement with this simple game. Please note that I actually print the random number for debugging purposes. Since the program seems to be working as intended, this could be removed.
Code:
```#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(){

int i = 1;
int ran = 0;
int input = 0;
char cont = 0;

srand( time( NULL ) );
ran = 1 + ( rand() % 999);

printf("The random number is %d. This is for debugging purposes.\n", ran);
printf( "I have a number between 1 and 1000.\nCan you guess my number?\nPlease type your first guess.\n");

while( i != 0){
input = 0;				/* Reset input. */
scanf( "%d", &input);	/* Ask for input, and store it inside the variable input. */

/* If the input does not equal the random number, check this. */
if( input != ran ){
if( input > ran ){
}

if( input < ran ){
}
}

/* If the input does equal the random number, make a new random number. Ask if
the user wants to play another game. If not, end the program. */
if( input == ran){
ran = 1 + ( rand() % 999);
printf("Correct! Would you like to play again? ( y or n)\n");
scanf("%s", &cont);
switch(cont) { /* check the input inside of the variable cont */
case 'y':
case 'Y':
ran = 1 + ( rand() % 999);
printf("Starting new game.\n");
printf("The random number is %d. This is for debugging purposes.\n", ran);
printf( "I have a number between 1 and 1000.\nCan you guess my number?\nPlease type your first guess.\n");
break;

case 'n':
case 'N':
printf("Ending game.\n");
i = 0;
break;

default:
printf("Wrong input.\n");
break;
}
}

}

return 0;
}```

8. First of all, when using scanf() to read in characters, you should not point to the address of the variable... So there should be no "&" symbol before your variable "cont"...

Here is what I would do:

Code:
```if( input == ran){
ran = 1 + ( rand() % 999);
printf("Correct! Would you like to play again? ( y or n)\n");
scanf("%c", cont);
if ((cont == 'y') || (cont == 'Y')) {
// blah blah blah
}
if ((cont =='n') || (cont == 'N')) {
// blah blah blah
}
else {
// blah blah blah
}
}```
it gets rid of those nasty switch statements!
hope that helps!

9. Post #3 and Post #5 both tell you to NOT use scanf. You say you must use scanf. Okay, then in Post #5 you are told why you you aren't getting results you expect. You aren't just entering 'y' or 'n'. There is also a '\n' at least. Also, you still haven't put a while() loop around your switch. Use the switch if you want, but for only 2 vs 2 argument the if statement would be better.

10. I know it is C++, but using srand() and rand() would make the program much smaller and easier to read

Code:
```srand((unsigned)time(0));

int num = rand() % 1000 + 1;```
Then use a do-while loop or a for loop to keep looping untill answer is correct

11. Originally Posted by Kennedy
Post #3 and Post #5 both tell you to NOT use scanf. You say you must use scanf.
Post three may tell me not to use scanf, but why would I use code when I have no idea what it does? I posted here asking why my code didn't work as expected, not how to completely rewrite it just because scanf is considered to be broken. I'm learning from a book. At the end of each chapter are excersizes that you should be able to complete with the knowledge you have learned from each previous chapter. Right now, the only thing I understand is scanf. Not sscanf, not fgets, nothing. So again, why would I use these functions when I don't understand them, and up until this point have not even heard of? The object of doing these excersizes is to understand the code, not use more efficient functions that are built into C that I know nothing about. If I start throwing in things that I haven't learned about, not only will I not learn anything, but I'll be confused if I come back to this code at a later date for guidance.

Okay, then in Post #5 you are told why you you aren't getting results you expect.
Lets take a look at exactly what post five told me.

Let me guess -- you typed "yes" when asked if you wanted to play a new game.

Well, the scanf("%c") only reads the 'y' -- "es\n" is still in the input stream. The next scanf() comes looking for a number and finds an 'e'. It gets confused and returns an error code without doing anything. The next scanf() will do the same thing. You have an infinite loop there, as you have described.
This post, while giving a correct way to fix my problem, did not seem to be correct to me at the time. Realize that I'm new, so I don't readily understand code when I see it. I have to disect it, look up definitions, etc. I did not understand, and still do not understand how to implement (although I do understand how it works) what his code did, However, his assumption that I typed in a full word instead of y or n was wrong. That's all I typed in. You say that the new line character, \n is passed on. That's not something easily realized when you're new to programming, and may explain why I was getting the errors. However, post five made no mention of the \n character, and for all I knew, n or y was all I was passing on.

Also, you still haven't put a while() loop around your switch. Use the switch if you want, but for only 2 vs 2 argument the if statement would be better.
I haven't put a loop around my switch statement because I'm still working on understanding how to implement it, and how to understand it. As is, my program works as intended, but does not take into account user error. It doesn't take this into account because my book does not call for it, and I have learned little about implementing it. Perhaps it's covered in another chapter. I'm still early in the book. From what I understand, the loop around the switch statement would check the scanf for errors, and allow more than one character to be passed onto the scanf without breaking the program.

Yes, using the if statement would be better. I see that now. However, being new to programming, I don't see every viable solution all at once. I saw that the switch statement would work, and knowing how to use it, I implemented it. It worked, and I was happy. Sure, it may not be as efficient as the if statement, but it's not wrong either. Maybe next time a problem like this comes to me, I'll realize that the if statement would work better than the switch statement. I hadn't thought of using an if statement with || to check for one case or the other.

I'm here to learn. Programming is not an easy task (atleast for most of us). If my book wants me to continue using scanf, I will until it teaches me about the other functions. That way I learn about them in full, instead of just jimmy rigging them into my program because others feel they are more efficient. I'll be looking up the functions suggested here, but if I dont' understand them, I'm not going to fret much. I'll learn them when I get to them. I'm not here to make a bullet-proof program, just to do a few excersizes to make sure I'm where I should be. I appreciate the help I recieved here, and your posts did help me track down the problem. However, I was looking to fix my program using the functions I had posted, not find more efficient ones. I see no problem with using scanf, and my book more than likely wants me to use it so that I understand at an early stage how to implement basic error checking, rather than have a function do everything for me. Learning too much too quickly is not always a good thing.

12. If you persist with scanf, then get used to all sorts of funnies.

Rule 1 - scanf leaves input.
So if you type in
1234ABCD<return>
and you try and read with %d, then you will have ABCD<return> to deal with at some later stage. Unless you're careful, even minor user typos will mess with your head.

Rule 2 - scanf skips leading white space, and stops at trailing white space.
For everything except %c conversions.

Rule 3 - if the conversion doesn't happen, then the data is still there.
Type in
ABCD<return>
and you try and read with %d, then you will have ABCD<return> to deal with.
Recovering from user input errors is a PITA, made even worse by the fact that few people even bother to look at what scanf() returns.

Keeping track of exactly where you are is hard work, even when the user is playing by the rules.

Oh, and ignore anyone who suggests using fflush(stdin) as a solution to the woes of dealing with input that scanf() doesn't deal with.

> If my book wants me to continue using scanf
Skip ahead, and find out how much longer you have to wait before you get to fgets()

13. Originally Posted by Nalif
Post three may tell me not to use scanf, but why would I use code when I have no idea what it does? I posted here asking why my code didn't work as expected, not how to completely rewrite it just because scanf is considered to be broken. I'm learning from a book. At the end of each chapter are excersizes that you should be able to complete with the knowledge you have learned from each previous [COLOR="Magenta"]chapter. Right now, the only thing I understand is scanf. Not sscanf, not fgets, nothing. So again, why would I use these functions when I don't understand them, and up until this point have not even heard of? The object of doing these excersizes is to understand the code, not use more efficient functions that are built into C that I know nothing about. If I start throwing in things that I haven't learned about, not only will I not learn anything, but I'll be confused if I come back to this code at a later date for guidance.
It seems to me your problems arise because you don't know how to use scanf. So by your own argument, why are you using it?

Originally Posted by Nalif
I haven't put a loop around my switch statement because I'm still working on understanding how to implement it, and how to understand it. As is, my program works as intended, but does not take into account user error. It doesn't take this into account because my book does not call for it, and I have learned little about implementing it. Perhaps it's covered in another chapter. I'm still early in the book. From what I understand, the loop around the switch statement would check the scanf for errors, and allow more than one character to be passed onto the scanf without breaking the program.
It's really not a user error, it's a programmer error (failure to handle input correctly). Perhaps that's why these issues were brought to your attention.

Originally Posted by Nalif
I'm here to learn. Programming is not an easy task (atleast for most of us). If my book wants me to continue using scanf, I will until it teaches me about the other functions. That way I learn about them in full, instead of just jimmy rigging them into my program because others feel they are more efficient. I'll be looking up the functions suggested here, but if I dont' understand them, I'm not going to fret much. I'll learn them when I get to them. I'm not here to make a bullet-proof program, just to do a few excersizes to make sure I'm where I should be. I appreciate the help I recieved here, and your posts did help me track down the problem. However, I was looking to fix my program using the functions I had posted, not find more efficient ones. I see no problem with using scanf, and my book more than likely wants me to use it so that I understand at an early stage how to implement basic error checking, rather than have a function do everything for me. Learning too much too quickly is not always a good thing.
Perhaps your books happens to suck because it does not tell you how to program correctly. If this is so and you know it, would you still discard sound advice in favor of unsound advice from a book?

14. Originally Posted by Dave_Sinkula
It seems to me your problems arise because you don't know how to use scanf. So by your own argument, why are you using it?
Let me restate. I do not understand scanf. However, I understand it much more than any other comparable function. I can't claim to fully understand any function I've ever used, because I've never taken a look at C's header files to see how they work and exactly what they do. For now, I usually know when I can use them, and I vaguely know what they do.
It's really not a user error, it's a programmer error (failure to handle input correctly). Perhaps that's why these issues were brought to your attention.
For now, I'm not so much interested in whos error it is. It's enough for me to realize that the problem is there and that I'll eventually realize how to deal with it.
Perhaps your books happens to suck because it does not tell you how to program correctly. If this is so and you know it, would you still discard sound advice in favor of unsound advice from a book?
This may indeed be true. I'm using C How to Program by Dietel, fourth edition. Do you know anything about the quality of this book?

Don't look at it as discarding sound advice - I said I would look up the functions recommended. I'm just afraid that I'll get ahead of the book and miss out on things I should have learned along the way. Even worst, that I get lost and become discouraged with programming all together.

15. Good attitude. (No sarcasm.)

You can take the long road or frustration and cling to scanf, or you can jettison it in favor of better ways (previously mentioned).
One of my rants.

One of these days I may feel I've got a comprehensive hold of scanf, but until then I'll wing it and avoid it because I know many bad things that come from using it.

And I know nothing of value regarding your book.
Originally Posted by Nalif
For now, I'm not so much interested in whos error it is. It's enough for me to realize that the problem is there and that I'll eventually realize how to deal with it.
The "how to deal with it" was already presented.

Originally Posted by Nalif
Even worst, that I get lost and become discouraged with programming all together.
Even worse, if you don't listen to the presented advice, you may become discouraged with programming altogether.