Educational Blog

How to Use scanf in C

Learn how scanf reads input in C, with format specifiers, pointers, safety tips, and common mistakes.

If you are learning C, scanf is one of the first input functions you will meet. It reads formatted data from standard input, which usually means the keyboard. That sounds simple, but scanf has enough sharp edges that it deserves a careful explanation.

The basic idea is straightforward: you give scanf a format string that tells it what to read, and then you pass it the addresses of variables where it should store the results. If you know what the format specifiers mean, how pointers work, and how to check the return value, scanf becomes useful instead of mysterious.

What scanf Does

scanf lives in <stdio.h> and has this general shape:

int scanf(const char *format, ...);

It reads input according to the format string and writes values into the variables whose addresses you provide. The function returns the number of input items successfully matched and assigned. If input fails before any conversion happens, it can return EOF.

That return value matters. It is how you tell the difference between valid input, partial input, and a real input failure.

A First Example

Here is the simplest useful pattern:

int main(void) {
    int age;

    printf("Enter your age: ");
    if (scanf("%d", &age) == 1) {
        printf("You entered %d
", age);
    } else {
        printf("Invalid input
");
    }

    return 0;
}

There are three important details here:

  • %d tells scanf to parse an integer.
  • &age passes the address of age, not the value itself.
  • scanf("%d", &age) == 1 checks that exactly one value was assigned.

If you forget the & for a numeric variable, scanf will treat the value inside the variable as an address. That is undefined behavior and often causes a crash.

Common Format Specifiers

The most common format specifiers cover the data types you use every day.

SpecifierReadsExample
%dsigned integer42
%uunsigned integer99
%ffloat3.14
%lfdouble2.71828
%csingle characterA
%sword/string without spaceshello
%xhexadecimal integerff

A few notes help avoid confusion:

  • %f is for float when used with scanf, but %lf is for double.
  • %s stops at whitespace, so it reads one word, not an entire sentence.
  • %c reads the next character exactly as it appears, including spaces and newlines unless you add whitespace in the format string.

Why Addresses Matter

scanf needs a place to store the result. In C, that means you pass a pointer to the target variable.

int n;
scanf("%d", &n);

&n means “address of n”. For arrays and strings, the rules are slightly different because the array name often decays into a pointer to its first element.

char name[50];
scanf("%49s", name);

Notice that name is passed without &. That works because name already refers to the array buffer. The width 49 limits how many characters scanf stores, leaving room for the null terminator.

Reading Strings Safely

scanf("%s", name) is common, but it has a limitation: it stops at the first whitespace. That means it is fine for a single word but not for full names or sentences.

For example:

char first[30];
scanf("%29s", first);

This reads Ada, but from Ada Lovelace it only captures Ada.

If you need spaces, you usually want fgets instead of scanf. scanf is still useful for token-style input, command parsing, and quick scripts, but it is not the best general-purpose text reader.

Handling Whitespace Correctly

Whitespace is the hidden source of a lot of scanf bugs.

Some format specifiers skip leading whitespace automatically. Others do not.

  • %d, %f, %s skip leading whitespace before reading.
  • %c does not skip whitespace unless you tell it to.

That means this code can surprise people:

char ch;
scanf("%c", &ch);

If there is a leftover newline in the input buffer, scanf may read that newline instead of the character you expected.

A common fix is to include a leading space in the format string:

scanf(" %c", &ch);

That space tells scanf to skip any leading whitespace before reading the character.

Checking Return Values

Never assume the input was valid. Always check what scanf returned.

int a, b;
if (scanf("%d %d", &a, &b) == 2) {
    printf("Sum: %d
", a + b);
} else {
    printf("Please enter two integers
");
}

This pattern is better than reading values first and checking later, because it prevents garbage data from flowing into the rest of the program.

A useful mental model is this: scanf is both a parser and a validator. If the input does not match the expected format, the conversion stops.

Width Limits and Buffer Safety

When reading text into a character array, always set a width limit.

char city[20];
scanf("%19s", city);

Without the width, a long input word can overflow the buffer. That is a classic C security bug.

The width value should always be one less than the array size so there is room for the terminating null byte.

For numeric inputs, width is usually not the main issue. The bigger concern is whether the input text can be parsed into the expected type.

A Practical Pattern for Interactive Input

Here is a small example that combines several good habits.

#include <stdio.h>

int main(void) {
    int year;
    char grade;
    char word[16];

    printf("Enter a year: ");
    if (scanf("%d", &year) != 1) {
        printf("Invalid year
");
        return 1;
    }

    printf("Enter a grade letter: ");
    if (scanf(" %c", &grade) != 1) {
        printf("Invalid grade
");
        return 1;
    }

    printf("Enter one short word: ");
    if (scanf("%15s", word) != 1) {
        printf("Invalid word
");
        return 1;
    }

    printf("Year: %d, Grade: %c, Word: %s
", year, grade, word);
    return 0;
}

This example shows three different input styles:

  • %d for an integer
  • %c for a character with whitespace skipped first
  • %15s for a bounded short string

If you treat each input as an opportunity for failure instead of assuming success, your C programs become much more reliable.

When scanf Is a Good Choice

scanf is a good tool when:

  • You know the input structure ahead of time.
  • You want to read simple typed values quickly.
  • You are parsing compact data such as numbers and tokens.
  • You are writing beginner exercises or small command-line programs.

It is less ideal when:

  • You need to read full lines with spaces.
  • You need robust error recovery after malformed input.
  • You are building interactive programs with flexible text handling.
  • You want easier control over leftover newline characters.

Common Mistakes to Avoid

Here is a compact checklist that covers the biggest pitfalls.

MistakeProblemBetter approach
Forgetting & for numeric variablesUndefined behaviorPass the variable address
Using %s without widthBuffer overflow riskUse a field width like %19s
Expecting %s to read spacesOnly reads one wordUse fgets for lines
Using %c after numeric input without careReads leftover whitespaceUse " %c"
Ignoring the return valueInvalid data slips throughCheck the number of assigned items

That list captures the problems you will meet most often in real code and in beginner assignments.

Mental Model for Success

The easiest way to think about scanf is this:

  1. The format string describes the shape of the input.
  2. scanf tries to match that shape from left to right.
  3. Successful conversions are stored through pointers.
  4. If the input no longer matches, the process stops.
  5. The return value tells you how far it got.

Once you internalize that sequence, debugging becomes much easier. If scanf seems to skip input, the issue is often whitespace or a mismatched format specifier. If it seems to ?fail randomly,? the issue is often unchecked return values.

A Better Way to Learn It

If you want to really understand scanf, test it with small experiments:

  • Try %d with valid and invalid numbers.
  • Try %c after reading an integer.
  • Try %s with a single word and then with a sentence.
  • Try different width limits on a small array.

That kind of hands-on testing shows exactly how the function behaves, which is more useful than memorizing rules in isolation.

Final Takeaway

Use scanf when you want a concise way to read structured input, but treat it with respect. Always pass addresses, always limit string input, and always check the return value. If you do those three things consistently, scanf becomes a practical tool instead of a source of mysterious bugs.

Written by

c-double.com Editorial Team

Editorial team

c-double.com publishes practical how-to guides and educational articles with clear steps and useful context.