Input and Output (I/O) operations are the fundamental means by which C programs interact with the outside world. Whether reading user input from the keyboard, displaying results on the screen, or processing files, understanding C's I/O functions is essential for every programmer. Unlike higher-level languages with extensive I/O libraries, C provides a concise but powerful set of functions that form the foundation of data exchange in systems programming.
The Standard I/O Library
C's I/O functionality is provided through the Standard I/O Library (stdio.h). This header file declares the functions, macros, and data types necessary for performing input and output operations.
#include <stdio.h>
The library operates on streams, abstract representations of input sources or output destinations. C automatically opens three standard streams when a program starts:
| Stream | Name | Description | Default Device |
|---|---|---|---|
stdin | Standard Input | Input stream | Keyboard |
stdout | Standard Output | Output stream | Screen |
stderr | Standard Error | Error output stream | Screen |
Formatted Output: The printf() Function
The most commonly used output function in C is printf(), which prints formatted data to the standard output.
Basic Syntax:
int printf(const char *format, ...);
Simple Examples:
#include <stdio.h>
int main() {
// Simple string output
printf("Hello, World!\n");
// Output with newlines
printf("This is line 1\n");
printf("This is line 2\n");
return 0;
}
Format Specifiers:
printf() uses format specifiers to insert values into the output string:
| Specifier | Data Type | Example |
|---|---|---|
%d or %i | int (signed integer) | printf("%d", 42); |
%u | unsigned int | printf("%u", 42); |
%f | float or double | printf("%f", 3.14159); |
%lf | double (long float) | printf("%lf", 3.14159); |
%c | char (single character) | printf("%c", 'A'); |
%s | String (char array) | printf("%s", "hello"); |
%p | Pointer address | printf("%p", &variable); |
%x or %X | Hexadecimal | printf("%x", 255); |
%o | Octal | printf("%o", 255); |
%% | Percent sign | printf("%%"); |
Examples with Format Specifiers:
#include <stdio.h>
int main() {
int age = 25;
float height = 1.85;
char grade = 'A';
char name[] = "Alice";
printf("Name: %s\n", name);
printf("Age: %d years\n", age);
printf("Height: %.2f meters\n", height); // .2 specifies 2 decimal places
printf("Grade: %c\n", grade);
// Multiple specifiers
printf("%s is %d years old, %.1f m tall, and got grade %c\n",
name, age, height, grade);
return 0;
}
Format Width and Precision:
#include <stdio.h>
int main() {
int num = 42;
float pi = 3.1415926535;
// Width specification
printf("|%d|\n", num); // |42|
printf("|%5d|\n", num); // | 42| (width 5, right-aligned)
printf("|%-5d|\n", num); // |42 | (left-aligned)
printf("|%05d|\n", num); // |00042| (zero-padded)
// Precision for floating point
printf("|%f|\n", pi); // |3.141593| (default 6 decimal places)
printf("|%.2f|\n", pi); // |3.14|
printf("|%8.3f|\n", pi); // | 3.142| (width 8, 3 decimals)
printf("|%-8.3f|\n", pi); // |3.142 | (left-aligned)
return 0;
}
Escape Sequences:
| Sequence | Meaning |
|---|---|
\n | Newline |
\t | Horizontal tab |
\r | Carriage return |
\b | Backspace |
\' | Single quote |
\" | Double quote |
\\ | Backslash |
\0 | Null character (string terminator) |
printf("Column1\tColumn2\tColumn3\n");
printf("Value1\tValue2\tValue3\n");
printf("She said, \"Hello!\"\n");
printf("Backslash: \\\n");
Formatted Input: The scanf() Function
The scanf() function reads formatted input from the standard input, typically the keyboard.
Basic Syntax:
int scanf(const char *format, ...);
Important: Unlike printf(), scanf() requires addresses of variables (using the & operator) for storing input values.
#include <stdio.h>
int main() {
int age;
float height;
char name[50];
printf("Enter your age: ");
scanf("%d", &age); // Note the & before age
printf("Enter your height in meters: ");
scanf("%f", &height); // & before height
printf("Enter your name: ");
scanf("%s", name); // No & needed for arrays (name is already an address)
printf("\n--- Your Information ---\n");
printf("Name: %s\n", name);
printf("Age: %d\n", age);
printf("Height: %.2f m\n", height);
return 0;
}
Multiple Inputs:
#include <stdio.h>
int main() {
int day, month, year;
printf("Enter date (dd mm yyyy): ");
scanf("%d %d %d", &day, &month, &year);
printf("Date: %02d/%02d/%04d\n", day, month, year);
return 0;
}
Common scanf() Pitfalls:
- Whitespace handling:
scanf()stops reading at whitespace for%s - Buffer overflow: No bounds checking for strings
- Input validation: Returns number of successfully matched items
#include <stdio.h>
int main() {
int num;
char str[10];
printf("Enter a number and a string: ");
int items = scanf("%d %9s", &num, str); // Limit string to 9 chars + null
if (items == 2) {
printf("Successfully read %d items\n", items);
printf("Number: %d, String: %s\n", num, str);
} else {
printf("Error: Expected 2 items, got %d\n", items);
}
return 0;
}
Character I/O: getchar() and putchar()
For single-character input and output, C provides simpler functions.
getchar() - Read a single character:
#include <stdio.h>
int main() {
char ch;
printf("Press any key: ");
ch = getchar(); // Reads one character
printf("You pressed: '%c'\n", ch);
printf("ASCII value: %d\n", ch);
return 0;
}
putchar() - Write a single character:
#include <stdio.h>
int main() {
char message[] = "Hello";
for (int i = 0; message[i] != '\0'; i++) {
putchar(message[i]); // Output each character
}
putchar('\n'); // Newline
return 0;
}
Reading Until Newline:
#include <stdio.h>
int main() {
char ch;
printf("Enter text (press Enter to finish):\n");
while ((ch = getchar()) != '\n') {
putchar(ch); // Echo the character
}
putchar('\n');
return 0;
}
String I/O: gets() and puts() (with warnings)
puts() - Output a string:
#include <stdio.h>
int main() {
char greeting[] = "Hello, World!";
puts(greeting); // Automatically adds newline
puts("Another line");
return 0;
}
gets() - DANGEROUS! Never use:
// NEVER USE gets() - it's dangerous and removed from C11 // char buffer[10]; // gets(buffer); // Can overflow buffer!
Safe alternative: fgets()
#include <stdio.h>
int main() {
char buffer[50];
printf("Enter a line of text: ");
fgets(buffer, sizeof(buffer), stdin); // Safe: limits input size
printf("You entered: ");
fputs(buffer, stdout); // Output without extra newline
return 0;
}
Practical Examples
Example 1: Simple Calculator
#include <stdio.h>
int main() {
double num1, num2, result;
char operator;
printf("Simple Calculator\n");
printf("Enter expression (e.g., 5 + 3): ");
scanf("%lf %c %lf", &num1, &operator, &num2);
switch (operator) {
case '+':
result = num1 + num2;
printf("%.2f + %.2f = %.2f\n", num1, num2, result);
break;
case '-':
result = num1 - num2;
printf("%.2f - %.2f = %.2f\n", num1, num2, result);
break;
case '*':
result = num1 * num2;
printf("%.2f * %.2f = %.2f\n", num1, num2, result);
break;
case '/':
if (num2 != 0) {
result = num1 / num2;
printf("%.2f / %.2f = %.2f\n", num1, num2, result);
} else {
printf("Error: Division by zero\n");
}
break;
default:
printf("Error: Unknown operator\n");
}
return 0;
}
Example 2: Temperature Converter
#include <stdio.h>
int main() {
char choice;
double celsius, fahrenheit;
printf("Temperature Converter\n");
printf("Choose conversion:\n");
printf("C - Celsius to Fahrenheit\n");
printf("F - Fahrenheit to Celsius\n");
printf("Enter choice: ");
scanf("%c", &choice);
if (choice == 'C' || choice == 'c') {
printf("Enter temperature in Celsius: ");
scanf("%lf", &celsius);
fahrenheit = (celsius * 9 / 5) + 32;
printf("%.2f°C = %.2f°F\n", celsius, fahrenheit);
}
else if (choice == 'F' || choice == 'f') {
printf("Enter temperature in Fahrenheit: ");
scanf("%lf", &fahrenheit);
celsius = (fahrenheit - 32) * 5 / 9;
printf("%.2f°F = %.2f°C\n", fahrenheit, celsius);
}
else {
printf("Invalid choice\n");
}
return 0;
}
Example 3: Input Validation Loop
#include <stdio.h>
int main() {
int age;
int valid = 0;
while (!valid) {
printf("Enter your age (1-120): ");
if (scanf("%d", &age) == 1) {
if (age >= 1 && age <= 120) {
valid = 1;
printf("Age accepted: %d\n", age);
} else {
printf("Age must be between 1 and 120\n");
}
} else {
printf("Invalid input. Please enter a number.\n");
// Clear input buffer
while (getchar() != '\n');
}
}
return 0;
}
Example 4: Menu-Driven Program
#include <stdio.h>
int main() {
int choice;
do {
printf("\n--- Main Menu ---\n");
printf("1. Display message\n");
printf("2. Show date\n");
printf("3. Show time\n");
printf("4. Exit\n");
printf("Enter your choice (1-4): ");
scanf("%d", &choice);
switch (choice) {
case 1:
printf("\nHello! Welcome to the program.\n");
break;
case 2:
printf("\nCurrent date: 2025-03-11\n");
break;
case 3:
printf("\nCurrent time: 14:30:00\n");
break;
case 4:
printf("\nGoodbye!\n");
break;
default:
printf("\nInvalid choice. Please try again.\n");
}
} while (choice != 4);
return 0;
}
Example 5: Reading Multiple Data Types
#include <stdio.h>
int main() {
int id;
char name[50];
float salary;
char department;
printf("Employee Information System\n");
printf("==========================\n\n");
printf("Enter employee ID: ");
scanf("%d", &id);
// Clear newline from previous input
while (getchar() != '\n');
printf("Enter employee name: ");
fgets(name, sizeof(name), stdin);
// Remove trailing newline
name[strcspn(name, "\n")] = 0;
printf("Enter monthly salary: ");
scanf("%f", &salary);
// Clear newline
while (getchar() != '\n');
printf("Enter department (A/B/C): ");
scanf("%c", &department);
printf("\n--- Employee Record ---\n");
printf("ID: %d\n", id);
printf("Name: %s\n", name);
printf("Salary: $%.2f\n", salary);
printf("Department: %c\n", department);
printf("Annual salary: $%.2f\n", salary * 12);
return 0;
}
Common Mistakes and Best Practices
Mistake 1: Forgetting the & in scanf()
int num;
scanf("%d", num); // WRONG - missing &
scanf("%d", &num); // CORRECT
Mistake 2: Buffer Overflow
char name[10];
scanf("%s", name); // DANGEROUS - can overflow if input > 9 chars
scanf("%9s", name); // SAFE - limits input to 9 chars + null
Mistake 3: Mixing scanf() and getchar()
int num;
char ch;
printf("Enter number: ");
scanf("%d", &num); // Leaves newline in buffer
printf("Enter character: ");
ch = getchar(); // Reads the leftover newline, not user input!
// Fix: Clear buffer
while (getchar() != '\n'); // Clear newline
ch = getchar(); // Now reads correctly
Best Practice 1: Always Check Return Values
if (scanf("%d", &num) != 1) {
printf("Invalid input\n");
// Handle error
}
Best Practice 2: Use fgets() for Strings
char buffer[100]; fgets(buffer, sizeof(buffer), stdin); // Remove trailing newline buffer[strcspn(buffer, "\n")] = 0;
Best Practice 3: Clear Input Buffer When Needed
void clearInputBuffer() {
int c;
while ((c = getchar()) != '\n' && c != EOF);
}
Error Output with stderr
Always use stderr for error messages:
#include <stdio.h>
int main() {
FILE *file = fopen("nonexistent.txt", "r");
if (file == NULL) {
fprintf(stderr, "Error: Could not open file\n");
return 1;
}
fprintf(stdout, "File opened successfully\n"); // Regular output
fclose(file);
return 0;
}
Summary of I/O Functions
| Function | Purpose | Header | Example |
|---|---|---|---|
printf() | Formatted output | stdio.h | printf("%d", num); |
scanf() | Formatted input | stdio.h | scanf("%d", &num); |
putchar() | Single character output | stdio.h | putchar('A'); |
getchar() | Single character input | stdio.h | ch = getchar(); |
puts() | String output (with newline) | stdio.h | puts("Hello"); |
fputs() | String output to stream | stdio.h | fputs("Hello", stdout); |
fgets() | Safe string input | stdio.h | fgets(buf, size, stdin); |
fprintf() | Formatted output to stream | stdio.h | fprintf(stderr, "Error"); |
sprintf() | Formatted output to string | stdio.h | sprintf(str, "%d", num); |
sscanf() | Formatted input from string | stdio.h | sscanf(str, "%d", &num); |
Conclusion
Basic Input/Output in C provides the essential tools for program-user interaction. While seemingly simple, mastering these functions requires understanding format specifiers, buffer management, error handling, and the nuances of different input functions. The Standard I/O library's functions have remained largely unchanged for decades because they provide exactly what's needed: simple, efficient, and predictable I/O operations.
For new C programmers, the key takeaways are:
- Always use
&withscanf()for non-array variables - Never use
gets()- usefgets()instead - Check return values for error detection
- Be mindful of buffer sizes to prevent overflow
- Clear the input buffer when switching between input types
With these fundamentals mastered, you'll be well-equipped to build interactive C programs that can handle user input gracefully and produce well-formatted output for any purpose.