138

In C: I'm trying to get char from the user with scanf and when I run it the program don't wait for the user to type anything...

This is the code:

char ch;
printf("Enter one char");
scanf("%c", &ch);
printf("%c\n",ch);

Why is not working?

ROMANIA_engineer
  • 54,432
  • 29
  • 203
  • 199
Yuval
  • 1,721
  • 4
  • 16
  • 15
  • 2
    Just to clarify here, if the C program contains *only* the code above, it will work as expected. Potential problems like the one OP mentions only arise when it is used together with other I/O code, for reasons mentioned in P.P's answer. – forumulator Jan 04 '18 at 11:00

11 Answers11

302

The %c conversion specifier won't automatically skip any leading whitespace, so if there's a stray newline in the input stream (from a previous entry, for example) the scanf call will consume it immediately.

One way around the problem is to put a blank space before the conversion specifier in the format string:

scanf(" %c", &c);

The blank in the format string tells scanf to skip leading whitespace, and the first non-whitespace character will be read with the %c conversion specifier.

John Bode
  • 119,563
  • 19
  • 122
  • 198
36

First of all, avoid scanf(). Using it is not worth the pain.

See: Why does everyone say not to use scanf? What should I use instead?

Using a whitespace character in scanf() would ignore any number of whitespace characters left in the input stream, what if you need to read more inputs? Consider:

#include <stdio.h>

int main(void)
{
   char ch1, ch2;

   scanf("%c", &ch1);  /* Leaves the newline in the input */
   scanf(" %c", &ch2); /* The leading whitespace ensures it's the
                          previous newline is ignored */
   printf("ch1: %c, ch2: %c\n", ch1, ch2);

   /* All good so far */

   char ch3;
   scanf("%c", &ch3); /* Doesn't read input due to the same problem */
   printf("ch3: %c\n", ch3);

   return 0;
}

While the 3rd scanf() can be fixed in the same way using a leading whitespace, it's not always going to that simple as above. Another major problem is, scanf() will not discard any input in the input stream if it doesn't match the format. For example, if you input abc for an int such as: scanf("%d", &int_var); then abc will have to read and discarded. Consider:

#include <stdio.h>

int main(void)
{
    int i;

    while(1) {
        if (scanf("%d", &i) != 1) { /* Input "abc" */
            printf("Invalid input. Try again\n");
        } else {
            break;
        }
    }

    printf("Int read: %d\n", i);
    return 0;
}

Another common problem is mixing scanf() and fgets(). Consider:

#include <stdio.h>

int main(void)
{
    int age;
    char name[256];
    printf("Input your age:");
    scanf("%d", &age); /* Input 10 */
    printf("Input your full name [firstname lastname]");
    fgets(name, sizeof name, stdin); /* Doesn't read! */
    return 0;
}

The call to fgets() doesn't wait for input because the newline left by the previous scanf() call is read and fgets() terminates input reading when it encounters a newline.

There are many other similar problems associated with scanf(). That's why it's generally recommended to avoid it.

So, what's the alternative? Use fgets() function instead in the following fashion to read a single character:

#include <stdio.h>

int main(void)
{
    char line[256];
    char ch;

    if (fgets(line, sizeof line, stdin) == NULL) {
        printf("Input error.\n");
        exit(1);
    }

    ch = line[0];
    printf("Character read: %c\n", ch);
    return 0;
}

One detail to be aware of when using fgets() will read in the newline character if there's enough room in the inut buffer. If it's not desirable then you can remove it:

char line[256];

if (fgets(line, sizeof line, stdin) == NULL) {
    printf("Input error.\n");
    exit(1);
}

line[strcpsn(line, "\n")] = 0; /* removes the trailing newline, if present */
P.P
  • 117,907
  • 20
  • 175
  • 238
10

This works for me try it out

