CodeBlanks Logo Icon CodeBlanks

File I/O

  • C course
  • Intermediate
  • Lesson 115/116
  • 6 min

Save and load data to/from files.

Saving tasks

The fourth lesson adds saving tasks to a file and loading them back. task_save writes the linked list to a text file; task_load reads the file and rebuilds the list.

task_save opens the file for writing with fopen, writes each task's name and priority with fprintf, and closes with fclose. task_load reads name and priority with fscanf, creates a task with task_new and inserts it with task_push_front. This is the basis of persistent storage; data survives in the file even when the program exits. The code from the previous lesson is included in the starting code.

Save and load

Saving and loading work together. Saving writes each task to a file; loading reads the file and rebuilds the list. Between the two you free the list for a clean start.

Flow: save with task_save(g_list, "tasks.txt");. Free the list and set g_list = NULL;. Then reload with task_load(&g_list, "tasks.txt");. Loading uses task_push_front, so the order reverses; this is the natural behavior of a linked list. This test confirms that save and load are symmetrical; you get back what you saved.

Practice Add save and load

Write int task_save(const Task *list, const char *path); open with fopen(path, "w"), write with fprintf(f, "%s %d\n", ...), close with fclose(f). Write int task_load(Task **list, const char *path); open with fopen(path, "r"), read with fscanf(f, "%31s %d", ...), insert with task_push_front. In main add two tasks, call task_save(g_list, "tasks.txt");, free the list, call task_load(&g_list, "tasks.txt");, print the high count.

Starter code

main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct Task {
    char name[32];
    int priority;
    struct Task *next;
} Task;

Task *g_list = NULL;

Task *task_new(const char *name, int priority) {
    Task *t = malloc(sizeof(Task));
    strncpy(t->name, name, 31);
    t->name[31] = '\0';
    t->priority = priority;
    t->next = NULL;
    return t;
}

void task_push_front(Task **list, Task *t) {
    t->next = *list;
    *list = t;
}

void task_print(const Task *list) {
    const Task *cur = list;
    while (cur) {
        printf("%s: %d\n", cur->name, cur->priority);
        cur = cur->next;
    }
}

typedef int (*TaskFilter)(const Task *);

int is_high_priority(const Task *t) {
    return t->priority >= 3;
}

int task_count_if(const Task *list, TaskFilter filter) {
    int count = 0;
    const Task *cur = list;
    while (cur) {
        if (filter(cur)) count++;
        cur = cur->next;
    }
    return count;
}

// task_save fonksiyonunu yaz
// task_load fonksiyonunu yaz
// main'de kaydet, serbest bırak, yükle ve yazdır

int main(void) {
    task_push_front(&g_list, task_new("Ödeme", 1));
    task_push_front(&g_list, task_new("Paketle", 3));
    task_print(g_list);
    int high = task_count_if(g_list, is_high_priority);
    printf("yüksek: %d\n", high);
    return 0;
}

Sample solution

main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct Task {
    char name[32];
    int priority;
    struct Task *next;
} Task;

Task *g_list = NULL;

Task *task_new(const char *name, int priority) {
    Task *t = malloc(sizeof(Task));
    strncpy(t->name, name, 31);
    t->name[31] = '\0';
    t->priority = priority;
    t->next = NULL;
    return t;
}

void task_push_front(Task **list, Task *t) {
    t->next = *list;
    *list = t;
}

void task_print(const Task *list) {
    const Task *cur = list;
    while (cur) {
        printf("%s: %d\n", cur->name, cur->priority);
        cur = cur->next;
    }
}

typedef int (*TaskFilter)(const Task *);

int is_high_priority(const Task *t) {
    return t->priority >= 3;
}

int task_count_if(const Task *list, TaskFilter filter) {
    int count = 0;
    const Task *cur = list;
    while (cur) {
        if (filter(cur)) count++;
        cur = cur->next;
    }
    return count;
}

int task_save(const Task *list, const char *path) {
    FILE *f = fopen(path, "w");
    if (!f) return 0;
    const Task *cur = list;
    while (cur) {
        fprintf(f, "%s %d\n", cur->name, cur->priority);
        cur = cur->next;
    }
    fclose(f);
    return 1;
}

int task_load(Task **list, const char *path) {
    FILE *f = fopen(path, "r");
    if (!f) return 0;
    char name[32];
    int priority;
    while (fscanf(f, "%31s %d", name, &priority) == 2) {
        task_push_front(list, task_new(name, priority));
    }
    fclose(f);
    return 1;
}

int main(void) {
    task_push_front(&g_list, task_new("Ödeme", 1));
    task_push_front(&g_list, task_new("Paketle", 3));
    task_save(g_list, "tasks.txt");
    Task *cur = g_list;
    while (cur) { Task *n = cur->next; free(cur); cur = n; }
    g_list = NULL;
    task_load(&g_list, "tasks.txt");
    int high = task_count_if(g_list, is_high_priority);
    printf("yüksek: %d\n", high);
    return 0;
}

Expected output

yüksek: 1

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 Which function does task_save use to write to a file?

  • malloc
  • printf
  • scanf
  • fprintf Correct answer

Explanation: fprintf writes formatted output to a file stream.

2 Match the file I/O functions

Term Meaning
fopen Open file
fprintf Write to file
fscanf Read from file
fclose Close file

3 Complete the fopen call

Question
FILE *f = fopen(____, "w");
Answer
FILE *f = fopen(path, "w");

Explanation: fopen(path, "w") opens the file for writing.

All lessons in Intermediate