Caution when reading char with scanf (C)

Quite often I see the following problem in people’s code ( as a matter of fact, aliens don’t do that mistake :p ), when trying to input a character again and again with scanf. Usually, this happens inside a loop, but let’s see a sample code without loop that exposes the problem.

badCscanf.c

#include <stdio.h>

int main(void)
{
    char c;
    
    printf("Input No.1\n");
    scanf("%c", &c);
    printf("c = %c\n", c);
    
    printf("Input No.2\n");
    scanf("%c", &c);
    printf("c = %c\n", c);
    
    printf("Input No.3\n");
    scanf("%c", &c);
    printf("c = %c\n", c);
    
    return 0;
}

which gives output

Input No.1
s
c = s
Input No.2
c = 

Input No.3
a
c = a

RUN SUCCESSFUL (total time: 5s)

As you see, the input No.2 was skipped. Well not really, not at all. But the intention of the programmer is usually to get three characters from the user, which is what is happening, isn’t? Let me explain. Think what you do, when you input. First prompt message arrives, you type s and then what? You hit enter! Enter is a character!

As a result, first scanf will read the s. Second scanf will read the enter! That’s why, the second printf of the value of c leaves just a newline after “c=”. Then the third scanf waits for a key press. You input a and then you hit enter. a is been assigned to variable c and enter remains in the stdin buffer ready to be read by the next scanf. If we had a fourth scanf, then it would read the enter.

However, many would think now that, “Wait a minute… I do this while reading numbers, with %d for example and I had no problem”. Correct! Why? Because %d automatically eats whitespaces and special characters. Logical, isn’t it? Whitespaces and special characters are characters, not numbers! However, %c has to interpret whitespaces and special characters as inputs, because %c reads characters😉 . Luckily enough, the “fix to scanf to do what you intend it to do” is to leave a space before %c. That way you say to scanf to automatically eat whitespaces and special characters, like enter! So, just change scanf(“%c”, &c); to scanf(” %c”, &c); and you will be just fine. See by yourself in the code bellow:

goodCscanf.c

#include <stdio.h>

int main(void)
{
    char c;
    /* FIX: Leave a space before %c */
    
    printf("Input No.1\n");
    scanf(" %c", &c);
    printf("c = %c\n", c);
    
    printf("Input No.2\n");
    scanf(" %c", &c);
    printf("c = %c\n", c);
    
    printf("Input No.3\n");
    scanf(" %c", &c);
    printf("c = %c\n", c);
    
    return 0;
}

which outputs, what you expect:

Input No.1
s
c = s
Input No.2
a
c = a
Input No.3
m
c = m

RUN SUCCESSFUL (total time: 4s)

I suggest taking a look at my relevant answer in Stackoverflow too.

This code was developed by me, G. Samaras. There is also a nice answer in this Stackoverflow question.

Have questions about this code? Comments? Did you find a bug? Let me know!😀
Page created by G. (George) Samaras (DIT)

93 thoughts on “Caution when reading char with scanf (C)

  1. Pingback: Program come out with out proper execution

  2. Pingback: trouble with one of my if conditions

  3. Pingback: help with while loop

  4. Even though I knew you had to enter space before %c in scanf, I didn’t quite well understood why. This cleared up some things.

    • Thank you. Didn’t we expect that to happen? “ggg” is a string, not a character. We have said to scanf() to read a character, i.e. the first letter of out string, which is ‘g’. So, the other two ‘g’ will remain in the input buffer, thus getting read by the next two scanf() functions. Do you agree?🙂

    • You are welcome. Isn’t the explanation I have provided enough? As I say there, “..that way you say to scanf to automatically eat whitespaces and special characters, like enter!..”. The reason is that the function is built that way, from the people that wrote the standard header.

  5. So I’m trying to input numbers into this %c and have an error message using !isalpha() = print “not alphabetic”, but when I input something like 10 into %c, it thinks I’m trying to input 1 and 0 so it skips the next statement just like gg would do or when you press enter without the space in front of the %c. Is there any way for me to get around this?

  6. Sorry dude, there is an mistake in your explanation. When you read with scanf(” %c”,&c); you have the problem that the first character you enter may are not correct. Only in the further steps your are right to do so. I think there is a better solution to solve this problem by using a buffer for the enter key such like this:

    char c;
    char buf;

    scanf(“%c%c”,&c,&buf);

    And at the end of the program you should free the buffer
    free(buf);

    Hope someone can need it

    • Thanks for the comment, but I can not see how this is going to work. I mean, ‘buf’ is not even dynamically allocated. If you want, you can post a complicable example.

  7. I was searching for the solution for many days ,and i understood it in just a min,
    i have a question.
    if we enter sss in place of s,
    s will be used and remaining will be stored in buffer,
    is there any thing to delete all the things from this buffer before we can take next input???

    • Thanks Tarun, that’s really great!🙂
      Yes, since we are reading a char at a time, since we use %c.

      So, you can either use %s, in order to read the whole input (i.e. sss) and put it in an array of characters. If the array has size equal to 10, then it will have the letter s in indices 0, 1 and 2 and the null terminator of the strings in index 3. If you want to take into account only the first s and just forget about the other two, just assign to the cell of the array at index 1 a null terminator.

      Another solution would be to follow the code I have provided above (without using an array) and use fflush (see the ref here http://www.cplusplus.com/reference/cstdio/fflush/).

      Hope that helps,
      Georgios

  8. Thanks a ton, after reading your article I remember hearing my professor mention this once. Completely forgot about it since its never been an issue before. Only need to forget a few more times before its second nature to always code with the “safety space”.

  9. one of the best article
    I have a question. I am facing the same problem in putchar() function.
    That is the Next putchar() function captures the previous enter button…😦 .. How to avoid that?

    • Asad thanks. I am not sure of the problem you are facing. I would suggest you to post a minimal example as a question in stackoverflow.com. Then make sure you post back here with the link of that question so I can take a look into it!

      • Sorry. I am talking about getchar() function. Same problem for this program. I want to take three charactars by getchar() but the second getchar() function is skipped alwasy
        #include
        main()
        {
        int x = getchar();
        int y = getchar();
        int z = getchar();
        printf(“x=%c and y=%c and z=%c”,x,y,z);
        }

  10. Thanks a lot you saved my life. And also I discovered that you can use %1s when reading a single character from the user. It works. You dont need to put space or anything just a scanf(“%1s”, &variable_name);

  11. Today i face this problem even since 2011, I didn’t thought that i would get this type of error. But i am so lucky to find this solution very soon.many tanx bro

  12. thanx a lot sir plz share some more tips and traps of c language
    sometimes these things are missed in everyday programming.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s