Beginning C and I have a bug that is killing me [duplicate] - c

This question already has answers here:
Problems with C scanf("%c") function to read characters one by one
(4 answers)
Closed 6 years ago.
I am writing some code and I have a prompt in the program driven by a while loop where you make a choice. However, it prints the prompt twice every time it goes through the loop and I just can't figure it out.
while (choice != 'x');
{
printf("\nChoice (a)dd (v)iew e(X)it [ ]\b\b");
scanf("%c",&choice);
if (choice == 'a') add_record();
if (choice == 'v') view_record();
}
The printf line is the one that prints twice. Thanks in advance for any help.

When you enter a character (i.e. type 'a' and press 'Enter'), the newline character ('\n') is also being read in from stdin. You can add a leading space to the format specifier to avoid this:
scanf(" %c", &choice);
The space indicates to scanf to ignore whitespace characters (such as '\n').

There are few things to notice in the question posted.
The outer while loop behavior depends on the variables initialization at first then the values being entered subsequently.
It then manipulates into print the prompt to enter choice, repeatedly (not just twice) depending on how many characters entered as input before 'enter' key is pressed.
The char i/o driver buffers the input entered and each of the characters entered is read by scarf() one at a time in this case, from the buffer. So it is needed to rewrite the code to work as following (expected from my understanding)
char choice = '!', ws = ' ';
int attempts = 0;
while (choice != 'x')
{
printf("\nAttempt:%d Choice (a)dd (v)iew e(X)it [ ]\b\b", ++attempts);
// Eat up the '\n', if one exist and Wait for valid input
while ((scanf("%c", &choice) > 0) && (choice == '\n'));
// Eat up all white space and other chars entered so far, except the last '\n'
while ((scanf("%c", &ws) > 0) && (ws != '\n'));
if (choice == 'a') add_record();
if (choice == 'v') view_record();
}

Related

Basic Yes/No Program Abruptly Ends in C [duplicate]

This question already has answers here:
The program doesn't stop on scanf("%c", &ch) line, why? [duplicate]
(2 answers)
Closed 6 years ago.
I'm an absolute beginner to coding in C and I'm attempting to practice by writing a program where a user responds to Yes/No questions in a series, like if it were a game.
The problem that I'm having is that after the first question is answered, and the second pops up, the program doesn't give me (the user) a chance to respond to it; the program abruptly ends.
Obviously, there must be something simple that I'm missing here to go from one question to another without it terminating. I'd appreciate any advice.
Here's what I've made so far:
#include <stdio.h>
char answer, answertwo;
int main()
{
printf ("Are you laughing? (Y/N)\n" );
scanf ("%c", &answer);
if (answer == 'y' || answer == 'Y')
printf("\nGood\n");
else if (answer == 'n' || answer == 'N')
printf("\nBye\n");
printf("Do you want to read? (Y/N)\n ");
scanf ("%c, &answertwo");
if (answertwo == 'y' || answertwo == 'Y')
printf("\nGood\n");
else if (answertwo == 'n' || answertwo == 'N')
printf("\nBye\n");
return 0;
}
Two things:
You have a typo on the line scanf ("%c, &answertwo");, move the quote to the end of the first argument:
scanf ("%c", &answertwo);
The second call to scanf ends prematurely because it consumes the newline in stdin from the first call. Try replacing your format specifiers in scanf from "%c" to " %c" so that they will ignore whitespace before the actual character is input.

In C - scanf() in a for loop is causing printf() to run multiple times

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"

using printf( ) twice in a C program

I just started learning C and one of my assignment is asking me to ask user enter a character twice. Each time user enters a character, the program will give user a response. The problem I am having right now is that every time the user enters a character, the program stops to proceed to the next question. Can someone help me?
#include <stdio.h>
int main()
{
char reply,reply2;
printf("Are you an engineering major (Y/N)? ");
scanf("%c",&reply);
if (reply == 'y' || reply =='Y')
{
printf("Hey, you're an engineering major");
}
if (reply == 'n' || reply == 'N')
{
printf("You are not an engineering major");
}
printf("Are you a freshman (Y/N)?");
scanf("%c",&reply2);
if (reply2 == 'y' || reply2 =='Y')
{
printf("Hey, you're a freshman");
}
if (reply2 == 'n' || reply2 == 'N')
{
printf("You are not a freshman");
}
return 0;
}
Most likely the problem is a trap that a lot of newbies fall into: none of your printed strings have a newline. You need to add \n to the end of your strings, as in printf("You are not a freshman\n");
The reason is that typically stdout (the stream where printf writes its text to) is line buffered. This means that it buffers all text until it either sees a newline or is forced to flush its contents via fflush. Only then the text that was buffered up to this point appears on screen.
Edit: Your second problem is that the scanf format "%c" reads any character. (I'm not sure whether it's line buffered as well, but its behaviour looks a bit like it.) Your first call scanf("%c",&reply) reads the y or n character but leaves the newline from pressing enter still in the stream. Your second call scanf("%c",&reply2) then reads the newline which was still in the stream (you can see that by doing a printf("%d\n", reply2); which will print 10). To fix that, use the format string " %c" (notice the space!) which tells scanf to ignore whitespace.
Also, you should handle unexpected input:
if (reply == 'y' || reply =='Y')
{
printf("Hey, you're an engineering major.\n");
}
else if (reply == 'n' || reply == 'N')
{
printf("You are not an engineering major.\n");
}
else
{
printf("I don't understand the answer '%c'.\n", reply);
}
(Exercise: implement that logic using switch instead of if/else if/else ;-)
What's happening here is that you're only reading one character with the first scanf call, but in order to input this you would have to type y or n, and then press enter.
The enter is registered as another character on the input stream, a newline, but because the first scanf call reads only one character its still in the stream when it is called for the second time. This leads to reply2 = '\n', skipping your if statements and terminating the program.
Change
scanf("%c",&reply2);
to
scanf(" %c",&reply2);
This will tell scanf to skip all the whitespace characters and read the first non-whitespace char. Otherwise, there will be a newline character \n read onto the reply2 variable. See also this answer.
You need to add \n at the end of your printfs to make your output more cleaner and understandable.Also add a space before the %c in the second scanf.This is done because scanf does not consume the \n character after you enter the first character.As the Enter key
(\n) is also a character,it gets consumed by the second scanf.The space before the %c will
discard all blanks like spaces.

