You cannot use scanf with the %d conversion format specifier to read a character.
Although it is possible to solve this problem with scanf, I instead recommend that you read an entire line of input as a string with the function fgets. If you determine that the user did not enter "q", then you can attempt to convert that string to an integer, and then check whether this integer is in the range 1 to 9.
Here is an example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
//forward declaration
void get_line_from_user( char *buffer, int buffer_size );
int main( void )
{
char board[9] = {
'C', ' ', 'U',
'U', ' ', ' ',
'C', 'U', ' '
};
long choice;
//repeat until input is valid
for (;;) //infinite loop, equivalent to while(1)
{
char line[200], *p;
printf( "Enter a square (1-9) or \"q\" to quit: " );
get_line_from_user( line, sizeof line );
//determine whether user wants to quit
if ( strcmp( line, "q" ) == 0 )
{
printf( "Quitting program!\n" );
exit( EXIT_SUCCESS );
}
//user did not want to quit, so attempt to convert input to
//an integer
choice = strtol( line, &p, 10 );
if ( p == line )
{
printf( "Unable to convert input to an integer!\n" );
continue;
}
//verify that the remainder of the line does not contain any
//non-whitespace characters, so that input such as "6abc"
//gets rejected
for ( ; *p != '\0'; p++ )
{
if ( !isspace( (unsigned char)*p ) )
{
printf( "Unexpected character encountered!\n" );
//we cannot use "continue" here, because this would
//continue the innermost loop, but we want to continue
//the outer loop
goto continue_outer_loop;
}
}
//verify that input is in the desired range
if ( choice < 1 || choice > 9 )
{
printf( "Please enter a number between 1 and 9!\n" );
continue;
}
//verify that square is not already occupied
if ( board[choice-1] == 'C' || board[choice-1] == 'U' )
{
printf( "Board square is already occupied!\n" );
continue;
}
//input is ok, so we can break out of the infinite loop
break;
continue_outer_loop:
continue;
}
printf( "Input is valid!\n" );
printf( "You entered: %ld\n", choice );
}
//This function will read exactly one line of input from the
//user. If the line is too long to fit in the buffer, then the
//function will automatically reprompt the user for input. On
//failure, the function will never return, but will print an
//error message and call "exit" instead.
void get_line_from_user( char *buffer, int buffer_size )
{
char *p;
//attempt to read one line of input
if ( fgets( buffer, buffer_size, stdin ) == NULL )
{
printf( "Error reading from input\n" );
exit( EXIT_FAILURE );
}
//attempt to find newline character
p = strchr( buffer, '\n' );
//make sure that entire line was read in (i.e. that
//the buffer was not too small to store the entire line)
if ( p == NULL )
{
//attempt to read one more character
int c = getchar();
//a missing newline character is ok if the next
//character is a newline character or if we have
//reached end-of-file (for example if the input is
//being piped from a file or if the user enters
//end-of-file in the terminal itself)
if ( c != '\n' && !feof(stdin) )
{
printf( "Input was too long to fit in buffer!\n" );
//discard remainder of line
while ( c != EOF && c != '\n' )
{
c = getchar();
}
}
}
else
{
//remove newline character by overwriting it with
//null character
*p = '\0';
}
}
This program has the following behavior:
Enter a square (1-9) or "q" to quit: test
Unable to convert input to an integer!
Enter a square (1-9) or "q" to quit: 6abc
Unexpected character encountered!
Enter a square (1-9) or "q" to quit: -5
Please enter a number between 1 and 9!
Enter a square (1-9) or "q" to quit: 0
Please enter a number between 1 and 9!
Enter a square (1-9) or "q" to quit: 10
Please enter a number between 1 and 9!
Enter a square (1-9) or "q" to quit: 1
Board square is already occupied!
Enter a square (1-9) or "q" to quit: 4
Board square is already occupied!
Enter a square (1-9) or "q" to quit: 5
Input is valid!
You entered: 5