C Input & Output
C - Input & Output
Section titled “C - Input & Output”Input refers to providing data to a program, typically from the keyboard, files, or network connections. Output refers to presenting data from a program, usually to the screen, files, or network.
C provides a standard library (stdio.h) with functions for performing input and output (I/O) operations.
Standard I/O Streams
Section titled “Standard I/O Streams”When a C program starts, three standard I/O streams are automatically opened:
| Stream Name | File Pointer | Typical Device & Purpose |
|---|---|---|
| Standard Input | stdin | Typically connected to the keyboard. Used for reading input. |
| Standard Output | stdout | Typically connected to the screen/terminal. Used for displaying normal output. |
| Standard Error | stderr | Typically connected to the screen/terminal. Used for displaying error messages. |
These streams are represented by file pointers (FILE *), providing a consistent interface for interacting with these standard devices.
Character I/O: getchar() & putchar()
Section titled “Character I/O: getchar() & putchar()”These functions handle I/O one character at a time.
-
int getchar(void): Reads the next available character fromstdinand returns it as anint. ReturnsEOF(a special integer constant, usually -1) on end-of-file or error. -
int putchar(int c): Writes the characterc(converted tounsigned char) tostdoutand returns the character written, orEOFon error.
Example:
#include <stdio.h>
int main(void) { int c;
printf("Enter a character: "); c = getchar(); // Read one character
// Check if getchar() succeeded before using putchar() if (c != EOF) { printf("You entered: "); putchar(c); // Write the character back putchar('\n'); // Add a newline for better formatting } else { printf("\nEnd of input or error encountered.\n"); }
return 0;}When run, this program waits for input. If you type hello and press Enter, it reads only the first character ‘h’:
Enter a character: helloYou entered: hLine I/O: fgets() & puts()
Section titled “Line I/O: fgets() & puts()”These functions handle I/O one line at a time.
-
char *fgets(char *str, int size, FILE *stream): Reads a line from the specifiedstream(e.g.,stdin) into the bufferstr. It stops reading aftersize - 1characters, or when a newline character (\n) is read, or when end-of-file is reached. Crucially,fgetsis safe because it prevents buffer overflows by respecting the providedsize. It stores the newline character if read and space permits, and always null-terminates the string (\0). Returnsstron success,NULLon error or end-of-file without reading any characters. -
int puts(const char *s): Writes the stringstostdout, followed by a newline character. Returns a non-negative value on success, orEOFon error.
Important Security Note: Avoid using the legacy gets() function. It does not perform bounds checking and can easily lead to buffer overflows, a serious security vulnerability. Always use fgets() instead of gets() for reading strings.
Example using fgets and puts:
#include <stdio.h>#include <string.h> // For strcspn, if removing newline
#define BUFFER_SIZE 100
int main(void) { char str[BUFFER_SIZE];
printf("Enter a line of text: ");
// Read a line safely using fgets if (fgets(str, BUFFER_SIZE, stdin) != NULL) { // Optional: Remove the trailing newline character if fgets stored it // strcspn finds the first occurrence of any character in the reject string (here, just newline) str[strcspn(str, "\n")] = 0;
printf("You entered: "); puts(str); // puts adds its own newline } else { // Handle error or EOF printf("\nFailed to read input or reached end-of-file.\n"); }
return 0;}When run:
Enter a line of text: This is a test line.You entered: This is a test line.Formatted I/O: scanf() & printf()
Section titled “Formatted I/O: scanf() & printf()”These functions handle I/O according to specified format strings, allowing you to read and write various data types.
-
int scanf(const char *format, ...): Reads formatted input fromstdinaccording to theformatstring. Subsequent arguments are pointers to variables where the read data should be stored. Returns the number of input items successfully matched and assigned, orEOFon input failure before any conversion. -
int printf(const char *format, ...): Writes formatted output tostdoutaccording to theformatstring. Subsequent arguments are the values to be formatted and printed. Returns the number of characters printed, or a negative value on error.
The format string contains conversion specifiers (e.g., %d for int, %f for float/double, %c for char, %s for string, %zu for size_t) that determine how arguments are converted. Both functions have many formatting options.
Example:
#include <stdio.h>
#define MAX_NAME_LEN 50
int main(void) { char name[MAX_NAME_LEN]; int age; int items_read;
printf("Enter your name and age (e.g., Alice 30): ");
// Read a string (up to whitespace) and an integer // Use width limit for %s to prevent buffer overflow // Check the return value of scanf! items_read = scanf("%49s %d", name, &age); // %49s reads max 49 chars + null terminator
if (items_read == 2) { // Check if both items were successfully read printf("\nHello, %s! You are %d years old.\n", name, age); } else if (items_read == 1) { printf("\nError: Only read the name. Please enter name and age correctly.\n"); } else { // Could be EOF or matching failure printf("\nError: Failed to read input correctly.\n"); // It's good practice to clear the input buffer here if retrying input int c; while ((c = getchar()) != '\n' && c != EOF) { /* consume rest of line */ } }
return 0;}When run:
Enter your name and age (e.g., Alice 30): Bob 25
Hello, Bob! You are 25 years old.Important Notes on scanf:
-
Whitespace Sensitivity: Most format specifiers (
%d,%s,%f, etc.) automatically skip leading whitespace. However,%cdoes not skip whitespace. -
%sStops at Whitespace: The%sspecifier reads characters until it encounters any whitespace (space, tab, newline). If you need to read a full line containing spaces, usefgets. -
Security: Using
%swithout a width limit (%49sin the example) is dangerous as it can cause buffer overflows if the input is longer than the buffer. Always specify a maximum width or usefgets. -
Return Value: Always check the return value of
scanfto ensure the expected number of items were successfully read and assigned. Input might not match the format string, leading to errors if not checked. -
Input Buffer: If
scanffails to match, the problematic input often remains in the input buffer, potentially causing issues for subsequent reads. Techniques exist to clear the buffer when needed.
Best Practices for Input Handling
Section titled “Best Practices for Input Handling”-
Prefer
fgetsto read entire lines of input into a buffer first. This gives you more control and avoids manyscanfpitfalls. -
After reading a line with
fgets, you can parse the buffer usingsscanf(the string version ofscanf), which offers the same formatting capabilities but reads from a string instead ofstdin. This often leads to more robust input handling. -
Always check the return values of I/O functions (
fgets,scanf,printf,putchar,getchar, etc.) to detect errors or unexpected conditions (like end-of-file). -
Use
stderrfor printing error messages, asstdoutmight be redirected.
For detailed information on format specifiers and advanced I/O functions, consult C documentation or resources like the printf(3) and scanf(3) man pages.