I am creating a simple Tic Tac Toe for C, and here is a particular function which I am having a problem with. This is supposed to let the user select 'X' or 'O', and for the most art it works. However, if I enter a wrong symbol, it prints the statement:
"Invalid symbol, please re-enter: " twice.
Why and how can I fix this?
char assign(void)
{
char user;
printf("Would you like to be X or O (Enter your choice): ");
user=getchar();
while(user != 'X' && user != 'x' && user != 'O' && user != 'o')
{
printf("Invalid symbol, please re-enter: ");
user=getchar();
}
if(user == 'O' || user == 'o') return('O');
else if(user == 'X' || user == 'x') return('X');
}
The problem cause is related to the newline charachter
use scanf() in this way instead of using getchar()
scanf(" %c", &user);
It's because when you use getchar it returns the next character, but leaves the newline in the input buffer. So the next getchar returns that newline.
You should also be careful because getchar actually returns an int and not a char.
You can solve this either by another getchar, or use scanf like this:
scanf("%c ", &user);
Note the space after the c in the above format, it tells scanf to read and disregard trailing whitespace.
You could also read a line with e.g. fgets and then use a simple sscanf on that line, then no extra space is needed.
You could fix it like this for example:
char assign(void)
{
char user;
char throwaway_newline;
printf("Would you like to be X or O (Enter your choice): ");
user=getchar();
throwaway_newline = getchar();
while(user != 'X' && user != 'x' && user != 'O' && user != 'o')
{
printf("Invalid symbol, please re-enter: ");
user=getchar();
throwaway_newline = getchar();
}
if(user == 'O' || user == 'o') return('O');
else if(user == 'X' || user == 'x') return('X');
}
You have a newline in your input buffer.
When you press a character which is not [xX] and not [oO] and follow it with a newline. getchar actually gets to see 2 characters(the newline and the invalid character)
You may want to use fgets instead of relying on character input and ignoring newlines with 2 getchar() calls everytime.
Related
Look at the example:
#include<stdio.h>
int main()
{
char ch;
while(scanf("%c", &ch))
{
if(ch == 'a' || ch == 'e' || ch == 'i' ||
ch == 'o' || ch == 'u' || ch == 'A' ||
ch == 'E' || ch == 'I' || ch == 'O' ||
ch == 'U')
{
printf("It's Vowel\n");
}
else if((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
{
printf("It's Consonant\n");
}
else
{
printf("Wrong Input/ It's not Alphabet\n");
}
}
return 0;
}
After compiling this example code, when I enter 'a', The output is "It's Vowel" and "Wrong Input/ It's not Alphabet". I think the cause for this output is, the compiler takes the character also takes the enter press as a character.
Is there any way to solve this problem?
I think the cause for this output is, the compiler takes the character also takes the enter press as a character.
It's not the compiler who takes characters. Getting input is a run-time operation. When the program is already running, the work of the compiler is far done, but beside that your guess is correct. It is because scanf() doesn't consume the newline character with made by the press to Enter at the first step.
This newline character then get read at the next iteration by scanf("%c", &ch)) and as the newline character is a legit character it is stored inside of ch.
Is there any way to solve this problem?
Use
while(scanf(" %c", &ch))
instead of
while(scanf("%c", &ch))
Notice the white space character (' ') before %c. This will fetch the abandoned newline character left in stdin from the last iteration.
I've been trying to get this code to work but the loop does not seem to work? I am very new to C and I sort of get confused with the syntax of this language. However my loop is not functioning like how I want it to be. I want the if and else statement to work but no matter what input (right or wrong) it always outputs "thank you".
#include <stdio.h>
#include <stdlib.h>
int confirm()
{
char c;
printf("Confirm (y/n): ");
scanf("%c", &c);
while (scanf("%c", &c))
{
if (c = 'Y' && 'y' && 'N' && 'n')
{
printf("\nthank you");
break;
}
else
{
printf("\nInput not recognised, try again. \n");
printf("\nConfirm (y/n): ");
scanf("%c", &c);
}
}
}
int main(int argc, char* agrv[])
{
confirm();
return 0;
}
it won't ask to enter another output when the output is incorrect. It just keeps ending from the if statement, thus the loop is not running?
Please help.
There's nothing wrong with your loop - it's the if statement that's wrong.
This code compiles, but it does not do what you want it to do:
if (c = 'Y' && 'y' && 'N' && 'n')
= is an assignment; you need == to do a comparison
&& means "AND"; you need ||, which means an "OR"
You combine logical expressions, not constants with && or ||
The condition should be
if (c == 'Y' || c == 'y' || c == 'N' || c == 'n')
Also note that when you read single characters with %c, your program "sees" all characters, including whitespace. This is a problem, because the '\n' left over in the buffer will be passed to your program before Y or N. To fix this, add a space before %c to your format string:
scanf(" %c", &c)
// ^
// |
// Here
Your code also ignores the first character that it reads. I think this is not intentional, so remove the call of scanf before the loop. You should also remove the second scanf from the loop, leaving the only call to scanf in the loop header.
int confirm()
{
char c;
printf("Confirm (y/n): ");
//scanf("%c", &c);// <---------- needless
while (scanf("%c", &c)) //<----while loop will do `scanf("%c",&c)`, so previous line should be remove.
{
if (c == 'Y' || c == 'y' || c == 'N' || c == 'n')// <- &&(AND); ||(OR). Also, be careful that don't be lazy, [c == 'Y' || 'y' || 'N' || 'n'] can't to communicate with computer
{
printf("\nthank you");
break;
}
else
{
printf("\nInput not recognised, try again. \n");
printf("\nConfirm (y/n): ");
scanf("%c", &c);
}
}
}
I want to exit my do-while loop when the user enters "exit" from the command line. I'm trying to do it without using strcmp() but it's just not performing how I think it should. When testing it if the user enters e for the first character, or x for the second character, or i for the third, or t for the fourth character then the program exits. It's probably something simple that I'm missing. So can anyone explain why this isn't working how I'm expecting? Thanks.
#include <stdio.h>
#define FLUSH while(getchar() != '\n');
int main(){
char input[20] = {0};
printf("This is a string math program. Enter a string 9 characters or less"
" followed by an operater and finally another string 9 characters or less."
" There should be no spaces entered. To exit the program type exit.\n");
do{
printf("Input: ");
scanf("%s",input);
FLUSH
} while((input[0] != 'e') && (input[1] != 'x') && (input[2] != 'i') && (input[3] != 't'));
}
Let's talk about De Morgan's Law. This:
(input[0] != 'e') && (input[1] != 'x') && (input[2] != 'i') && (input[3] != 't')
is required to be true for your loop to continue. It is equivalent to this:
!(input[0] == 'e' || input[1] == 'x' || input[2] == 'i' || input[3] == 't')
So yes, your loop will stop when any character matches. Just use strcmp, but if you can't for some bizarre reason, just change the above logic.
char player_select(void){
char player = 'n';
while(player == 'n'){
printf("Select your player (X or O): ");
scanf("%c\n", &player);
if(player != 'X' && player != 'O'){
printf("Invalid input. Try again.\n");
player = 'n';
}
}
printf("Your character input is: %c\n", player);
exit(0);
return player;
}
I am getting some weird output here:
Select your player (X or O): X
Invalid input. Try again.
Select your player (X or O): i
Your character input is: X
Incorrect use of scanf()
// scanf("%c\n", &player);
scanf(" %c", &player);
The '\n' in "%c\n" does not do what you think. '\n' tells scanf() to consume white-space like '\n' and ' ' until non-white-space occurs. You input was not as described.
Since stdin is buffered, text by itself, will not typically get read until a '\n' follows.
It gets complicated to explain in detail why things failed. So briefly, use " %c" instead of "%c\n". Or better yet, use fgets().
buffer player[10];
fgets(ch, sizeof ch, stdin);
if(player[0] != 'X' && player[0] != 'O') { ...
I hope this will work for you.
I have removed the \n inside the scanf and i have added while(getchar()!='\n'); for emptying stdin.
char player_select(void){
char player = 'n';
while(player == 'n'){
printf("Select your player (X or O): ");
scanf("%c", &player);
if(player != 'X' && player != 'O'){
printf("Invalid input. Try again.\n");
player = 'n';
}
while(getchar()!='\n');
}
This is the output:
Select your player (X or O): A
Invalid input. Try again.
Select your player (X or O): X
Your character input is: X
Try:
if (scanf("%c\n", &player) == 1 && player != 'X' && player != 'O'){
printf("Invalid input. Try again.\n");
player = 'n';
}
Bring scanf into the if, removing from your above code, and check its return value == 1.
You can try removing the \n from scanf mask if this won't suffice.
I wanted to check whether input given is integer input or not. I did not wanted to store input in a string. After seeing several questions on stackoverflow and by hit and trial, I have created following code
while(scanf("%d%c",&num,&a) != 2 || a != '\n')
{
printf("Please enter an integer only : ");
if(a == '\n')
scanf("%c",&a);
else
{
while(a != '\n')
scanf("%c",&a);
}
}
It works but according to my understanding, the following should have also worked
while(scanf("%d%c",&num,&a) != 2 || a != '\n')
{
printf("Please enter an integer only : ");
while(a != '\n')
scanf("%c",&a);
}
Can someone please tell me why above did not worked ?? Also if someone has better solution please give it also.
Note :I am considering 12qwe also as an invalid input. I just want integers.
The problem with
while(scanf("%d%c",&num,&a) != 2 || a != '\n')
{
printf("Please enter an integer only : ");
while(a != '\n')
scanf("%c",&a);
}
is that if a happens to contain '\n' before the scan, and the scan fails, the inner while loop doesn't run at all. So
if the scan failed trying to parse an int from the input stream because the input was e.g. "ab c\n", the offending input remains in the input stream, the next scanf in the outer while loop control fails parsing an int again, a remains '\n', repeat.
if an input error occurred before reading a character from the stream into a, the scanf in the outer loop control fails because of a corrupted stream, repeat.
In the other version,
while(scanf("%d%c",&num,&a) != 2 || a != '\n')
{
printf("Please enter an integer only : ");
if(a == '\n')
scanf("%c",&a);
else
{
while(a != '\n')
scanf("%c",&a);
}
}
you make at least some progress as long as there is input to be read from the stream, since whatever a contains, you read at least one character from the input stream before attempting the next parsing of an int. It will also result in an infinite loop if the input stream is corrupted/closed/ends prematurely, e.g. if you redirect stdin from an empty file. You can have that loop also output multiple "Please enter an integer only : " messages by giving input like `"a\nb\nc\nd\n".
So you should check whether scanf encountered the end of the stream or some other read error before converting anything from the input, and abort in that case:
int reads;
while(((reads = scanf("%d%c", &num, &a)) != 2 && reads != EOF) || a != '\n')
{
printf("Please enter an integer only : ");
// read at least one character until the next newline
do {
reads = scanf("%c", &a);
}while(reads != EOF && a != '\n');
}
This is a wrong way to do. You can rather read the input using fgets() and then parse your string for integer ASCII range.
fgets(s, 1024, stdin)
for (i=0; s[i] ! = '\0';i++) {
if( s[i] <'0' && s[i] >'9')
// not an integer<br>
You can also use standard functions like isalnum, isalpha etc.
it works……
while(scanf("%d%c",&num,&a) != 2 || a != '\n')
{
printf("Please enter an integer only : ");
do{
scanf("%c",&a);
}while(a != '\n');
}