int main(){
char c;
scanf(" %c",&c);
printf("%c",c);
return 0;
}
Praveen samuel
  • 109
  • 1
  • 4
  • 2
    Now that's wild! Would you explain why the space in front of `%c` makes a difference? – Max Coplan Sep 10 '19 at 15:59
  • 2
    Solved: [check](https://gsamaras.wordpress.com/code/caution-when-reading-char-with-scanf-c/) [these](https://stackoverflow.com/questions/29502486/why-is-this-statement-printed-twice-in-while-loop/29502522#29502522) [out](https://stackoverflow.com/questions/23869502/in-c-programming-how-to-print-1-character/23869739#23869739) – Max Coplan Sep 10 '19 at 16:02
  • 3
    This doesn't seem to add any more information than the accepted answer from 2012. – domsson Jan 06 '20 at 18:05
5

Here is a similiar thing that I would like to share,

while you're working on Visual Studio you could get an error like:

'scanf': function or variable may be unsafe. Consider using scanf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS

To prevent this, you should write it in the following format

A single character may be read as follows:

char c;
scanf_s("%c", &c, 1);

When multiple characters for non-null terminated strings are read, integers are used as the width specification and the buffer size.

char c[4];
scanf_s("%4c", &c, _countof(c));
tripleee
  • 175,061
  • 34
  • 275
  • 318
Sanberk
  • 51
  • 1
  • 2
  • It seems like it doesn't work for me. Unhandled exception at 0x799AF2F6 (ucrtbased.dll) in Deitel0805.exe: An invalid parameter was passed to a function that considers invalid parameters fatal. #include #include int main() { char c; printf("%s", "Please enter a character:"); scanf_s("%с", &c, 1); return 0; } – Besuglov Sergey Jan 10 '20 at 09:22
3

neither fgets nor getchar works to solve the problem. the only workaround is keeping a space before %c while using scanf scanf(" %c",ch); // will only work

In the follwing fgets also not work..

char line[256];
char ch;
int i;

printf("Enter a num : ");
scanf("%d",&i);
printf("Enter a char : ");

if (fgets(line, sizeof line, stdin) == NULL) {
    printf("Input error.\n");
    exit(1);
}

ch = line[0];
printf("Character read: %c\n", ch);
Kaushik
  • 95
  • 1
  • 8
1

try using getchar(); instead

syntax:

void main() {
    char ch;
    ch = getchar();
}
0

The only code that worked for me is:

scanf(" %c",&c);

I was having the same problem, and only with single characters. After an hour of random testing I can not report an issue yet. One would think that C would have by now a bullet-proof function to retrieve single characters from the keyboard, and not an array of possible hackarounds... Just saying...

tripleee
  • 175,061
  • 34
  • 275
  • 318
-1

Before the scanf put fflush(stdin); to clear buffer.

mpromonet
  • 11,326
  • 43
  • 62
  • 91
-2

Use string instead of char like

char c[10];
scanf ("%s", c);

I belive it works nice.

ForceBru
  • 43,482
  • 10
  • 63
  • 98
POTATO
  • 1
  • 6
    This doesn't answer the question because the OP wanted to `scanf` a _single character_, not a series of them. – ForceBru Jun 22 '16 at 16:59
-3

Provides a space before %c conversion specifier so that compiler will ignore white spaces. The program may be written as below:

#include <stdio.h>
#include <stdlib.h>
int main()
{
    char ch;
    printf("Enter one char");
    scanf(" %c", &ch); /*Space is given before %c*/
    printf("%c\n",ch);
return 0;
}
-4

You have to use a valid variable. ch is not a valid variable for this program. Use char Aaa;

char aaa;
scanf("%c",&Aaa);

Tested and it works.

Jee Mok
  • 6,157
  • 8
  • 47
  • 80
  • 2
    "ch is not a valid variable for this program" Except it is? It's the first line of code in the given example. – Hoppeduppeanut Dec 17 '18 at 01:04
  • This answer is very useful. I did not know that C compiler is not case-sensitive. For example: `THIS_ANSWER_IS_BAD` can be detected by C compiler as `this_answer_is_BAD`. Oh, it should be `mychar`, not `ch`, tested it and it works. – FaranAiki Sep 27 '21 at 06:05