Dr. Roger Ianjamasimanana

Understanding the stdio.h header in C

By Dr. Roger Ianjamasimanana

1. What is the stdio.h header in C?

The code>stdio.h header is a C standard library header (short for “standard input/output header”) providing essential functions for handling input and output operations. These functions allow you to read from and write to files, interact with the console, and process formatted data. Below, we explore the main functions declared in stdio.h. Understanding how to use them helps you better structure your C program.


2. Types and definitions

  • FILE: A structure type representing an open file stream. Functions like fopen, fgetc, and fclose use FILE * to operate on files.
  • Macros:
    • EOF: integer value representing the End Of File or an error.
    • NULL: pointer used to indicate no valid memory address.
    • BUFSIZ: size of the file buffer used internally by the runtime.

3. Stdio.h file handling functions

stdio.h provides a variety of functions to open, read, write, and close files. Here are the most commonly used:

Functions Prototypes Descriptions
fopen

FILE *fopen(const char *filename,
            const char *mode);
Opens a file and returns a FILE * pointer. The mode can be "r", "w", "a", "rb", "wb", etc., indicating read, write, append, or binary variations.
fclose
int fclose(FILE *stream);
Closes an open file and frees the associated resources. Returns 0 on success or EOF on error.
fflush
int fflush(FILE *stream);
Flushes the output buffer of a stream. If stream is NULL, it flushes all open output streams.
freopen
FILE *freopen(const char *filename,
              const char *mode,
              FILE *stream);
Reopens an existing FILE stream with a new filename or mode, which effectively reassigns the stream to a different file or access mode.
setbuf, setvbuf
void setbuf(FILE *stream, char *buf);
int setvbuf(FILE *stream,
            char *buf,
            int mode,
            size_t size);
Control buffering for a file stream. setbuf uses a simple approach while setvbuf offers finer control (line buffering, no buffering, etc.).

4. Character and string I/O functions

These functions handle character-by-character or line-based input and output, commonly used for text files and standard console interactions.

Functions Prototypes Descriptions
fgetc, getc
int fgetc(FILE *stream);
int getc(FILE *stream);
Reads and returns the next character from the given stream or EOF on error/end-of-file. getc can be a macro version of fgetc.
fputc, putc
int fputc(int c, FILE *stream);
int putc(int c, FILE *stream);
Writes a character (c) to the specified stream. Returns the written character or EOF on error.
fgets
char *fgets(char *str,
            int n,
            FILE *stream);
Reads up to n-1 characters from stream and stores them in str, stopping at a newline or EOF. Null-terminates str if successful.
fputs
int fputs(const char *str,
          FILE *stream);
Writes a string (no newline appended) to stream. Returns a nonnegative value on success or EOF on error.
gets
char *gets(char *str);
Dangerous and deprecated. Reads from stdin into str until a newline or EOF, but provides no buffer size checks. Use fgets instead.
putchar, getchar
int putchar(int c);
int getchar(void);
Write/read a character to/from stdout/stdin. Often used for simplistic console I/O.

5. Formatted I/O functions

Formatted I/O functions allow you to read and write data in human-readable forms, supporting placeholders for various data types.

Functions Prototypes Descriptions
printf, fprintf
int printf(const char *format, ...);
int fprintf(FILE *stream,
            const char *format, ...);
Print formatted output to stdout or a specific stream using format specifiers like %d, %s, %f, etc.
scanf, fscanf
int scanf(const char *format, ...);
int fscanf(FILE *stream,
           const char *format, ...);
Read formatted data from stdin or a specified file. Match inputs against a format string and store them in provided variable addresses.
sprintf, snprintf
int sprintf(char *str,
            const char *format, ...);
int snprintf(char *str,
             size_t size,
             const char *format, ...);
Write formatted data into a string buffer. snprintf is safer since it limits the number of written bytes to size-1.
sscanf
int sscanf(const char *str,
           const char *format, ...);
Reads formatted data from a string rather than a file or console. Useful for parsing data stored in memory.

6. Binary and block I/O functions

You use these functions to read and write raw binary data or larger blocks of memory efficiently.

Function Prototype Description
fread, fwrite
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);
Read/write raw binary data. They handle nmemb elements, each of size bytes. Returns the count of items successfully read/written.
fseek, ftell, rewind
int fseek(FILE *stream,
          long offset,
          int whence);

long ftell(FILE *stream);

void rewind(FILE *stream);
Control file position indicator: move the file pointer to a specific location, obtain the current position, or reset it to the file’s start.

7. Error handling and End-of-File detection

  • feof(FILE *stream): tests if the end of the file has been reached. Typically used after a read fails to distinguish EOF from an error.
  • ferror(FILE *stream): checks if an error occurred on the stream. Returns non-zero if an error happened.
  • clearerr(FILE *stream): resets the EOF/error flags on a stream so subsequent operations can proceed.
  • perror(const char *s): prints an error message describing the last system call or library function error, often used when file operations fail.

8. Sample code: reading and writing a text file

Below is a simple example demonstrating some key functions from stdio.h. We open a file for writing, store user input, then reopen it for reading.

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    FILE *file;
    char buffer[100];

    /* Step 1: Open file in write mode */
    file = fopen("/tmp/example.txt", "w");
    if (file == NULL) {
        perror("Error opening file for writing");
        return EXIT_FAILURE;
    }

    /* Step 2: Write some text to the file */
    fprintf(file, "Hello, world!\n");
    fprintf(file, "This is a sample text file.\n");
    fclose(file);

    /* Step 3: Open the file in read mode */
    file = fopen("/tmp/example.txt", "r");
    if (file == NULL) {
        perror("Error opening file for reading");
        return EXIT_FAILURE;
    }

    /* Step 4: Read each line using fgets */
    printf("File Content:\n");
    while (fgets(buffer, sizeof(buffer), file) != NULL) {
        printf("%s", buffer);
    }

    /* Step 5: Check if an error occurred or if it's just EOF */
    if (ferror(file)) {
        perror("Error reading file");
    }
    fclose(file);

    return EXIT_SUCCESS;
}

Explanation of the code:

  • We use fopen(..., "w") to create or overwrite example-file.txt.
  • fprintf writes formatted data to the file, just like printf but with a file stream as the first argument.
  • We close the file using fclose, then reopen it in read mode ("r") to read content using fgets.
  • After reading the lines, we check with ferror if an error occurred. If not, we reached EOF normally.

9. Conclusion

The stdio.h header handles file and console I/O in C. By understandinf these functions (e.g., fopen, fclose, printf and scanf) you can handle text and binary data effectively. The stdio.h header offers versatile, well-established tools that form the backbone of many C programs.

feature-top
Readers’ comment
feature-top
Log in to add a comment
🔐 Access