FirstHack Learn
Log in Sign up free

Input and Output in C

10 min read · 39 views

Input and Output in C

C has no built-in print statement. printf and scanf are ordinary functions living in the standard library, which is exactly why you must write #include <stdio.h> to use them. That header does not contain the functions themselves. It contains their declarations, telling the compiler what arguments they expect and what they return. The actual machine code is joined in later by the linker.

Understanding that these are just functions explains most of their odd behaviour.

How printf actually works

printf takes a format string followed by zero or more values. It walks the format string character by character, copying ordinary characters straight to the screen. When it hits a %, it stops copying, reads the specifier that follows, and pulls the next argument off the list to format it.

That last part is important: printf does not check that you gave it the right type. It trusts the format string completely. If the string says %d and you pass a double, printf will read those bytes as if they were an integer and print nonsense.

C
#include <stdio.h>

int main(void)
{
    int    roll   = 17;
    float  marks  = 82.5f;
    char   grade  = 'A';
    double ratio  = 0.6666666666;

    printf("Roll   : %d\n", roll);
    printf("Marks  : %f\n", marks);
    printf("Marks  : %.1f\n", marks);
    printf("Grade  : %c\n", grade);
    printf("Ratio  : %.4lf\n", ratio);
    printf("Name   : %s\n", "Ananya");
    printf("Hex    : %x   Octal: %o\n", 255, 255);

    return 0;
}

The specifiers you will actually use

Specifier Prints Example output
%d Signed integer 42
%u Unsigned integer 42
%f float or double 3.140000
%.2f Rounded to 2 decimals 3.14
%c Single character A
%s String, i.e. char array Ananya
%x Integer in hexadecimal ff
%o Integer in octal 377
%zu Result of sizeof 4
%% A literal percent sign %

Two notes that clear up common confusion. In printf, %f handles both float and double, because a float argument is automatically widened to double when passed. In scanf this is not true and the distinction between %f and %lf genuinely matters. Second, %.2f rounds for display; it does not change the stored value.

Width and alignment

A number between the % and the specifier sets a minimum field width, which is how you line up columns in a table.

C
#include <stdio.h>

int main(void)
{
    printf("%-10s %8s %6s\n", "Subject", "Marks", "Grade");
    printf("%-10s %8d %6c\n", "Maths",   91, 'A');
    printf("%-10s %8d %6c\n", "Physics", 78, 'B');
    printf("%-10s %8d %6c\n", "Chem",    65, 'C');

    printf("\n%08.3f\n", 3.14159);

    return 0;
}

%-10s left-aligns a string in a field ten characters wide. Without the minus sign the value is right-aligned, which is what you usually want for numbers. %08.3f pads with zeros to a total width of eight, with three decimal places.

Escape sequences

Some characters cannot be typed directly inside a string literal, so C uses a backslash to escape them.

Sequence Meaning
\n Newline
\t Horizontal tab
\\ A single backslash
\" A double quote inside a string
\' A single quote inside a char constant
\0 The null character, value zero
\r Carriage return

\n matters more than it looks. Output is usually line buffered, meaning the text sits in a buffer until a newline arrives. If your program prints without a newline and then crashes, that text may never appear, making the crash look like it happened earlier than it did.

💡Windows paths need doubled backslashes

printf("C:\new\table\n"); does not print a path. \n and \t are escape sequences, so you get a newline and a tab. Write printf("C:\\new\\table\\n"); when you want literal backslashes.

Reading input with scanf

scanf is the mirror image of printf, and it is where most beginner frustration lives. Here is the basic shape.

TEXT
#include <stdio.h>

int main(void)
{
    int age;
    printf("Enter your age: ");
    scanf("%d", &age);
    printf("You are %d\n", age);
    return 0;
}

The ampersand in &age is not decoration. C passes arguments by value, so scanf receives copies. A copy is useless for storing a result. &age means "the address of age", which gives scanf somewhere real to write. Forgetting the ampersand is the single most common C mistake in first-year labs, and it typically compiles with only a warning before crashing at run time.

The one exception: an array name already behaves as an address, so reading a string uses no ampersand.

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

The 49 caps how many characters are read, leaving room for the terminating null. Plain %s with no limit will happily write past the end of your array and corrupt memory. Also note that %s stops at the first space, so "Adnan Hassan" reads as "Adnan" and the rest stays waiting in the buffer.

The scanf traps

Trap 1: leftover newline before %c. After scanf("%d", &n); the Enter key you pressed is still sitting in the input buffer. A following scanf("%c", &ch); immediately consumes that newline instead of waiting for you. The fix is a space in the format string, which tells scanf to skip whitespace first.

TEXT
scanf("%d", &n);
scanf(" %c", &ch);

Trap 2: %f versus %lf. In scanf you must use %f for a float and %lf for a double. Getting this wrong writes the wrong number of bytes into your variable and corrupts whatever sits next to it.

Trap 3: ignoring the return value. scanf returns how many items it successfully read. If the user types "hello" when you asked for %d, nothing is read, your variable keeps its old value, and the bad text stays in the buffer, so the next scanf fails too.

TEXT
if (scanf("%d", &n) != 1) {
    printf("That was not a number.\n");
    return 1;
}
⚠️Practise with hardcoded values first

Most online judges and the Run button on this site feed no keyboard input, so a program waiting on scanf simply hangs. While you are learning a new concept, assign values directly in the code. Bring scanf back once the logic is already correct.

Common mistakes

  • Missing & in scanf. scanf("%d", n); compiles with a warning and then crashes. Write scanf("%d", &n);
  • Mismatched specifier and variable. scanf("%d", &price); where price is a float writes four bytes of integer into a float. Match them exactly.
  • Using %c right after %d. The stray newline gets consumed. Use " %c" with a leading space.
  • Unbounded %s. Always give a width, such as %49s for a char[50].
  • Expecting %s to read a full line. It stops at whitespace. Use fgets when you need an entire line including spaces.
  • Assuming %.2f changes the value. It only changes the display. The variable still holds the full precision.

Formatted output is a skill you will use in every program you ever write in this language, and reading input carefully is what separates a program that works from one that works only when the user cooperates. Put both to work on the Practice page.

Create a free account to track what you have finished.