Docs

Input Output

Input/Output in C (scanf, printf)

šŸ“– Introduction

Input/Output (I/O) operations allow C programs to interact with users and external devices. The most common I/O functions are printf() for output and scanf() for input, both declared in <stdio.h>.


šŸŽÆ Standard I/O Streams

C provides three standard streams that are automatically opened when a program starts:

ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”
│                     Standard Streams                         │
ā”œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”¤
│                                                              │
│   Keyboard ──► stdin  ──┐                                   │
│                         │                                   │
│                         ā–¼                                   │
│                   ā”Œā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”                              │
│                   │ C Program │                              │
│                   ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜                              │
│                    │        │                               │
│                    ā–¼        ā–¼                               │
│                 stdout   stderr                             │
│                    │        │                               │
│                    ā–¼        ā–¼                               │
│                  Screen  Screen                             │
│                                                              │
ā””ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜
StreamTypeDescriptionC Name
Standard InputInputKeyboard (by default)stdin
Standard OutputOutputScreen (by default)stdout
Standard ErrorOutputScreen (for errors)stderr

šŸ“¤ Output with printf()

Basic Syntax:

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

printf() returns the number of characters printed (negative on error).

Simple Output:

#include <stdio.h>

int main() {
    printf("Hello, World!\n");  // Print string with newline
    printf("Hello ");
    printf("World\n");          // Continues on same line
    return 0;
}

Format Specifiers:

int age = 25;
float price = 19.99;
char grade = 'A';
char name[] = "John";

printf("Age: %d\n", age);       // Integer
printf("Price: %f\n", price);   // Float
printf("Grade: %c\n", grade);   // Character
printf("Name: %s\n", name);     // String

Complete Format Specifier Table:

SpecifierTypeExampleOutput
%d, %iSigned integerprintf("%d", 42);42
%uUnsigned integerprintf("%u", 42);42
%fFloat/doubleprintf("%f", 3.14);3.140000
%e, %EScientific notationprintf("%e", 1234.5);1.234500e+03
%g, %GShorter of %f or %eprintf("%g", 0.0001);0.0001
%cCharacterprintf("%c", 'A');A
%sStringprintf("%s", "Hi");Hi
%pPointer addressprintf("%p", &x);0x7ffd...
%x, %XHexadecimalprintf("%x", 255);ff
%oOctalprintf("%o", 64);100
%ldLong intprintf("%ld", 100000L);100000
%lldLong long intprintf("%lld", 10000000000LL);10000000000
%lfDouble (scanf only)scanf("%lf", &d);N/A
%LfLong doubleprintf("%Lf", 3.14L);3.140000
%zusize_tprintf("%zu", sizeof(int));4
%%Literal %printf("%%");%

Format Modifiers:

Format: %[flags][width][.precision][length]specifier

Width:

printf("[%10d]\n", 42);     // [        42]  Right-aligned, width 10
printf("[%-10d]\n", 42);    // [42        ]  Left-aligned, width 10
printf("[%*d]\n", 10, 42);  // [        42]  Width from variable

Precision:

printf("%.2f\n", 3.14159);      // 3.14       (2 decimal places)
printf("%.5s\n", "Hello World"); // Hello      (5 characters)
printf("%10.2f\n", 3.14159);    //       3.14 (width 10, 2 decimals)

Flags:

FlagMeaningExampleOutput
-Left-align%-10d, 4242
+Show sign%+d, 42+42
Space for positive% d, 42 42
0Zero-pad%010d, 420000000042
#Alternate form%#x, 2550xff

Examples:

int num = 42;
float f = 3.14159;

// Width and alignment
printf("[%10d]\n", num);      // [        42]
printf("[%-10d]\n", num);     // [42        ]
printf("[%010d]\n", num);     // [0000000042]

// Precision
printf("[%.2f]\n", f);        // [3.14]
printf("[%10.2f]\n", f);      // [      3.14]
printf("[%-10.2f]\n", f);     // [3.14      ]

// Signs
printf("[%+d]\n", num);       // [+42]
printf("[%+d]\n", -num);      // [-42]
printf("[% d]\n", num);       // [ 42]

