C Programming C++ Java JavaScript Kotlin PHP Python

šŸ’» C Programming

Learn the basics of C programming, including variables, loops, and functions.

Input & Output::( printf(), scanf(), Escape sequences, Format specifiers)

C’s standard I/O is provided by the C Standard Library (<stdio.h>). The most common functions for console I/O are:

  • printf() — formatted output to stdout.

  • scanf() — formatted input from stdin.

There are many related functions too: puts(), putchar(), fgets(), fputs(), getchar(), sscanf(), sprintf()/snprintf(), fprintf() (for files), etc. Use fgets() + sscanf() for safe input instead of scanf() for many real programs.


1. printf() — Formatted output

Definition: int printf(const char *format, ...);
Prints formatted text to standard output. Returns number of characters printed (or a negative value on error).

Principles:

  • The format string contains text + conversion specifiers (like %d, %s) which are replaced by the corresponding arguments.

  • C uses variadic functions for printf. Arguments undergo default argument promotions (e.g., float → double), so pass matching types.

  • Use snprintf() when you need to format into a buffer safely (avoid sprintf() because it can overflow).

Basic examples:

#include <stdio.h> int main(void) { int age = 20; double pi = 3.1415926535; char name[] = "Denis"; printf("Name: %s\n", name); printf("Age: %d\n", age); printf("Pi approx: %.4f\n", pi); // 4 decimal places return 0; }

Flags, width, precision, length modifier (brief):

  • Structure: %[flags][width][.precision][length]specifier

  • Flags: - (left), + (always sign), (space if no sign), 0 (pad with zeros), # (alternate form)

  • Width: minimum field width (integer or * to pass at runtime)

  • Precision: for floats (digits after decimal) or max chars for strings

  • Length: h, hh, l, ll, L, z, j, t (match the argument type)

Examples:

printf("%6d", 42); // field width 6 -> " 42" printf("%-6d", 42); // left-aligned -> "42 " printf("%06d", 42); // zero-padded -> "000042" printf("%.2f", 3.14159); // -> "3.14" printf("%.*f", 3, 3.14159); // dynamic precision -> "3.142"

Useful specifiers (common):

  • %d / %i — signed int

  • %u — unsigned int

  • %ld, %lld — long, long long

  • %hd, %hhd — short, signed char

  • %f, %F — double (note: float promoted to double)

  • %Lf — long double

  • %c — single character

  • %s — string (null-terminated)

  • %p — pointer (address)

  • %o, %x, %X — octal, hex lowercase/uppercase

  • %e, %E, %g — scientific / general format

  • %zu — size_t (use when printing sizeof results)

  • Use <inttypes.h> macros for int32_t, int64_t: PRId32, PRIu64 etc:

    #include <inttypes.h> printf("val = %" PRId32 "\n", x);

Best practices for printf:

  • Use the correct length modifiers; mismatched types cause undefined behavior.

  • Prefer snprintf() to fill a buffer safely.

  • For logging use fprintf(stderr, ...) for errors, stdout for normal output.

  • Use %zu for size_t, %p for pointers.


2. scanf() — Formatted input (and safer alternatives)

Definition: int scanf(const char *format, ...);
Reads formatted input from standard input. Returns the number of input items successfully matched and assigned, or EOF on failure.

How it works:

  • scanf() parses stdin according to the format and stores the results into the provided addresses (you pass pointers).

  • You must pass addresses for non-array variables (use &), but arrays (like char s[20]) decay to pointers so you pass the array name.

Basic example:

#include <stdio.h> int main(void) { int age; char name[50]; printf("Enter your name and age: "); scanf("%49s %d", name, &age); // %49s limits input to 49 chars + null printf("Name: %s, Age: %d\n", name, age); return 0; }

Why scanf() can be dangerous / pitfalls:

  • %s reads a whitespace-delimited token and can overflow the target buffer if you don't give a width.

  • scanf() leaves newline characters in the input buffer for some conversions.

  • Mixing scanf() with fgets()/getchar() needs care because of leftover \n.

  • scanf()'s return value must be checked (it tells how many conversions succeeded).

  • scanf() treats whitespace in the format string as "skip any whitespace".

Safer alternatives:

  • Use fgets() to read a full line into a buffer, then parse with sscanf() or strtol() / strtod() / strtok() / custom parsing.

  • fgets() prevents buffer overflow and gives you control over validation.

Example: safe input with fgets + sscanf

#include <stdio.h> int main(void) { char buf[100]; int age; printf("Enter age: "); if (fgets(buf, sizeof buf, stdin)) { if (sscanf(buf, "%d", &age) == 1) { printf("You are %d years old\n", age); } else { puts("Invalid number"); } } return 0; }

Using field width in scanf to prevent overflow:

  • For char name[50] use %49s

  • For strings with spaces use: fgets() or scanf("%49[^\n]", name) but the latter still tricky

Handling characters and whitespace:

  • %c reads the next character (even whitespace). If you want to ignore whitespace before %c, use " %c" (a leading space in the format string).

  • Example: scanf(" %c", &ch); skips whitespace and reads the next non-space char.

Check return value:

int n = scanf("%d", &x); if (n != 1) { /* handle invalid input */ }

3. Escape Sequences

Definition: Escape sequences are special sequences that represent characters that are difficult to type or invisible (like newline) inside string or character literals.

Common escape sequences:

  • \n — newline (line feed)

  • \r — carriage return

  • \t — horizontal tab

  • \b — backspace

  • \f — form feed

  • \v — vertical tab

  • \\ — backslash \

  • \' — single quote

  • \" — double quote

  • \0 — null character (string terminator)

  • \a — audible bell (may ring or do nothing)

  • \ooo — octal character code (e.g., \101)

  • \xhh — hex character code (e.g., \x41)

