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.
Related
I'm having a problem with multiple characters while using a while loop. I'm writing a code that would direct the user to a new function based on the input of either "y" or "n". When I scanf for one character it works fine; however, when the user types in multiple characters the while loop repeats.
#include <stdio.h>
int main()
{
char x;
printf("type in letter n or y\n");
scanf("%c", &x);
while (x!= 'Y' && x!='N' && x!= 'n' && x!='y')
{
printf("Invalid, please type Y/N to continue: \n");
scanf(" %c", &x);
}
if (x== 'Y' || x == 'y')
{
printf("y works");
}
if (x =='N' || x =='n')
{
printf("n works");
}
}
For example, if I type in hoyp, it would say "Invalid, ..." 2 times and then the "y works" would be written on the third line. How can the code be changed so that the invalid would only be said once, and the user must input again to allow the program to continue?
This is how scanf behaves. It keeps reading in all the characters you've entered. You can accept a string as input first using fgets and extract and check only its first character. fgets allows you to specify the exact number of characters to be read. I have first declared a char array of size 4096. This will work when the input is up to 4095 characters. You can adjust the size as per your needs.
#include <stdio.h>
int main()
{
char x, buffer[4096];
printf("type in letter n or y\n");
fgets(buffer, 4096, stdin);
x = buffer[0];
while (x!= 'Y' && x!='N' && x!= 'n' && x!='y')
{
printf("Invalid, please type Y/N to continue: \n");
fgets(buffer, 4096, stdin);
x = buffer[0];
}
if (x== 'Y' || x == 'y')
{
printf("y works");
}
if (x =='N' || x =='n')
{
printf("n works");
}
}
Here is my approach to the problem:
I have used fgets() instead of scanf(). See why
here.
I have used the suggestion by users jamesdlin and M.M in this question to solve the repeated printing issue when the input is more than one character or if the input is empty. I encourage you to read the whole thread to know more about this issue.
(Optional) Used some extra headers for better code readability in the loop conditions. I think the fgets() could be used in the condition of the while() but I got used to the pattern I have written below.
Edit: added a condition to reject inputs with length > 1. Previously, inputs that starts with 'y' or 'n' will be accepted (and are interpreted as 'y' or 'n' respectively) regardless of their length.
#include <stdio.h>
#include <stdbool.h>
#include <ctype.h>
void clearInput();
int main()
{
// allocate space for 'Y' or 'N' + '\n' + the terminator '\0'
// only single inputs will be accepted
char _inputbuff[3];
char choice;
bool isValidInput = false;
while(!isValidInput) {
printf("Please enter your input[y/n]: ");
// use fgets() instead of scanf
// this only stores the first 2 characters of the input
fgets(_inputbuff, sizeof(_inputbuff), stdin);
// don't accept empty input to prevent hanging input
if(_inputbuff[0] == '\n') {
printf("Empty input\n");
// go back to the top of the loop
continue;
}
// input is non-empty
// if the allocated space for the newline does not
// contain '\n', reject the input
if(_inputbuff[1] != '\n') {
printf("Input is more than one char.\n");
clearInput();
continue;
}
choice = _inputbuff[0];
// printf("The input is %c\n", choice);
// convert the input to uppercase for a 'cleaner' code
// during input validation
choice = toupper(choice);
// the input is not 'Y' or 'N'
if(choice != 'Y' && choice != 'N') {
printf("Please choose from Y or N only.\n");
// go back to the top of the loop
continue;
}
// the input is 'Y' or 'N', terminate the loop
isValidInput = true;
}
// conditions for 'Y' or 'N'
if(choice == 'Y') {
printf("The input is Yes.\n");
return 0;
}
if(choice == 'N') {
printf("The input is No.\n");
return 0;
}
}
void clearInput() {
int _clear;
// clear input stream to prevent repeated printing of invalid inputs
while ((_clear = getchar()) != '\n' && _clear != EOF ) { }
}
(This is my first time answering a question and it has been a while since I have used C so feel free to give suggestions/corrections regarding my answer. Thanks!)
I was trying a simple C code and found out strange error. Here is the code. As soon as the first
scanf()
function is encountered, the compiler automatically skips it and move ahead. Why is that so?
#include<stdio.h>
#include<stdlib.h>
void main()
{
float base_cost, refresh_cost;
int ticket;
char coupon, refresh, circle;
printf("Enter number of tickets: ");
scanf("%d", &ticket);
if(ticket<5 ||ticket>40)
{
printf("Minimum of 5 and Maximum of 40 Tickets");
exit(0);
}
printf("Do you want refreshment?(Y/N): "); //Here compiler skips
scanf("%c", &refresh);
printf("Do you have coupon?(Y/N): ");
scanf("%c", &coupon);
printf("Enter circle: ");
scanf("%c", &circle);
if(circle!='k'||circle!='q' || circle!='K' || circle!='Q')
{
printf("Invalid Input");
exit(0);
}
else if(circle == 'k' || circle == 'K')
{
if(ticket > 20)
base_cost = (ticket*75.00) - 0.1*(ticket*75.00);
else if(coupon == 'y' || coupon == 'Y')
base_cost = (ticket*75.00) - 0.02*(ticket*75.00);
else
base_cost = ticket*75.00;
}
else if (circle == 'q' || circle == 'Q')
{
if(ticket > 20)
base_cost = (ticket*150.00) - 0.1*(ticket*150.00);
else if(coupon == 'y' || coupon == 'Y')
base_cost = (ticket*150.00) - 0.02*(ticket*150.00);
else
base_cost = ticket*150.00;
}
if (refresh == 'y' || refresh == 'Y')
{
refresh_cost = ticket * 50.00;
}
else
refresh_cost = 0.00;
printf("\nTotal cost: %0.2f", base_cost + refresh_cost);
}
I used the variable refresh in order to allow the user to have a choice, whether or not to insert elements i.e. Y or N.
Also, it looks like other scanf function with char as input are also been skipped.
But the compiler basically skips the third scanf function, the one that accepts the char, along with the while loop.
Unlike %d and %s, the %c conversion specifier does not skip over leading whitespace. What's happening is you have a stray newline in the input stream after the first scanf call to get the ticket number; that newline is read by the next scanf call and assigned to refresh.
To avoid this, put a blank space in front of the %c specifier:
scanf( " %c", &refresh );
That blank space tells scanf to skip over any leading whitespace. Do this for every %c that is meant to read a non-whitespace cparacter.
I need to write a program in C that let's the user choose to draw a rectangle square or print the board he made but everytime after the first input of a shape the program acts as if he entered an invalid character.
printf("please make you decision R-rectangle, S-square, E-end\n");
scanf("%c", &decision);
do
{
if (decision == 'R') {
printf("you chose rectangle! please enter the X start position, Y start position, hieght and width\n");
scanf("%d %d %d %d", &rectMat[0][rectCounter], &rectMat[1][rectCounter], &rectMat[2][rectCounter], &rectMat[3][rectCounter]);
if (rectCounter + 1 < MAX_RECT)
{
if (checkRECT(rectMat[0][rectCounter], rectMat[1][rectCounter], rectMat[2][rectCounter], rectMat[3][rectCounter], areaMat) == 1)
{
drawRECT(rectMat[0][rectCounter], rectMat[1][rectCounter], rectMat[2][rectCounter], rectMat[3][rectCounter], areaMat);
rectCounter++;
}
else
{
printf("we couldn't fit you rectangle\n");
}
}
else
{
printf("you have too many rectangles\n");
}
}
if (decision == 'S')
{
printf("you chose square! please enter the X start position, Y start position and size of the side\n");
scanf("%d %d %d", &sqrMat[0][rectCounter], &sqrMat[1][rectCounter], &sqrMat[2][rectCounter]);
if (sqrCounter<MAX_SQR)
{
if (checkSQR(sqrMat[0][rectCounter], sqrMat[1][rectCounter], sqrMat[2][rectCounter],areaMat)==1)
{
drawSQR(sqrMat[0][rectCounter], sqrMat[1][rectCounter], sqrMat[2][rectCounter], areaMat);
sqrCounter++;
}
else
{
printf("we couldn't fit your square\n");
}
}
else
{
printf("you have too many sqaures\n");
}
}
if (decision == 'P')
{
printArea(areaMat);
}
if (decision != 'E'&& decision != 'P'&& decision != 'S'&& decision != 'R')
{
printf("invalid entry\n");
}
printf("please make you decision R-rectangle, S-square, E-end\n");
scanf("%c", &decision);
} while (decision != 'E');
When you read characters using the "%c" format, it will read the next character in the input buffer, it will not skip any white-space. And when using scanf to read anything, the newline you enter to send the input to the program will also be sent, and added as a white-space character after the end of your input. Most formats do skip leading white-space (like for example the "%d" format), but the "%c" and "%[" formats do not.
When reading character it's almost always advisable to skip leading white-space, which is done by adding a space before the format, like e.g.
scanf(" %c", &decision);
// ^
// |
// Note space here
Also note that there is a difference between upper- and lower-case letters. 'R' != 'r'. Either check for both upper- and lower-case letters, or use toupper (or tolower) to convert.
you better off using getc() instad of scanf() since you're expecting a single char anyway
When setting a character value to specified user input using the getchar() method, the user could potentially decide to not input anything, but still hit the enter key. Is there a way to check to see if the character value is "\n"?
// for example:
printf("input y/n\n");
char inp;
// the user hits enter before entering any value
inp = getchar();
getchar();
while (inp != 'y' && inp != 'n') {
inp = getchar();
getchar();
}
if (inp == 'y') {
printf("+\n");
} else {
printf("-\n");
}
example input/output
case 1
'enter'
yy results in: +
case 2
'enter'
y
y
yy results in: +
case 3
'enter'
y
'enter'
y results in: +
Would anyone be willing to explain these cases? As someone who is new to c, but relatively experienced in java, I'm curious to understand the uses and logic of getchar().
Please remove the second getchar()
// the user hits enter before entering any value
inp = getchar();
//getchar(); // this getchar() is not needed
also in
while (inp != 'y' && inp != 'n') {
inp = getchar();
// getchar(); // this getchar() is not needed
}
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.