// Alternate forms
printf("[%#x]\n", 255);       // [0xff]
printf("[%#o]\n", 64);        // [0100]
printf("[%#.0f]\n", 3.0);     // [3.]

šŸ“„ Input with scanf()

Basic Syntax:

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

scanf() returns the number of successfully read items (0 or negative on failure).

āš ļø Important: Use Address-of Operator (&)

int age;
scanf("%d", &age);    // CORRECT: Pass address
// scanf("%d", age);  // WRONG: Undefined behavior!

Simple Input:

#include <stdio.h>

int main() {
    int age;
    float height;
    char grade;

    printf("Enter age: ");
    scanf("%d", &age);

    printf("Enter height: ");
    scanf("%f", &height);

    printf("Enter grade: ");
    scanf(" %c", &grade);  // Note: space before %c

    printf("Age: %d, Height: %.2f, Grade: %c\n", age, height, grade);

    return 0;
}

scanf Format Specifiers:

SpecifierReadsExample
%dSigned integerscanf("%d", &num);
%iInteger (any base)scanf("%i", &num);
%uUnsigned integerscanf("%u", &num);
%fFloatscanf("%f", &f);
%lfDoublescanf("%lf", &d);
%cSingle characterscanf("%c", &ch);
%sString (no spaces)scanf("%s", str);
%[...]Scansetscanf("%[^\n]", str);
%nCharacters read so farscanf("%d%n", &x, &n);

Reading Multiple Values:

int a, b, c;

// Space-separated input
printf("Enter three integers: ");
scanf("%d %d %d", &a, &b, &c);

// Or any whitespace works
scanf("%d%d%d", &a, &b, &c);  // Spaces optional in format

// Reading different types
int age;
float height;
char initial;
scanf("%d %f %c", &age, &height, &initial);

The Newline Problem:

int num;
char ch;

printf("Enter number: ");
scanf("%d", &num);

printf("Enter character: ");
scanf("%c", &ch);  // PROBLEM: Reads leftover '\n'!

// Solutions:

// Solution 1: Add space before %c
scanf(" %c", &ch);  // Space consumes whitespace

// Solution 2: Use getchar() to consume newline
scanf("%d", &num);
getchar();  // Consume '\n'
scanf("%c", &ch);

// Solution 3: Use %*c to skip the newline
scanf("%d%*c", &num);  // %*c reads and discards a character
scanf("%c", &ch);

Reading Strings:

char name[50];

// Method 1: %s (stops at whitespace)
printf("Enter name: ");
scanf("%s", name);  // Note: No & for arrays!
// Input: "John Doe" → Only "John" is stored

// Method 2: %[^\n] (reads until newline)
scanf(" %[^\n]", name);  // Reads whole line including spaces
// Input: "John Doe" → "John Doe" is stored

// Method 3: Limit input length (SAFE)
scanf("%49s", name);     // Max 49 chars + null terminator
scanf("%49[^\n]", name); // Max 49 chars with spaces

Return Value Checking:

int num;
printf("Enter a number: ");

if (scanf("%d", &num) != 1) {
    printf("Invalid input!\n");
    return 1;
}

printf("You entered: %d\n", num);

šŸ”” Character I/O: getchar() and putchar()

getchar() - Read Single Character:

#include <stdio.h>

int main() {
    int ch;  // Use int, not char (for EOF detection)

    printf("Enter a character: ");
    ch = getchar();

    printf("You entered: ");
    putchar(ch);
    putchar('\n');

    return 0;
}

putchar() - Write Single Character:

putchar('A');       // Print 'A'
putchar('\n');      // Print newline
putchar(65);        // Print 'A' (ASCII value)

Reading a Line Character by Character:

int ch;
printf("Enter text (press Enter to stop): ");
while ((ch = getchar()) != '\n') {
    putchar(ch);
}
putchar('\n');

šŸ“ String I/O: gets() and puts()

āš ļø Warning: Never Use gets()

gets() is unsafe and removed from C11. It doesn't check buffer size:

// DANGEROUS - Never use!
char buffer[10];
gets(buffer);  // Can overflow buffer!

Use fgets() Instead:

