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 tostdout. -
scanf()ā formatted input fromstdin.
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
formatstring 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 (avoidsprintf()because it can overflow).
Basic examples:
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:
Useful specifiers (common):
-
%d/%iā signed int -
%uā unsigned int -
%ld,%lldā long, long long -
%hd,%hhdā short, signed char -
%f,%Fā double (note:floatpromoted todouble) -
%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 printingsizeofresults) -
Use
<inttypes.h>macros forint32_t,int64_t:PRId32,PRIu64etc:
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,stdoutfor normal output. -
Use
%zuforsize_t,%pfor 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()parsesstdinaccording to theformatand stores the results into the provided addresses (you pass pointers). -
You must pass addresses for non-array variables (use
&), but arrays (likechar s[20]) decay to pointers so you pass the array name.
Basic example:
Why scanf() can be dangerous / pitfalls:
-
%sreads 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()withfgets()/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 withsscanf()orstrtol()/strtod()/strtok()/ custom parsing. -
fgets()prevents buffer overflow and gives you control over validation.
Example: safe input with fgets + sscanf
Using field width in scanf to prevent overflow:
-
For
char name[50]use%49s -
For strings with spaces use:
fgets()orscanf("%49[^\n]", name)but the latter still tricky
Handling characters and whitespace:
-
%creads 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:
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:
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ā signedint -
%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_tmacros in<inttypes.h>
-
Floating point formats:
-
%f/%Fā decimal notation -
%e/%Eā scientific notation (exponent) -
%g/%Gā use%for%ewhichever is shorter, strips trailing zeros -
%Lfālong double
Character and string:
-
%cā single char (passintorcharpromoted toint) -
%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:
-
printfpromotesfloattodouble, so%fexpectsdouble. -
For
scanf,%fexpects pointer tofloat,%lfexpects pointer todouble. (This difference is important!) -
Use format macros in
<inttypes.h>such asPRId64forint64_twhen portability is required:
5. Practical Examples & Patterns
Example 1 ā Basic input & output
Example 2 ā Avoiding scanf overflow (use width)
Example 3 ā Reading full line (with spaces)
Example 4 ā Format building with snprintf
6. Use Cases
-
printf()used for: user messages, debug printing, formatted reports, logging to files (viafprintf()). -
scanf()used for: small quick demos and controlled input; preferfgets()for real-world user input. -
fgets()+sscanf()orstrtol()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
-
Prefer
fgets()+sscanf()orstrtol()/strtod()for parsing user input.
scanf()is fine for controlled, simple inputs but has pitfalls. -
Always check the return value of
scanf()/sscanf()/fgets()to detect errors or EOF. -
Avoid
gets()ā it is removed from the standard because it is unsafe. -
Always limit string input with width specifiers (
%49s) if you usescanf("%s", ...). -
Use
snprintf()rather thansprintf()to avoid buffer overflows. -
Use
fflush(stdout)if you need to ensure prompt output in some interactive programs (e.g., beforescanf()on some platforms). Do not usefflush(stdin)ā it is undefined behavior. -
Use correct format specifiers and length modifiers ā a mismatch is undefined behaviour and a common source of bugs.
-
When comparing floats, use a tolerance (epsilon) rather than
==. -
Prefer
inttypes.hmacros for portable printing of fixed-width integers. -
Keep input validation strict ā always validate the parsed values (range, format).
8. Common Pitfalls & How to Avoid Them
-
Buffer overflow with
%sā use width orfgets(). -
Leftover newline after
scanf()ā consume withgetchar()or usefgets()next. -
Mixing
scanf()andfgets()ā manage leftover\ncarefully. -
Mismatched format specifiers ā always match type and specifier.
-
Assuming
floatequalsdoublebehavior ā remember promotion rules and scanf differences (%fvs%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:
-
stdoutusually line-buffered if connected to terminal; usefflush(stdout)or\nat 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.