Programming in C

File Management, Dynamic Memory, and Preprocessors


Concise notes on file I/O, streams, command-line arguments, dynamic memory allocation, basic linked list ideas, and preprocessor directives with short examples and debugging hints.


File Management and Streams

  • File operations: open, read, write, close using fopen, fclose, fread, fwrite, fseek, ftell.
  • Streams: standard streams stdin, stdout, stderr.
  • Command-line arguments: int main(int argc, char *argv[]), where argc is count and argv holds arguments.
  • Error handling: check return values (e.g., fopen may return NULL), use perror or strerror(errno).
  • Random access: use fseek and ftell to move and query file position for binary I/O.
File Read (simple)
FILE *fp = fopen("data.bin", "rb");
if (fp == NULL) { perror("open"); exit(1); }
char buf[128];
size_t n = fread(buf, 1, sizeof(buf), fp);
fclose(fp);
file-i-o

Command-line Arguments & Error Handling

  • Access arguments via argv[1] etc.; convert strings to numbers with atoi, strtol.
  • Always validate argc and check conversions for errors.
  • Use errno, perror and return non-zero exit code on failure.

Dynamic Memory Allocation

  • malloc: allocate uninitialized block: void *malloc(size_t size). Check for NULL.
  • calloc: allocate and zero-initialize: void *calloc(nmemb, size).
  • realloc: resize previously allocated block: void *realloc(ptr, new_size). Use carefully to avoid leaks.
  • free: release memory: free(ptr). Avoid double-free and use-after-free.
Dynamic array (simple)
int *a = malloc(n * sizeof(int));
if (a == NULL) { perror("malloc"); exit(1); }
... use a ...
free(a);
malloc-layout

Basic Idea — Linked List

  • Self-referential structure where each node points to next: struct Node { int val; struct Node *next; };.
  • Create nodes with malloc, set fields, and link via pointers; free nodes when removed.
  • Common ops: insert at head, delete node, traverse; watch for NULL checks.
Insert at head (sketch)
struct Node *n = malloc(sizeof *n);
n->val = v;
n->next = head;
head = n;
linkedlist

Preprocessor Directives

  • Macro definition: #define PI 3.14 — text substitution before compilation.
  • Macro substitution: use parentheses in macros to avoid precedence bugs: #define SQR(x) ((x)*(x)).
  • File inclusion: #include <stdio.h> or #include "file.h".
  • Conditional compilation: #ifdef, #ifndef, #if, #endif.
Macro example
#define MAX(a,b) ((a) > (b) ? (a) : (b))
int m = MAX(x, y);

Debugging Exercise

Find and fix the errors
#include <stdio.h>
#include <stdlib.h>

char *make_message() {
  char buf[64];
  snprintf(buf, sizeof(buf), "hello");
  return buf; // error: returning pointer to local stack buffer
}
Correct points
  • Do not return pointer to local buffer. Allocate with malloc or let caller provide buffer.
  • Check allocations and use free to avoid leaks.
  • Always close files with fclose even on error paths.

Programming Exercise

  • Write a program that reads a binary file of integers and prints statistics (min, max, mean) using fread.
  • Implement a simple singly linked list with insert and delete operations using dynamic memory.

Diagrams to paste: file-i-o.png, malloc-layout.png, linkedlist.png. This module includes the core points required for college exams. If you want a one-page revision sheet, say "Make Ch6 cheat sheet".