char buffer[100];
printf("Enter a line: ");
fgets(buffer, sizeof(buffer), stdin);  // Safe!

// Note: fgets keeps the newline character
// Remove it if needed:
buffer[strcspn(buffer, "\n")] = '\0';

puts() - Print String with Newline:

puts("Hello, World!");  // Automatically adds newline
// Equivalent to: printf("Hello, World!\n");

šŸ”„ Buffer Flushing

fflush() - Flush Output Buffer:

printf("Loading");
for (int i = 0; i < 5; i++) {
    printf(".");
    fflush(stdout);  // Force output immediately
    sleep(1);
}
printf("\n");

Clearing Input Buffer:

// Method 1: Read and discard until newline
int c;
while ((c = getchar()) != '\n' && c != EOF);

// Method 2: Using scanf
scanf("%*[^\n]");  // Discard until newline
scanf("%*c");      // Discard newline itself

šŸ“Š Formatted I/O Examples

Creating Tables:

printf("%-10s %10s %10s\n", "Name", "Age", "Score");
printf("%-10s %10s %10s\n", "----", "---", "-----");
printf("%-10s %10d %10.2f\n", "Alice", 25, 95.50);
printf("%-10s %10d %10.2f\n", "Bob", 30, 88.75);
printf("%-10s %10d %10.2f\n", "Charlie", 22, 92.00);

Output:

Name              Age      Score
----              ---      -----
Alice              25      95.50
Bob                30      88.75
Charlie            22      92.00

Progress Bar:

for (int i = 0; i <= 100; i += 10) {
    printf("\r[%-20s] %3d%%", "####################" + (20 - i/5), i);
    fflush(stdout);
    usleep(100000);  // Sleep 100ms
}
printf("\n");

Hexdump:

unsigned char data[] = {0x48, 0x65, 0x6C, 0x6C, 0x6F};
for (int i = 0; i < sizeof(data); i++) {
    printf("%02X ", data[i]);
}
printf("\n");
// Output: 48 65 6C 6C 6F

āš ļø Common Mistakes

1. Missing & in scanf:

int x;
scanf("%d", x);    // WRONG: crashes or corrupts memory
scanf("%d", &x);   // CORRECT

2. Wrong Format Specifier:

float f = 3.14;
scanf("%d", &f);   // WRONG: expects int
scanf("%f", &f);   // CORRECT

double d;
scanf("%f", &d);   // WRONG for double
scanf("%lf", &d);  // CORRECT for double

3. Buffer Overflow with %s:

char name[10];
scanf("%s", name);      // DANGEROUS: could overflow
scanf("%9s", name);     // SAFE: max 9 chars + null

4. Not Checking Return Value:

// Bad: No error checking
scanf("%d", &num);

// Good: Check for valid input
if (scanf("%d", &num) != 1) {
    printf("Invalid input\n");
}

5. Mixing scanf and getchar:

scanf("%d", &num);
char ch = getchar();  // Gets '\n' from previous input!

// Fix:
scanf("%d", &num);
getchar();            // Consume the newline first
char ch = getchar();  // Now gets actual character

āœ… Best Practices

  1. •Always check scanf() return value for input validation
  2. •Use field width with %s to prevent buffer overflow: %49s
  3. •Prefer fgets() over scanf() for strings - safer and more flexible
  4. •Use appropriate format specifiers - %lf for double in scanf
  5. •Add space before %c when following other inputs: " %c"
  6. •Flush stdout when printing without newline and expecting input
  7. •Initialize buffers before reading into them
  8. •Handle EOF in character input loops

šŸ”‘ Key Takeaways

  1. •printf() displays formatted output; scanf() reads formatted input
  2. •Format specifiers must match the variable type
  3. •scanf requires address (using &) except for arrays
  4. •Whitespace in scanf skips whitespace in input
  5. •Check return values to handle input errors
  6. •Buffer overflow is a major security concern - always limit input size
  7. •The newline problem requires special handling with character input

ā­ļø Next Topic

Continue to Operators to learn about arithmetic, relational, logical, and bitwise operators.

Input Output - C Programming Tutorial | DeepML