Input & Output in C ๐ฅ๏ธ
Mentor's Note: Input and output are how your program talks to the outside world. Without output, your computer works in silence. Without input, your program is a static script that cannot adapt. Let's make our programs interactive! ๐ก
๐ Educational Content: This tutorial is designed to align with GSEB Std 10/12, CBSE Computer Science, and BCA Sem 1 syllabus standards.
By the end of this tutorial, you'll know:
- How to control the width and precision of text output using
printf. - How to read user input using
scanfand why the address-of operator&is required. - How to use escape sequences like
\n,\t, and\\. - How to read and write single characters using
getcharandputchar. - Why
gets()is dangerous and how to usefgets()as a secure alternative for strings.
๐ The Scenario: The Fast-Food Counterโ
Imagine you walk up to a Fast-Food Counter:
- The Order Slip (Input): You write your order on a slip. The cashier takes it and places it on a specific metal hook on the counter (The memory address-of
&operator) so the cook knows where to find your order data. - The Meal Tray (Output): Once the food is ready, the server formats it neatly. They don't just dump the burger and fries onto the counter; they place them in custom-sized slots on a tray, formatting the layout perfectly (Formatted Output).
- The Single-fry Dispenser (Character Input/Output): A small dispenser drops exactly one french fry at a time (like reading/writing one character).
Without structured input/output streams, the counter would be chaotic. C uses input/output streams to process data safely and display it beautifully.
๐ Concept Explanationโ
C does not have built-in input/output statements. Instead, it relies on standard functions provided by the <stdio.h> library.
1. Formatted Output: printf()โ
The printf() function stands for "print formatted." It allows you to output strings, variables, and constants.
Advanced Formatting: Width & Precisionโ
You can control how numbers are formatted using the syntax: %[flags][width][.precision]specifier
- Width: The minimum number of character spaces reserved for the value. If the value is shorter, it is padded with spaces.
%5d: Reserves 5 spaces, right-aligning the integer.%-5d: Left-aligns the integer within the 5 reserved spaces.
- Precision: Controls the number of digits after the decimal point for floating-point numbers.
%.2f: Prints a float with exactly 2 decimal places (rounds up if necessary).%8.2f: Reserves 8 spaces in total, with 2 of those spaces containing the decimal digits.
2. Formatted Input: scanf() and the Address-Of Operator &โ
The scanf() function reads formatted data from the keyboard.
The Role of the & Operatorโ
When you read a value into a variable (e.g. scanf("%d", &age)), you must prepend the variable name with & (the address-of operator).
scanfneeds to know the location in memory where the variable is stored to write the user's input directly into it.- Exception: You do not use
&when reading strings into character arrays because array names in C decay automatically into their starting memory address.
3. Character Input & Output: getchar() and putchar()โ
For single characters, C provides lightweight, specialized alternatives to printf and scanf:
getchar(): Reads a single character from the input buffer.putchar(char): Prints a single character to the screen.
char c = getchar(); // Reads a character
putchar(c); // Prints that character
4. String Input: Safe alternatives to gets()โ
Older C courses teach gets(buffer) to read full lines of text including spaces.
- The Danger:
gets()has no idea how large your buffer is. If your array can hold 10 characters and the user types 100,gets()will overwrite adjacent memory, leading to a crash or a security vulnerability known as a Buffer Overflow. - The Modern Standard:
gets()was officially deprecated and removed from C11. - The Solution: Always use
fgets(buffer, size, stdin)which limits the reading size tosize - 1bytes.
5. Common Escape Sequencesโ
Escape sequences are special character combinations representing layout actions (like tab or backspace) or symbols that are otherwise difficult to print.
| Escape Sequence | Description |
|---|---|
\n | Newline (moves cursor to next line) |
\t | Horizontal Tab (creates spacing) |
\\ | Prints a single backslash |
\" | Prints a double quote |
\% | Prints a percentage sign (used as %% inside format strings) |
๐ป Working Example: Formatted Input/Output and safe fgetsโ
Here is a complete program that reads student details, handles formatting width, and reads names safely:
#include <stdio.h>
// ๐ Scenario: Student Registry System
// ๐ Action: Reads inputs safely and displays formatted data
int main() {
int rollNo;
float percentage;
char fullName[40];
printf("Enter Roll Number: ");
scanf("%d", &rollNo);
printf("Enter Percentage: ");
scanf("%f", &percentage);
// Consume the leftover newline character '\n' in the input buffer
// left by the previous scanf. Without this, fgets would read the
// newline instantly and skip asking the user for their name!
getchar();
printf("Enter Student Full Name: ");
fgets(fullName, sizeof(fullName), stdin);
// Display formatted output
printf("\n==================================\n");
printf(" STUDENT DATA CARD\n");
printf("==================================\n");
// %-15s left-aligns string in 15 spaces
// %5d right-aligns int in 5 spaces
printf("%-15s: %5d\n", "Roll Number", rollNo);
// %.2f limits float to 2 decimal places
printf("%-15s: %8.2f%%\n", "Percentage", percentage);
printf("%-15s: %s", "Full Name", fullName);
printf("==================================\n");
return 0;
}
// Output:
// Enter Roll Number: 45
// Enter Percentage: 82.567
// Enter Student Full Name: Aarav Sharma
//
// ==================================
// STUDENT DATA CARD
// ==================================
// Roll Number : 45
// Percentage : 82.57%
// Full Name : Aarav Sharma
// ==================================
๐ Sample Dry Runโ
Let's trace how variables change when the program runs:
| Step | Instruction | Variable | Memory Address | Value Entered | Action |
|---|---|---|---|---|---|
| 1 | scanf("%d", &rollNo); | rollNo | 0x7ffee3 | 45 | Value 45 written directly to address 0x7ffee3. |
| 2 | scanf("%f", &percentage); | percentage | 0x7ffee7 | 82.567 | Value 82.567 written to 0x7ffee7. |
| 3 | getchar(); | None | None | '\n' | Leftover newline consumed from the stdin buffer. |
| 4 | fgets(fullName, 40, stdin); | fullName | 0x7ffefa | "Aarav Sharma" | Reads string including space up to 39 characters. |
๐งช Interactive Elementsโ
Try It Yourselfโ
Task: Write a program that declares a double variable double val = 12.3456789;. Print it using different formats:
- Default precision.
- Exactly 3 decimal places.
- Total width of 10 spaces, left-aligned, with 2 decimal places.
Hint: Use %.3lf and %-10.2lf.
Quick Quizโ
Why do we call getchar() after reading a number with scanf() but before calling fgets()?
- A) To pause the program.
- B) To initialize
fgets(). - C) To consume the leftover newline
\nin the input buffer. - D) It is not necessary; the code works without it.
Explanation: When you type a number and press Enter (like 45\n), scanf reads the 45 but leaves the \n (newline) in the input buffer. If we call fgets immediately, it sees the \n in the buffer and assumes the user pressed enter, skipping name input completely. We use getchar() to consume that leftover newline first.
๐ Complexity Analysisโ
- Time Complexity:
- Output (
printf,putchar): $O(K)$ where $K$ is the number of characters printed. - Input (
scanf,getchar,fgets): $O(K)$ where $K$ is the number of characters read from stdin.
- Output (
- Space Complexity:
- Memory allocation: $O(M)$ where $M$ is the size of the input buffer (e.g. 40 bytes for
fullName).
- Memory allocation: $O(M)$ where $M$ is the size of the input buffer (e.g. 40 bytes for
๐ฏ Practice Problemsโ
Easy Level ๐ขโ
- Write a program to print three numbers separated by tabs (
\t) and newlines (\n). - Fix this bug in the code:
int age;scanf("%d", age); // What is missing here?
Medium Level ๐กโ
- Write a calculator program that reads two float numbers and prints their sum, difference, product, and quotient, formatted to exactly 2 decimal places.
Hard Level ๐ดโ
- Write a program to read a line of text containing spaces using
fgets(). Strip the trailing newline character (\n) thatfgets()automatically appends, and print the cleaned string and its length.
โ Frequently Asked Questionsโ
Details
Q: What is the difference between scanf and fgets for reading strings?
scanf("%s", str) reads a word. It stops reading as soon as it encounters a space, tab, or newline. fgets(str, size, stdin) reads a line. It reads all characters including spaces, and stops only when it reaches the specified size limit or encounters a newline.Details
Q: Why does my program crash when I forget the & in scanf?
If you forget the & (e.g., scanf("%d", age)), scanf takes the current value inside age (which is a garbage value like 10543) and tries to write the input directly to the memory address 10543. Since this address is protected, the operating system kills your program instantly (generating a segmentation fault).Details
Q: Can I use fflush(stdin) to clear the input buffer?
No! According to the C standard, fflush(stdin) is undefined behavior. While it may work on some compilers (like old Turbo C or Windows MSVC), it does not work on GCC/Linux. The portable way to clear the buffer is reading characters manually: while ((c = getchar()) != '\n' && c != EOF);.๐ Best Practices & Common Mistakesโ
โ Best Practicesโ
- Always check input buffer: When combining
scanfwith character/string readers likegetchar()orfgets(), remember to consume the trailing newline. - Set array limits: When using
fgets(), pass the actual size of the character array usingsizeof(array)to make buffer protection automatic. - Label input requests: Always print a prompt (like
printf("Enter age: ")) before calling an input function so the user knows they need to type something.
โ Common Mistakes โ ๏ธโ
- Missing
&in scanf: Writingscanf("%d", num)instead ofscanf("%d", &num). - Using gets(): Writing
gets(name)instead offgets(name, sizeof(name), stdin). - Mismatching formatting specifiers: Writing
scanf("%d", &floatVar).
โ Summaryโ
In this tutorial, you've learned:
- โ
C handles I/O using standard functions from the
<stdio.h>library. - โ
printfsupports formatting flags for controlling alignment, width, and decimal precision. - โ
scanfrequires the address-of operator&to locate variables in memory. - โ
getcharandputcharare optimized for single-character input/output. - โ
fgetsis the secure, buffer-protected replacement for the obsoletegetsfunction.
๐ก Pro Tip: To print a literal percent sign
%in aprintfformat string, double it:printf("Tax: %d%%", 18);!
๐ Further Readingโ
Continue your learning path:
Go deeper: