C Terminal I/O Reference


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)
  15. Quick reference: common functions

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:

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

#include <stdio.h>

FILE *fopen(const char *pathname, const char *mode);
int fclose(FILE *stream);

mode examples:

Always check for NULL from fopen and nonzero return from fclose.


4. Formatted I/O (printf/scanf families)

Output (formatted)

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)

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:

For fixed-width integer types introduced in C99, use inttypes.h macros

#include <inttypes.h>
int32_t i32;
printf("%" PRId32 "\n", i32);

Common macros: PRId32, PRIu64, PRIxPTR, etc.


6. Character I/O

int getchar(void);
int putchar(int ch);
int ungetc(int ch, FILE *stream);
int fgetc(FILE *stream);
int fputc(int ch, FILE *stream);

7. Line and block I/O

Line-based

char *fgets(char *s, int size, FILE *stream);
int fputs(const char *s, FILE *stream);

Block-based (binary)

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);

8. Buffering and setvbuf / fflush

Buffering modes:

Control buffering:

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

int fseek(FILE *stream, long offset, int whence);
long ftell(FILE *stream);
void rewind(FILE *stream);

10. Error handling

int feof(FILE *stream);
int ferror(FILE *stream);
void clearerr(FILE *stream);

Example pattern:

if (ferror(fp)) {
    perror("file read");
}

11. Temporary files

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


13. Examples

Read lines from stdin safely

#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

#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

#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:

#ifdef __unix__
#include <termios.h>
#endif

15. Quick reference: common functions

Back to Top