Please excuse this beginner's question. I've just started programming and I'm using C for the code below.
The purpose of this code is for the computer to guess a number the user has picked. The computer will narrow down the numbers available based on queues like 'too low' or 'too high'.
computer_guess(int answer)
{
int lownum, highnum, guess, answer;
//Instructions
printf("Please use 'h' for too high or 'l' for too low ");
printf("for incorrect guess. Use 'c' if the guess is right.\n");
guess = (lownum + highnum)/2;
printf("\n %d. \n", guess);
printf("Is this the right number?");
do
{
answer = getchar();
if (answer == 'h')
{
guess = (lownum + (highnum -1))/2;
printf("%d \n", guess);
}
else if (answer == 'l') //If the computer's guess is too high.
{
guess = ((lownum + 1) + highnum)/2;
printf("%d \n", guess);
}
else if (answer != '\n')//If the user enters letters other than 'h' or 'l', an error message will be returned.
{
fflush(stdin);
printf("Invalid. Please use either h (too high), l (too low) or c (correct).");
}
} while (answer != 'c');
if (answer == 'c')//If the correct answer is given, the game will end.
{
printf("The computer has guessed the right number.");
}
return 0;
}
The problem I'm running into is that my code seems to ignore my while condition (while (answer != 'c')). In my output, even if I enter 'c', it prints the Error statement in the last "else if" block and statement about being right.
This is the output:
Invalid. Please use either h (too high), l (too low) or c (correct). The computer has guessed the correct answer!
What do I need to do to make sure the error isn't printed when 'c' is entered?
Thank you!
Statements of your program are executed in the order pre-defined by C standard. This includes the computation of the while condition of the do/while loop.
The loop checks the condition upon reaching the end of loop's body. This includes execution of all if statements inside the loop, along with their else branches. Since you have no special handling for 'c' inside your loop, if (answer != '\n') branch gets executed, and gives the printout that you see.
You can fix this by using a "forever" loop, and handling 'c' input inside its body:
for (;;) {
answer = getchar();
if (answer == 'c') {
break;
}
... // The rest of your code goes here
}
Related
I'm creating a loop that basically has a (y/n) yes, no answer and I wanted to use an if else inside of a do while loop. When using the input == Y it seems to not accept it, so I'm wondering that's even possible in C? Or if I'm approaching in the wrong way.
I tried just a simple if input == Y but that didn't work, then I tried a strcmp and that didn't seem to work either. I'm at the strcmp part because I think I might be close to the answer with that but I'm not entirely sure if I'm understanding what's going on with the char values.
printf("Would you like to print another invoice? Y=yes, N=No\n");
do {
scanf("%s", &newInvoice);
if(strcmp(newInvoice, Y)!= 0) {
main();
}
else if(strcmp(newInvoice, N)!= 0) {
printf("Goodbye!\n");
}
else {
printf("Invalid Entry (it has to be y or n):\n");
}
} while(strcmp(newInvoice, N)!= 0);
When I had just input == Y it wanted me to initialize Ym and N so that didn't seem to be the answer. I would like the loop to repeat the question and input until they say yes or no; if they enter something like G or whatever other character it needs to loop again.
consider the following (changed abelenky's code a little). The below makes sure the lower case letters get accepted, but it's probably a little clunky, and may be represented a little more elegant.
int main()
{
char newInvoice, buffer;
do
{
newInvoice = getchar();
bufferClean(&buffer); //see underneath the code for the explanation.
if (newInvoice == 'Y' || newInvoice == 'y')
{
printf("you've chosen YES, continue ......\n");
break; // breaks the loop and continues with the code.
}
else if (newInvoice == 'N' || newInvoice == 'n')
{
printf("you've chosen NO, Goodbye!\n");
return 1; //main returns 1 and ends the program
}
else
{
printf("Invalid Entry (it has to be y or n):\n");
}
} while(1);
printf("exited the loop\n");
return 0;
}
Also, asking for users' input is a little tricky. I suggest clearing the buffer after using it, as it passes on the newline char and may skip any further input prompt.
I have created a little function to do so:
void bufferClean(char *buff)
{
while ((*buff = getchar()) != '\n' && *buff != EOF);
}
Just declare a char buffer in main() with no value, and pass it on to the function every time you want to clear the buffer (I do every time after asking for users' input). I'm a novice, and if I'm making any mistakes please point them out!
I'm completing an assignment and after completing it, I have 1 bug, and 1 bug fix I made that I don't fully understand. Currently, as long as the user does what is asked, everything works fine. But I know that doesn't happen often, so I'd love to know how to stop these issues.
Would love any advice - I am a complete beginner with C.
I found many different pieces of advice here: C: Multiple scanf's, when I enter in a value for one scanf it skips the second scanf
I added a space to my scanf() statements which solved some of the bugs - and I understand that \n is added onto the end of the entered strings / chars, I'm just not sure how to check for it / handle it, and I tried using getchar() in place of the scanf() but I still get double print / loop problems.
Bug Issue
When the user is running through the game loop, if they enter more than 1 character (for example: 'oo', when prompted with the scanf() to enter 'y' or 'n') my printf statements run 1x per character entered, and connect to each other:
Example would be:
Welcome to Two doors.
Would you like to play? (y/n):Welcome to Two doors.
Would you like to play? (y/n):
This issue also shows up if the user enters 'y' to play the game but then enters a character other than 1,2 or 3 in the second section.
How can I limit the length of their response? Or is the best way to monitor the length of the play and choice variables prior to entering the if statements? Maybe checking to see if they are longer than 1 character and if so, only taking the first character?
Second issue - bug fix that I don't understand
In the scanf() functions I ran into a very similar problem to what I described above, but it happened when the user entered any character. The solution I found was to add a space before the character ->
scanf(" %c", &play);
vs
scanf("%c", &play);
Is this issue only a problem when using loops? Since I never found these bugs prior to looping back through the code.
Updated Code with 'while (getchar() != '\n');' suggestion from Sourav Ghosh
#include <stdio.h>
int main(void) {
char play;
int choice;
char answer[] = "No matter which one you choose the guards both tell you which door leads to death, and therefore you can pick the other door.\n";
int gameLoop = 1;
int timesPlayed = 0;
while (gameLoop == 1){
if (timesPlayed == 0) {
printf("Welcome to Two doors.\n");
printf("Would you like to play? (y/n):");
} else {
printf("Would you like to play again? (y/n):");
}
scanf(" %c", &play);
while (getchar() != '\n');
if (play == 'y') {
// == instead of =
printf("\nYou are a prisoner in a room with 2 doors and 2 guards.\n");
printf("One of the doors will guide you to freedom and behind the other is a hangman --you don't know which is which.\n");
printf("One of the guards always tells the truth and the other always lies. You don't know which one is the truth-teller or the liar either.\n");
printf("You have to choose and open one of these doors, but you can only ask a single question to one of the guards.\n");
printf("What do you ask so you can pick the door to freedom?\n\n");
printf("\t1.Ask the truth-guard to point to the door of doom.\n");
printf("\t2.Ask the liar-guard to point to the door of doom.\n");
printf("\t3.Doesn't matter which one you pick.\n");
scanf(" %d", &choice);
while (getchar() != '\n');
switch (choice) {
case 1:
printf("%s", answer);
timesPlayed++;
break;
case 2:
printf("%s", answer);
timesPlayed++;
break;
case 3:
printf("%s", answer);
timesPlayed++;
break;
default:
printf("The Troll Smasher comes out from the shadows and squeezes the stupid out of you until you pop. GAME OVER!\n");
break;
}
} else if(play == 'n') {
printf("Sorry to hear that, we at Two Doors hope you have a super duper day!\n");
gameLoop = 0;
break;
} else {
printf("That is not a valid input, please try again by entering either 'y' to start the game or 'n' to quit the game.\n");
}
}
return 0;
}
The problem with %c format specifier is that, it will read only one byte from the input buffer and if the input buffer has more in store and the call in encountered next time, it will not ask for user input, it will simply read the next byte from the available input stream.
So, to answer
How can I limit the length of their response?
well, there's no straightway approach that you can stop the user from entering only X characters/ digits, instead, swipe off the excess, (if any) and for the next call, start with an empty buffer is an easy approach.
So, the quick way out of this would be, to clean off the standard input of remaining inputs. You can do something like
int retval = scanf(" %c", &play);
//some code
while (getchar() != '\n'); //eat up the input buffer
//next call to scanf(), input buffer is empty now....
to stop scanf() from reading already existing unwanted inputs and force it to ask the input from user.
Also, don't forget to check the return value of scanf() to ensure the success of the call.
For the first issue the problem is caused because the execution of the program enters the loop again for example if the user types oo that means that after reading with scanf it is going all the way to the last else.
Inside that else none of the variables is modified so when it reenters the loop gameLoop is still 1 and timesPlayed is still 0 so it will print the statements in the first if, then scanf will read the second o and repeat the process. The problem is that scanf reads one character at the time.
Actually for entering one character you can use getchar() but in any case after char input you should clean standard input stream. Consider the following example, that forces the user to the correct input:
char name[11];
char answer = 0;
printf("Would you like to play again? (y/n): ");
while ((answer = getchar()) != 'y' && answer != 'n')
{
printf("You should answer 'y' or 'n'\n");
// clean the buffer from mess
while (getchar() != '\n');
}
// clean the buffer from mess
while (getchar() != '\n');
// next input
printf("Enter your name: ");
scanf("%10s", name);
// clean the buffer from mess
while (getchar() != '\n');
UPDATE:
Just for clarification, the code
while ((answer = getchar()) != 'y' && answer != 'n')
{
printf("You should answer 'y' or 'n'\n");
// clean the buffer from mess
while (getchar() != '\n');
}
can be be easier to understand while rewritten as
char name[11];
char answer = 0;
printf("Would you like to play again? (y/n): ");
while (1) // infinit loop
{
answer = getchar();
// clean the buffer from mess (immideatly after reading)
while (getchar() != '\n');
if (answer == 'y' || answer == 'n') // check the input
break; // stop the loop if condition is true
// or ask again
printf("You should answer 'y' or 'n'\n");
}
// next input
printf("Enter your name: ");
scanf("%10s", name);
// clean the buffer from mess
while (getchar() != '\n');
in my first example I just optimize the code combining reading and checking the data in parentheses after while: (answer = getchar()) != 'y' is like two actions - answer = getchar() and then answer != 'y'
In the last snippet condition answer != 'y' && answer != 'n' was intentionally replaced with answer == 'y' || answer == 'n' to show difference between "do while data is incorrect" and "stop when correct data get"
I am still very new to programming, so I am not sure the correct action to take. I can't seem to get the program to display a different option when selected by the user. Either the first option displays, or it shows the 'Invalid Entry' text. I am only going to include the problem code, since I've tested the rest without the if/else statements and it calculates and displays correctly.
printf("Select interest type: S, Y, M \n\n");
scanf("%ch", &type); /*program has finished calculating and is waiting on user input. Variable 'type' has already been initialized as a char*/
printf("\n\nIn %i years, at %.2f percent interest rate, \n", n, R);
/*this is where the problem starts*/
if (type == 'S')
printf("Your investment becomes %.2f dollars, with simple interest.\n", futureVal_simp);
else
{
if (type == 'Y')
printf("Your investment becomes %.2f dollars, with annual compounding interest.\n", futureVal_yr);
else
{
if (type == 'M')
printf("Your investment becomes %.2f dollars, with monthly compounding interest.\n\n\n", futureVal_mnth);
else printf("Invalid entry.\n\n\n"); /*these are supposed to display based on char entered*/
}
}
return 0;
}
I checked other questions on the site, but am still not sure. Should I be using != and && instead of multiple if/else?
You want scanf("%c", &type); not "%ch". The %c means a character, the h means a literal h.
You also need to check the return value of scanf(). Always.
Using logical operator / if-else statement -- if they are equivalent, choosing one of them is your choice. (Maybe in this case, you can also use switch statement.)
But sometimes, using too long logical formula as a condition can reduce the readability of your code.
if(type == 'S')
{
content...
}
else if(type == 'Y')
{...}
else if(type == 'M')
{...}
else{...}
Because else if means else{if(...)} as itself, so you don't need to write another if/else statement in else block.
The best way I recommend is to use switch statement in this case. Branch conditions are not complex -- those conditions are just to check out whether the character 'type' is 'S', 'Y', 'M' or others. In this situation, switch statement can increase the readability of your code.
You've already got the answer from Mr #John Zwinck, but just for the sake of completeness,
You should change your scanf from
scanf("%ch", &type);
to
scanf(" %c", &type); // note the extra space before %c
This tells scanf() to ignore all previous whitespace-like charcaters and read the first non-whitespace input.
FYI, in previous case, the previously pressed ENTER keystroke [after previous input] was stored as a \n in the input buffer. Then, that \n being a valid input for %c, was being read by scanf(), producing the scenario
'%c' it doesn't ask for input at all.
Also, as an improvement, you can consider using a switch statement instead of if-else condition.
This question already has answers here:
Check if input is integer type in C
(16 answers)
Closed 8 years ago.
I am working on code for one of my classes and I have hit a wall. I need the user to input a number that will be used as the number of times a for loop will be repeated. The first loop where I ask for this number is a while loop. I need to make sure the value entered is a number and not a letter or special character.
I do not know how to make sure that it is not a letter or special character.
The next problem is making sure that the for loop only runs for the specified number of times that is the number provided in the first loop.
This is what I have written so far.
#include <stdio.h>
int main()
{
int num_of_scores, n;
char enter;
float score=-1, total=0, average;
do
{
printf("\n\nEnter the number of quiz scores between 1 and 13: ");
scanf ("%d, %c", &num_of_scores, &enter);
}
while(num_of_scores<1 || num_of_scores>13/* && enter == '\n'*/);
printf("\nStill Going!");
for(n=0; n<num_of_scores; n++)
{
printf("\nEnter score %i: ", n+1);
scanf ("%f", &score);
while(score>=0 || score<=100)
{
total = total + score;
score = -1;
break;
}
}
average = total / num_of_scores;
printf("\nThe average score is %.0f.\n\n", average);
return 0;
}
So I have edited the code a little bit. There is a part in the first while loop that is in a comment which i removed because it made the program end after that loop. The printf("still going") is just a test to make sure the program gets that far. Any further pointers? I am still not sure how to check make sure a number is not entered. I though adding the && enter == '\n' would do it, but if it hangs the program it is no good. Many of the examples you have suggested are good, but i find them a little confusing. Thanks!
I'd check Check if input is integer type in C for the answer to this...
Check the return value of scanf. Per the man page:
RETURN VALUE
These functions return the number of input items successfully matched and assigned, which can be fewer than provided
for, or even zero in the event of an early matching failure.
The value EOF is returned if the end of input is reached before either the first successful conversion or a matching
failure occurs. EOF is also returned if a read error occurs, in which case the error indicator for the stream (see
ferror(3)) is set, and errno is set indicate the error.
do{
char ch = 0;
num_of_scores = 0;
printf("\nEnter the number of quiz scores between 1 and 13: ");
if(scanf("%d%c", &num_of_scores, &ch)!=2 || ch != '\n'){
int ch;
while((ch=getchar())!='\n' && ch !=EOF);
}
} while(num_of_scores<1 || num_of_scores>13);
I'm a beginner with a few hours of expirience and I'm trying to make a really simple program to get familiar withe IF command. I came up with this code:
#include<stdio.h>
int main()
{
char ans;
char n;
char y;
printf("Do you want to exit?\n");
scanf("%c\n",ans);
if (ans == y)
{
printf("As you wish!\n");
return 0;
}
else (ans == n);
{
printf("You'll exit anyways!\n");
return 0;
}
}
I think it should work, but after I type something the program stops workig! Thanks in advance!
The
if (ans == y)
should read
if (ans == 'y')
The former compares ans to the value of the uninitialized variable y, whereas the latter checks whether ans contains the character 'y'.
The same goes for 'n'.
The y and n variables are unnecessary and can be removed.
Also, the following line is incorrect:
else (ans == n);
It should read
else if (ans == 'n')
(I've added the if and have removed the semicolon.)
Finally, the scanf() should read:
scanf("%c",&ans);
else (ans == n);
This doesn't give expected results. Remove the ; and the condition.
else may only take a body of code. It does not handle conditions.
If you want conditions, use else if:
else if (ans == 'n')
More errors:
if (ans == y)
y in here refers to the variable, which is declared but has no value. Surely you want to refer to the character 'y':
if (ans == 'y')
Also, scanf expects a pointer, so instead of ans, use &ans.
It needs to write to the memory address of the value. It doesn't care about the value.
You'll learn about pointers eventually. (Assuming you haven't gone over them in your few hours of experience)
There are three main errors.
You should pass pointers to the scanf function, so you have to add an ampersand before ans (&ans).
There is a trailing ; at the end of the else statement.
y refers to a variable (which does not exist), whereas you want to compare ans against the character 'y'.