Added io ref
This commit is contained in:
parent
5dd0daed8a
commit
04274e14e3
|
|
@ -37,5 +37,6 @@ Next: Overview
|
||||||
- [SE 3250 Assignment Details](./se_3250_assignment_details.html)
|
- [SE 3250 Assignment Details](./se_3250_assignment_details.html)
|
||||||
- [Changed](./changes.html)
|
- [Changed](./changes.html)
|
||||||
- [Full Specification](./stack_lang_spec.html)
|
- [Full Specification](./stack_lang_spec.html)
|
||||||
|
- [C Terminal I/O Reference](./io_ref.html)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,351 @@
|
||||||
|
---
|
||||||
|
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. It’s 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.
|
||||||
Loading…
Reference in New Issue