YREA-SLS/docs/io_ref.md

352 lines
9.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
Title: C Terminal I/O Reference
Prev:
Next:
---
*This was generated by ChatGPT as a reference to assist in development.*
# C99 Terminal I/O Reference
A concise, practical reference for terminal (stdin/stdout/stderr) and file I/O in **C99**. Includes common functions, behavior notes, examples, and safe-usage tips.
---
## Table of contents
1. Overview
2. Streams and `FILE *`
3. Opening and closing streams
4. Formatted I/O (`printf`/`scanf` families)
5. Format specifiers and `inttypes.h`
6. Character I/O
7. Line and block I/O (`fgets`, `fputs`, `fread`, `fwrite`)
8. Buffering and `setvbuf` / `fflush`
9. File positioning (`fseek`, `ftell`, `rewind`)
10. Error handling (`feof`, `ferror`, `clearerr`, `perror`)
11. Temporary files
12. Tips for safe and portable terminal I/O
13. Examples
14. POSIX terminal control (note)
---
## 1. Overview
Standard C99 defines the `<stdio.h>` interface for input/output. Its oriented around *streams* (`FILE *`) and provides both formatted and unformatted operations. C99 also introduced `<inttypes.h>` (and `<stdint.h>`) for precise integer types and format macros.
The standard I/O streams preopened by the implementation are:
* `stdin` — standard input (usually the keyboard/pipe)
* `stdout` — standard output (usually the terminal/pipe)
* `stderr` — standard error (usually the terminal, unbuffered)
`stdout` is usually line-buffered when connected to a terminal and fully buffered when redirected to a file.
---
## 2. Streams and `FILE *`
`FILE` is an opaque type representing an I/O stream. Use pointers to `FILE` returned by `fopen`, or the standard `stdin`/`stdout`/`stderr`.
Common operations: read/write, reposition, flush, close, and check errors.
---
## 3. Opening and closing streams
```c
#include <stdio.h>
FILE *fopen(const char *pathname, const char *mode);
int fclose(FILE *stream);
```
`mode` examples:
* `"r"` — read (file must exist)
* `"w"` — write (truncate/create)
* `"a"` — append (create if needed)
* `"r+"` — read/update
* `"w+"` — read/update (truncate/create)
* Add `b` for binary: `"rb"`, `"wb"` (on POSIX `b` is ignored but required for portability to Windows)
Always check for `NULL` from `fopen` and nonzero return from `fclose`.
---
## 4. Formatted I/O (`printf`/`scanf` families)
**Output (formatted)**
```c
int printf(const char *format, ...);
int fprintf(FILE *stream, const char *format, ...);
int snprintf(char *str, size_t size, const char *format, ...);
int vprintf(const char *format, va_list ap);
```
Return value: number of characters written (excluding terminating `\0` for `snprintf`) or a negative value on error.
**Input (formatted)**
```c
int scanf(const char *format, ...);
int fscanf(FILE *stream, const char *format, ...);
int sscanf(const char *str, const char *format, ...);
```
`scanf`-style functions parse input according to `format`. They are error-prone for untrusted input — prefer `fgets` + `sscanf` or manual parsing.
**Important:** Always limit field widths for `%s` and others when using `scanf` to avoid buffer overflow: `%99s` for a 100-byte buffer.
---
## 5. Format specifiers and `inttypes.h`
Common specifiers:
* `%d``int`
* `%i``int` (auto-detects base)
* `%u``unsigned int`
* `%ld``long int`
* `%lld``long long int`
* `%zu``size_t`
* `%f``float` (promoted to `double` in `printf`/`scanf` variadic calls — use `%f` with `double` in `printf`; `scanf` expects pointer to `float` for `%f`)
* `%lf``double` for `scanf` (in `printf` `%f` and `%lf` are equivalent)
* `%Lf``long double`
* `%c``char` (or `int` in `printf`), for `scanf` expects `char *`
* `%s` — NUL-terminated string
* `%p` — pointer
* `%n` — write number of characters printed so far into `int *`
For fixed-width integer types introduced in C99, use `inttypes.h` macros
```c
#include <inttypes.h>
int32_t i32;
printf("%" PRId32 "\n", i32);
```
Common macros: `PRId32`, `PRIu64`, `PRIxPTR`, etc.
---
## 6. Character I/O
```c
int getchar(void);
int putchar(int ch);
int ungetc(int ch, FILE *stream);
int fgetc(FILE *stream);
int fputc(int ch, FILE *stream);
```
* `getchar()` is equivalent to `fgetc(stdin)`.
* Return values for `fgetc`/`getchar`: next character as an unsigned char cast to `int`, or `EOF` on end-of-file or error.
* `ungetc` pushes a character back onto the stream (one character is guaranteed).
---
## 7. Line and block I/O
**Line-based**
```c
char *fgets(char *s, int size, FILE *stream);
int fputs(const char *s, FILE *stream);
```
* `fgets` reads up to `size-1` characters or until newline; the resulting string includes the newline if present and is NUL-terminated. Returns `NULL` on EOF or error.
* Use `fgets` to safely read lines from `stdin` (avoid `gets`).
**Block-based (binary)**
```c
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
```
* Returns number of elements read/written; check against `nmemb` to detect short reads/writes.
---
## 8. Buffering and `setvbuf` / `fflush`
Buffering modes:
* Fully buffered — data collected until buffer fills (default for files).
* Line buffered — buffer flushed on newline (default for interactive `stdout`).
* Unbuffered — no buffering (default for `stderr`).
Control buffering:
```c
int setvbuf(FILE *stream, char *buf, int mode, size_t size);
int setbuf(FILE *stream, char *buf); // simpler wrapper
int fflush(FILE *stream); // flush output buffer
```
`mode` constants: `_IOFBF` (full), `_IOLBF` (line), `_IONBF` (none).
Call `fflush(stdout)` to ensure output is written (useful before `scanf` or when using `fork`).
---
## 9. File positioning
```c
int fseek(FILE *stream, long offset, int whence);
long ftell(FILE *stream);
void rewind(FILE *stream);
```
* `whence`: `SEEK_SET`, `SEEK_CUR`, `SEEK_END`.
* For binary files larger than `LONG_MAX`, POSIX defines `fseeko`/`ftello` with `off_t` (not in C99 standard).
---
## 10. Error handling
```c
int feof(FILE *stream);
int ferror(FILE *stream);
void clearerr(FILE *stream);
```
* `ferror` indicates if an error occurred on the stream.
* `perror(const char *s)` prints a human-readable error message based on `errno`.
Example pattern:
```c
if (ferror(fp)) {
perror("file read");
}
```
---
## 11. Temporary files
```c
FILE *tmpfile(void); // create and open a temporary binary file (removed on close)
char *tmpnam(char *s); // generate a filename
```
`tmpnam` is unsafe for race conditions; prefer `tmpfile` or platform-specific secure alternatives.
---
## 12. Tips for safe and portable terminal I/O
* Prefer `fgets` + `sscanf` (or manual parsing) over `scanf` to avoid buffer overflows and ambiguous input parsing.
* When printing into buffers, use `snprintf` to avoid overflows and to detect truncation (it returns the number of characters that would have been written).
* Validate `fread`/`fwrite` return values.
* Check `fopen` for `NULL` and call `perror`/inspect `errno` on failure.
* Use `fflush(stdout)` if mixing output with `fork()` or before expecting input on interactive programs.
* Use `setvbuf` if your program has special performance needs.
* For cross-platform portability, include `b` in mode strings for binary files (Windows requires it).
* Use `inttypes.h` macros for printing fixed-width integers.
---
## 13. Examples
### Read lines from stdin safely
```c
#include <stdio.h>
#include <string.h>
int main(void) {
char buf[256];
while (fgets(buf, sizeof buf, stdin)) {
// strip newline
size_t len = strlen(buf);
if (len && buf[len - 1] == '\n') buf[len - 1] = '\0';
printf("line: '%s'\n", buf);
}
return 0;
}
```
### Read integers robustly using `fgets` + `sscanf`
```c
#include <stdio.h>
int main(void) {
char line[128];
long value;
while (fgets(line, sizeof line, stdin)) {
if (sscanf(line, "%ld", &value) == 1) {
printf("got: %ld\n", value);
} else {
fprintf(stderr, "invalid input: %s", line);
}
}
}
```
### Write/read binary struct to file
```c
#include <stdio.h>
#include <stdlib.h>
struct pair { int a; double b; };
int main(void) {
struct pair p = {42, 3.14159};
FILE *f = fopen("data.bin", "wb");
if (!f) { perror("fopen"); return 1; }
if (fwrite(&p, sizeof p, 1, f) != 1) { perror("fwrite"); }
fclose(f);
f = fopen("data.bin", "rb");
struct pair q;
if (!f) { perror("fopen"); return 1; }
if (fread(&q, sizeof q, 1, f) != 1) { perror("fread"); }
fclose(f);
printf("read: %d %f\n", q.a, q.b);
}
```
---
## 14. POSIX terminal control (note)
C99 does **not** standardize low-level terminal control (raw mode, disabling echo, key-by-key input). On POSIX systems you can use `<termios.h>` and `tcgetattr`/`tcsetattr`. On Windows you use console APIs (`GetConsoleMode` / `SetConsoleMode`). These are outside the C standard and require conditional compilation and platform-specific code.
Example POSIX-only header include:
```c
#ifdef __unix__
#include <termios.h>
#endif
```
---
## Quick reference: common functions
* `fopen`, `fclose` — open/close file
* `fread`, `fwrite` — block I/O
* `fgets`, `fputs` — line I/O
* `printf`, `fprintf`, `snprintf` — formatted output
* `scanf`, `fscanf`, `sscanf` — formatted input
* `fgetc`, `fputc`, `getchar`, `putchar` — character I/O
* `fflush`, `setvbuf` — flushing and buffering
* `fseek`, `ftell`, `rewind` — positioning
* `feof`, `ferror`, `clearerr`, `perror` — error handling
* `tmpfile`, `tmpnam` — temporary files
---
If you want, I can:
* Add a printable PDF / cheat-sheet version.
* Expand the POSIX terminal control section with a `termios` example.
* Create a one-page cheat-sheet for printing and scanning format specifiers.