printf & scanf

You've already been using printf to get values out onto the screen. Its counterpart, scanf, reads values back in from whoever is typing at the terminal. Between the two of them, you get a full loop: ask the user something, read their answer, do something with it.

Format specifiers, precisely

printf doesn't know the type of anything you pass it — it just reads the format string left to right and pulls values off the argument list to match each % specifier. Get the specifier wrong for the type and printf will misread the bytes; it has no way to catch the mistake for you.

</> formatting.c
#include <stdio.h>

int main(void) {
    double pi = 3.14159265;

    printf("Default: %f\n", pi);
    printf("Two decimals: %.2f\n", pi);
    printf("Width 10: %10.2f\n", pi);
    return 0;
}
Output
Default: 3.141593
Two decimals: 3.14
Width 10:       3.14

Left unspecified, %f always prints six digits after the decimal point, rounding as needed — that's why 3.14159265 becomes 3.141593. Adding .2 before the f caps it at two decimal places. The number before the dot, like the 10 in %10.2f, sets a minimum field width and pads with spaces on the left, which is handy for lining up columns of numbers.

Reading input with scanf

scanf needs to know two things: what type of value to expect, and where in memory to put it once it's read. That second part is why you'll see an & in front of most variables passed to scanf — it's the "address-of" operator, and it hands scanf the actual memory location of your variable so it can write directly into it, rather than into some copy that vanishes when the function returns. This will make a lot more sense after the pointers lesson; for now, just know the & is required for ordinary variables.

</> greet.c
#include <stdio.h>

int main(void) {
    int age;

    printf("Enter your age: ");
    scanf("%d", &age);
    printf("You are %d years old.\n", age);

    return 0;
}
Output (assuming the user types 25 and presses Enter)
Enter your age: 25
You are 25 years old.

The 25 in that output is the terminal echoing back what was typed, not something the program printed — it appears right after the prompt because scanf waits there until Enter is pressed, then reads the number and hands control back to your code.

A gotcha: %f vs %lf in scanf

This one catches almost everyone at least once. In printf, both float and double use %f — arguments smaller than an int get automatically widened when passed to a variadic function like printf, so a float shows up as a double by the time printf sees it. But scanf receives an address, not a widened copy, so it needs to know exactly how many bytes to write: %f for a float variable, %lf for a double one.

</> payday.c
#include <stdio.h>

int main(void) {
    int hours;
    double rate;

    printf("Hours worked: ");
    scanf("%d", &hours);
    printf("Hourly rate: ");
    scanf("%lf", &rate);

    printf("You earned $%.2f\n", hours * rate);
    return 0;
}
Output (assuming 8 and 15.5 are entered)
Hours worked: 8
Hourly rate: 15.5
You earned $124.00
Note: using %f where scanf expects %lf is undefined behavior — it will sometimes appear to work and sometimes silently corrupt nearby memory, which makes it a nasty bug to track down. When in doubt, remember: double variables need %lf in scanf, even though they use plain %f in printf.