Unexpected call of printf - c

This is the first question I've posted about C programming on here as I just started learning C just a few weeks ago. Ill write up my code and ask what my problem is :) If Anyone please knows how I can fix my mistake or whatever I should replace for my code please reply:)!
The problem I am having, is that if you run the code for yourself, you will see that everything works fine, except for the 'else' part in the statement. The issue I am having is that when someone types more than one letter, it will run the last printf statement more than once, and will printf as many times as the user inputs a character other than y or n.
The first part with the Y or N is working fine, yet if they type any number of other chars, it doesnt just state "Please select again", one time and then re-scanf, it types out at least 2 printfs, just for even one character entered, "Please select again" "Please select again", and then, if you type more chars for the answer, it will just type even more "please select again"'s.
Please help me understand what I am doing wrong as I'm so keen on learning to program properly, but I am just stuck here atm :)
#include <stdio.h>
#include <conio.h>
int main()
{
char answer;
int loop = 0;
printf("Please select. [Y/N]:\n");
while (loop == 0)
{
scanf("%c", &answer);
if (answer == 'y' || answer == 'Y')
{
printf("Seeyou Later Aligator.\n");
break;
return 0;
}
else if (answer == 'n' || answer == 'N')
{
printf("Mmkay.\n");
break;
return 0;
}
else
{
printf("Please select again [Y/N]:\n");
loop = 0;
}
}
getch();
return 0;
}

scanf reads the required number of characters each time. If there are more characters, they are not ignored. They are read next time you call scanf. Hence you see multiple prints for every character. Inorder to explicitly ignore pending input, call fflush(stdin) after scanf. Which means to flush out any data in standard input stream.
Update:
fflush should not be used on input streams as said in comments. Use the accepted solution for ignoring output. However I recommend using toupper or tolower instead of bit hack.

The reason as many have pointed out is that your scanf is reading the extra newline character left in the input buffer after the user presses ENTER. So here is an alternative way to read input to avoid that whole mess:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
char answer;
printf("Please select. [Y/N]:\n");
while (1)
{
scanf("%1s%*[^\n]", &answer);
answer |= 0x20;
if (answer == 'y')
{
puts("Seeyou Later Aligator.");
break;
}
else if (answer == 'n')
{
puts("Mmkay.");
break;
}
else
{
puts("Please select again [Y/N]:");
}
}
getchar();
return 0;
}
This will read just the first character found on stdin and ignore everything else after that and at the same time clear the input buffer of the newline character

break; is enough ... return will never be executed as you will break out of the while
Its printing more than once because scanf is taking in '\n' and extra inputs from previous entry
also the variable loop is pointless in your code
here is the fixed code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
char answer;
int loop = 0;
printf("Please select. [Y/N]:\n");
while (1)
{
scanf("%c", &answer);
if (answer == 'y' || answer == 'Y')
{
printf("Seeyou Later Aligator.\n");
break;
//return 0;
}
else if (answer == 'n' || answer == 'N')
{
printf("Mmkay.\n");
break;
// return 0;
}
else
{
printf("Please select again [Y/N]:\n");
while(getchar()!='\n'){
getchar();
if(getchar() == '\n'){
break;
}
}
}
}
getchar();
return 0;
}
Output:
$ ./test
Please select. [Y/N]:
dddd
Please select again [Y/N]:
ffffff
Please select again [Y/N]:
y
Seeyou Later Aligator.

Related

C program doesn't wait for user input with scanf()

I'm new to C and this is my TicTacToe for first C project. For that, I setup a simple process for user where to choose X or O. But it doesn't seem to work for reason. Here it continues to the if statements and goes into infinite loop cause it didn't wait for user input.
I've gone through similar forums about this exact question but I was unable to get an answer that fixed my problem. Also, feedbacks about the code are much appreciated because I do want to improve my code.
#include <stdio.h>
#include <stdlib.h>
void main()
{
char checks_player;
int is_input_valid = 0;
while(is_input_valid == 0)
{
printf("What do you want to choose? (X/O) ");
scanf(" %c",checks_player);
if(checks_player == 'x')
{
checks_player = 'X';
is_input_valid = 1;
}
else if(checks_player == 'o')
{
checks_player = 'O';
is_input_valid=1;
}
else if((checks_player == 'O')|| (checks_player == 'X'))
{
is_input_valid = 1;
}
else
{
printf("Invalid Input!!\nTry Again.\n\n");
}
}
}
You need to pass a pointer to scanf. Instead of this:
scanf(" %c",checks_player);
Use this:
scanf(" %c", &checks_player);

How to fix - unexpected output using getchar() and do-while