Examples:

printf("Hello\tWorld\n"); // tab between words, newline at end printf("Quote: \"To be...\"\n"); printf("Backslash: \\\n"); // prints one backslash printf("Null char: %c\n", '\0'); // prints nothing visible

Notes:

  • Strings in C are null-terminated ('\0').

  • Use escape sequences to control formatting, embed quotes, or print special characters.


4. Format Specifiers (detailed reference & rules)

Integer formats:

  • %d / %i — signed int

  • %u — unsigned int

  • %o — unsigned octal

  • %x / %X — unsigned hexadecimal (lower/upper)

  • length modifiers:

    • h → short: %hd, %hu

    • hh → signed/unsigned char: %hhd, %hhu

    • l → long: %ld, %lu, %lo, %lx

    • ll → long long: %lld, %llu

    • z → size_t: %zu (unsigned)

    • j → intmax_t macros in <inttypes.h>

Floating point formats:

  • %f / %F — decimal notation

  • %e / %E — scientific notation (exponent)

  • %g / %G — use %f or %e whichever is shorter, strips trailing zeros

  • %Lf — long double

Character and string:

  • %c — single char (pass int or char promoted to int)

  • %s — null-terminated string (char array)

Pointer and special:

  • %p — pointer (address)

  • %% — prints a literal %

Precision and width examples:

  • %10d — width 10, right-aligned

  • %-10d — width 10, left-aligned

  • %.3f — 3 decimal places

  • %10.3f — width 10, 3 decimals

  • %.*f — precision from argument: printf("%.*f", prec, value);

Important notes:

  • printf promotes float to double, so %f expects double.

  • For scanf, %f expects pointer to float, %lf expects pointer to double. (This difference is important!)

  • Use format macros in <inttypes.h> such as PRId64 for int64_t when portability is required:

    #include <inttypes.h> int64_t x = 42; printf("x = %" PRId64 "\n", x);

5. Practical Examples & Patterns

Example 1 — Basic input & output

#include <stdio.h> int main(void) { char name[50]; int age; printf("Enter name: "); if (fgets(name, sizeof name, stdin)) { // remove newline if present name[strcspn(name, "\n")] = '\0'; } printf("Enter age: "); if (scanf("%d", &age) != 1) { fprintf(stderr, "Invalid age\n"); return 1; } printf("Hello %s, age %d\n", name, age); return 0; }

Example 2 — Avoiding scanf overflow (use width)

char buf[20]; scanf("%19s", buf); // prevents buffer overflow (leaves room for '\0')

Example 3 — Reading full line (with spaces)

char line[200]; if (fgets(line, sizeof line, stdin)) { // process the entire line, safe even with spaces }

Example 4 — Format building with snprintf

char buffer[128]; int written = snprintf(buffer, sizeof buffer, "User: %s, score: %d", user, score); if (written >= (int)sizeof buffer) { // truncated }

6. Use Cases

  • printf() used for: user messages, debug printing, formatted reports, logging to files (via fprintf()).

  • scanf() used for: small quick demos and controlled input; prefer fgets() for real-world user input.

  • fgets() + sscanf() or strtol() used for robust parsing and input validation.

  • snprintf() used to safely create formatted strings in memory (avoid buffer overflow).


7. Best Practices & Rules of Thumb

  1. Prefer fgets() + sscanf() or strtol()/strtod() for parsing user input.
    scanf() is fine for controlled, simple inputs but has pitfalls.

  2. Always check the return value of scanf()/sscanf()/fgets() to detect errors or EOF.

  3. Avoid gets() — it is removed from the standard because it is unsafe.

  4. Always limit string input with width specifiers (%49s) if you use scanf("%s", ...).

  5. Use snprintf() rather than sprintf() to avoid buffer overflows.

  6. Use fflush(stdout) if you need to ensure prompt output in some interactive programs (e.g., before scanf() on some platforms). Do not use fflush(stdin) — it is undefined behavior.

  7. Use correct format specifiers and length modifiers — a mismatch is undefined behaviour and a common source of bugs.

  8. When comparing floats, use a tolerance (epsilon) rather than ==.

  9. Prefer inttypes.h macros for portable printing of fixed-width integers.

  10. Keep input validation strict — always validate the parsed values (range, format).


8. Common Pitfalls & How to Avoid Them

  • Buffer overflow with %s → use width or fgets().

  • Leftover newline after scanf() → consume with getchar() or use fgets() next.

  • Mixing scanf() and fgets() → manage leftover \n carefully.

  • Mismatched format specifiers → always match type and specifier.

  • Assuming float equals double behavior → remember promotion rules and scanf differences (%f vs %lf).

  • Using fflush(stdin) — undefined; instead read and discard input.


9. Small flow diagram (text)

Keyboard → terminal driver → program stdin buffer → parsing (scanf/fgets) → variables
printf/fprintf → format string → stdout buffer → terminal driver → screen

To flush output:

  • stdout usually line-buffered if connected to terminal; use fflush(stdout) or \n at end of line.


10. Quick Reference Cheat Sheet

  • Read a line safely: fgets(buf, sizeof buf, stdin);

  • Parse int safely: if (sscanf(buf, "%d", &x) == 1) ...

  • Print size_t: printf("%zu\n", n);

  • Print pointer: printf("%p\n", (void*)ptr);

  • Print int64_t: printf("%" PRId64 "\n", v); (#include <inttypes.h>)

  • Format float to 2 decimals: printf("%.2f\n", value);

  • Prevent overflow with scanf string: scanf("%49s", s);

  • Use snprintf() to build strings safely.

ā“

No quizzes yet

Quizzes to test your knowledge coming soon!

šŸ“š Recent Tutorials

Explore the latest tutorials added to our platform

Code copied to clipboard!