do while not execution, terminates unexpectedly [duplicate]

This question already has answers here:
C programming: character in scanf [duplicate]
(2 answers)
Closed 8 years ago.
I have the following code, i wanted to terminate the while loop if any key except 1 & 2 is press. but only do executes once. and not while. why my while condition is always false. please guide:
char a;
do
{
printf("To Enter the Employee sales press 1 \n");
printf("To Add more items press 2 \n ");
printf("Press any key to Terminate \n\n");
scanf("%c", &a);
if ( a == '1' )
{
printf("1 is presed ");
}
else if(a == '2')
{
int c;
printf("entre Value:");
scanf("%d",&c);
printf("\n");
addItem( &myArray, &size, c );
printitems(myArray, size);
}
}while(a == '1' || a == '2');
Edit So sorry, it was in single qout. i forgot to put the latest code. Even with qoutes it does not run while.
You need a space before your %c in scanf():
scanf(" %c", &a);
You're reading the first character that's entered and leaving one on the buffer. So if you enter:
'1' you're really getting two characters, first '1' then a '\n' (a "1" then a new line character, that happens when you hit enter). So it first stores '1' into a, then the second time it will read the remaining newline character into a, (it will apear to "skip" asking you for input). Since '\n' is not equal to '1' or '2' so it correctly exits.
Adding the space before the %c tells scanf() to ignore any white space left on the buffer (and new line characters count as white space)
You have declared 'a' as type char. and your while condition is
while(a == 1 || a == 2);
It should be
while(a == '1' || a == '2');

While loops duplicates printf two times before getting to getchar()? [duplicate]

This question already has answers here:
Using getchar() in a while loop
(3 answers)
Closed 9 years ago.
I'm currently learning C and C++ on my own. In this little "program practice" I ask the user to enter either 'i' or 'd' to know whether they want to work with integers or decimal (float) numbers. I have a while loop that makes sure the user enter 'i' or 'd' by telling them if they entered the wrong char. For some reason, the prompt inside the while loop prints two times before going to the getchar(). I'm having a bit of hard time understanding what's happening under the hood in this situation. Any help is super appreciated. I'm using Xcode (don't know if it's relevant).
#include <stdio.h>
int main()
{
char action;
printf("Please enter 'i' to work with integers or 'd' to work with decimals.\n\n");
scanf("%c", &action);
while (action != 'i' || action != 'd')
{
printf("You didn't entered the right command. Please try again (i/d)\n");
action = getchar()
}
}
So what I'm getting as an output is this:
You didn't entered the right command. Please try again (i/d)
You didn't entered the right command. Please try again (i/d)
What is happening is that when you enter a character and hit a return, you are actually entering two characters - the character and the return character ('\n'). The loop executes once for each character. Which is why you see it go through twice.
The trick is to filter out the return character explicitly, like so:
#include <stdio.h>
int main()
{
char action;
printf("Please enter 'i' to work with integers or 'd' to work with decimals.\n\n");
scanf("%c", &action);
while (action != 'i' || action != 'd')
{
if (action != '\n')
{
printf("You didn't entered the right command. Please try again (i/d)\n");
}
action = getchar();
}
}
As correctly diagnosed by Ziffusion in his answer, you get the double prompt because you get the newline after the user's incorrect input as a separate character, and that too is neither i nor d.
Here is a rewrite with some improvements:
#include <stdio.h>
int main(void)
{
char action = '\0';
printf("Please enter 'i' to work with integers or 'd' to work with decimals: ");
while (scanf(" %c", &action) == 1 && action != 'i' && action != 'd')
printf("You didn't enter the right command. Please try again (i/d): ");
printf("Action selected: %d\n", action);
}
What's changed?
The prompt doesn't end with a newline, so the user's response appears immediately after it. Standard I/O normally synchronizes standard output and standard input so that the prompt will be flushed, despite not ending with a newline. If the prompt doesn't appear, you can add a fflush(stdout); or fflush(0); after each of the prompting printf() statements.
The result of scanf() is checked to deal with EOF.
The format of scanf() includes a leading space. This will skip white space before the character that's returned, so you get a non-blank, non-newline character.
The original condition action != 'i' || action != 'd' is always true; you need the && instead.
Nitpick: improve grammar of error message.
Note that after the loop, action might not be either i or d if the user triggered EOF (typed Control-D or equivalent). If you get EOF (for example, the user ran the program with standard input from /dev/null), you would not have a deterministic value in action except for the initialization to '\0'.
Here I fixed you code:
#include <stdio.h>
int main()
{
char action;
printf("Please enter 'i' to work with integers or 'd' to work with decimals.\n\n");
scanf("%c", &action);
while (action != 'i' && action != 'd') // here the loop will stop if action is 'i' or 'd'
{
printf("You didn't entered the right command. Please try again (i/d)\n");
scanf("\n%c", &action);// here to deal with '\n'
}
}

Resources