I am trying to make a simple code that will read a char from input and execute "Correct" or "Incorrect input" and run the code again until the correct input is entered. First of all it does not work for capital X. The other issue that I want to fix is that after the incorrect input I have to press enter to get the "Enter x" message, instead of getting in immediately after the incorrect input message.
#include <stdio.h>
int main()
{
do
{
printf("Enter x\n");
if (getchar()=='x'|| getchar()=='X')
{
printf("Entered char is X\n");
return 0;
}
else
{
printf("Input incorrect! Please try again!!!\n");
}
}
while (getchar()!='x' || getchar()!='X');
return 0;
}
You need to store the input in a variable, otherwise you keep asking for input several times in a row, for each getchar call.
For weird historic reasons, getchar actually returns an int, since the value EOF that can be returned from it is an int. So the variable must be int.
And finally, each time the user hits enter, a invisible line feed character \n is appended to the input stream. This character does you no good, so you should discard it with an extra read.
#include <stdio.h>
int main (void)
{
int input;
do
{
printf("Enter x\n");
input = getchar();
getchar(); // extra getchar to chew up line feed from stdin
if (input=='x'|| input=='X')
{
printf("Entered char is X\n");
}
else
{
printf("Input incorrect! Please try again!!!\n");
}
} while (input!='x' && input!='X');
return 0;
}
Please note that the opposite of input=='x'|| input=='X' is input!='x' && input!='X' (De Morgan's laws). "If input is not 'x' and input is not 'X' then loop".
When you hit the ENTER key the newline character \n is placed in input buffer. You need to consume that newline character in order to read the next character.
Also you are reading two time, which is unnecessary in this case. So your code should be like this
#include <stdio.h>
int main()
{
char inp;
do
{
printf("Enter x\n");
inp = getchar();
getchar(); // reading the newline character '\n'
if (inp == 'x'|| inp =='X')
{
printf("Entered char is X\n");
return 0;
}
else
{
printf("Input incorrect! Please try again!!!\n");
}
}
while (inp !='x' || inp !='X');
return 0;
}
p.s There is no need to put condition checking in while loop, since you are returning in if condition. while(true) would work fine. Thanks #bruno for pointing that out.
In your code:
if (getchar()=='x'|| getchar()=='X')
getchar() is called twice.
Instead, you should write it this way:
char c = getchar();
if (c=='x'|| c=='X')
for the second part, if your goal is print the message on a new line, then just simply change your printf to:
printf("\nInput incorrect! Please try again!!!\n");

How would I only let the user input one character in c

If I only want the user to enter one char, how would I go about doing that in the c language. My attempt at this is below but it failed horribly. From what i read online I heard you could use the function gets or fgets to accomplish this, but I could not figure out how.
do
{
geussNumber += 1;
printf("Enter guess number %d\n", geussNumber);
scanf(" %c", &geussLetter);
scanf ("%c", &inputViolation);
if (isalpha(geussLetter) == 0)
{
printf("You did not enter a letter\n");
}
else if (inputViolation == true)
{
printf("You eneterd more than one letter\n");
}
else
{
inputLoopEnd = 1;
}
}
while( inputLoopEnd == false );
You could use the getc family of functions.
Have a look at http://quiz.geeksforgeeks.org/difference-getchar-getch-getc-getche/ for example.
It seems you want to read input one line at a time (i.e. the user types a one-letter guess and then <enter>), and you want to verify that the guess indeed contains only a single letter. Couching the problem in those terms perhaps makes it clearer how fgets() could be applied, as that function's purpose is to read one line at a time. Having read a whole line -- or at least as much as the buffer can accommodate -- you can validate it and extract the guess.
scanf() is hard to use properly, so I do recommend the fgets() approach. If you insist on using scanf(), however, then you might do it like this:
// consumes leading whitespace, inputs one character, then consumes any
// immediately-following run of spaces and tabs:
int result = scanf(" %c%*[ \t]", &guessLetter);
if (result == EOF) {
// handle end-of-file ...
} else {
assert(result == 1); // optional; requires assert.h
int nextChar = getchar();
if ((nextChar == '\n') || (nextChar == EOF)) {
// handle multiple-character guess ...
} else if (!isalpha(guessLetter)) {
// handle non-alphabetic guess ...
} else {
// it's valid ...
}
}
Do not use things like fgets() or fputs() etc... They are falling out of use.
As you can see from the description here... this function is designed to handle objects of type str, and you are more focused on using chars at the moment so why not just handle only chars to make life easier.
You can't do this the way you think you can...
scanf(" %c", &geussLetter);
scanf ("%c", &inputViolation);
This can't work because even if the user enters in only one char the way they are supposed to, it's still going to trigger your inputViolation scheme.
Edit: 12:14pm 7/20/2016
I really like the elegance of MOHAMAD's solution on the community wiki.
So I edited to fit your situation and it works well here too. Same idea...
#include <stdio.h>
#include <stdlib.h>
int clean_stdin()
{
while (getchar() != '\n');
return 1;
}
int main(void)
{
int first_time_around = 0;
char theguess = 0;
char c;
do
{
if (first_time_around == 0)
first_time_around++;
else
printf("Wrong input \n");
printf("Enter guess number: \n");
} while (((scanf("%c%c", &theguess, &c) != 2 || c != '\n')
&& clean_stdin()) || !isalpha(theguess));
return 0;
}

Can't clear the stdin using fflush(stdin), after using getchar(), in an infinite for loop C prog

I have just started off with C programming and while I was trying to write a programme to accept only y or n characters I came across that
#include <stdio.h>
#include <stdlib.h>
int main()
{
char ch;
printf("Do you want to continue\n");
for (;;)
{
ch=getchar();
if (ch=='Y' || ch=='y')
{
printf("Sure!\n");
break;
}
else if (ch=='N'||ch=='n')
{
printf("Alright! All the best!\n");
break;
}
else
{
printf("You need to say either Yes/No\n");
fflush(stdin);
}
}
return(0);
}
When I run this code, and type in any other character other than Y/y or N/n, I receive the last printf statement (You need to say either Yes/No) as output twice.
I understand that this is happening because it considers enter, i.e, '\n' as another character.
Using fflush doesn't help as it's an infinite loop.
How else can I modify it so that the last statement is displayed only once?
You can use a loop to read any characters left using getchar():
ch=getchar();
int t;
while ( (t=getchar())!='\n' && t!=EOF );
The type of ch should int as getchar() returns an int. You should also check if ch is EOF.
fflush(stdin) is undefined behaviour per C standard. Though, it's defined for certain platforms/compilers such as Linux and MSVC, you should avoid it in any portable code.
Another option - use scanf ignoring white spaces.
Instead of ch=getchar();, just need scanf( " %c", &ch );
With this you can also get rid of fflush(stdin);
Like is said in my comment you should use int ch instead of char ch because the return type of getchar which is int.
To clean stdin you could do something like the following:
#include <stdio.h>
#include <stdlib.h>
int main(void){
int ch,cleanSTDIN;
printf("Do you want to continue\n");
for (;;)
{
ch = getchar();
while((cleanSTDIN = getchar()) != EOF && cleanSTDIN != '\n');
if (ch=='Y' || ch=='y')
{
printf("Sure!\n");
break;
}
else if (ch=='N'||ch=='n')
{
printf("Alright! All the best!\n");
break;
}
else
{
printf("You need to say either Yes/No\n");
}
}
return(0);
}
Any way a do while will probably do the job for you:
#include <stdio.h>
#include <stdlib.h>
int main(void){
char ch;
int check;
do {
printf("Do you want to continue: ");
if ((scanf("%c",&ch)) == 1){
while((check=getchar()) != EOF && check != '\n');
if ((ch == 'y') || (ch == 'Y')){
printf("Alright! All the best!\n");
break;
} else if((ch == 'n') || (ch == 'N')){
printf("You choosed %c\n",ch);
break;
}else{
printf("You need to say either Yes/No\n");
}
}else{
printf("Error");
exit(1);
}
}while (1);
return 0;
}
Output1:
Do you want to continue: g
You need to say either Yes/No
Do you want to continue: y
Alright! All the best!
Output2:
Do you want to continue: n
You choosed n
Or we can simply use another break; statement after the last printf().

How to fix the running of my program in terms of conditional statements and output in C?

I have a problem with my input for my program:
#include <stdio.h>
#include <stdlib.h>
int confirm()
{
char c;
printf("Confirm (y/n): ");
scanf("%c", &c);
while (scanf("%c", &c))
{
if (c == 'Y' || c == 'y' || c == 'N' || c == 'n')
{
printf("\nThank you. \n");
break;
}
else
{
printf("\nInput not recognised, ry again. \n");
printf("Confirm (y/n): ");
}
}
}
int main(int argc, char* argv[])
{
confirm();
return 0;
}
When it executes, it asks the first question and inputting the answer is fine. However after entering the character (either y or n) the program prints the second question and stops. The whole program is not running. I don't know what I'm doing wrong.
Loose the first scanf at line 9 and (for me) it then seem to work correctly: if ynYN is entered then the confirm function exits, otherwise it continues looping

Resources