Тренировочные задания: Текстовые файлы

Пять задач на fopen, fscanf, fprintf и fclose. Данные — только числа.

Задача 1. Сумма чисел из файла

В input.txt записано N, затем N целых чисел. Найдите сумму и запишите её в output.txt.

Пример input.txt:

4
1 2 3 4

Пример output.txt:

10
Решение
#include <stdio.h>

int main(void)
{
    FILE *in = fopen("input.txt", "r");
    if (in == NULL)
    {
        perror("input.txt");
        return 1;
    }

    int n;
    if (fscanf(in, "%d", &n) != 1 || n < 0)
    {
        fclose(in);
        return 1;
    }

    int sum = 0;
    for (int i = 0; i < n; i++)
    {
        int x;
        if (fscanf(in, "%d", &x) != 1)
        {
            fclose(in);
            return 1;
        }
        sum += x;
    }
    fclose(in);

    FILE *out = fopen("output.txt", "w");
    if (out == NULL)
    {
        return 1;
    }

    fprintf(out, "%d\n", sum);
    fclose(out);
    return 0;
}

Задача 2. Количество записей по курсам

В input.txt записано N, затем N строк id course score. Запишите в output.txt количество записей для каждого непустого курса.

Пример input.txt:

4
1 1 4.1
2 2 4.9
3 1 4.5
4 3 4.0

Пример output.txt:

1: 2
2: 1
3: 1
Решение
#include <stdio.h>

int main(void)
{
    FILE *in = fopen("input.txt", "r");
    if (in == NULL)
    {
        return 1;
    }

    int n;
    if (fscanf(in, "%d", &n) != 1 || n < 0)
    {
        fclose(in);
        return 1;
    }

    int count[7] = { 0 };
    for (int i = 0; i < n; i++)
    {
        int id, course;
        double score;
        if (fscanf(in, "%d %d %lf", &id, &course, &score) != 3)
        {
            fclose(in);
            return 1;
        }
        if (course >= 1 && course <= 6)
        {
            count[course]++;
        }
    }
    fclose(in);

    FILE *out = fopen("output.txt", "w");
    if (out == NULL)
    {
        return 1;
    }

    for (int c = 1; c <= 6; c++)
    {
        if (count[c] > 0)
        {
            fprintf(out, "%d: %d\n", c, count[c]);
        }
    }
    fclose(out);
    return 0;
}

Задача 3. Запись списка в файл

Считайте N и N записей id course score, сохраните их в односвязный список и запишите в output.txt в обратном порядке.

Пример input.txt:

2
1 1 4.0
2 2 3.5

Пример output.txt:

2 2 3.50
1 1 4.00
Решение
#include <stdio.h>
#include <stdlib.h>

typedef struct
{
    int id;
    int course;
    double score;
} Student;

typedef struct Node
{
    Student data;
    struct Node *next;
} Node;

int main(void)
{
    FILE *in = fopen("input.txt", "r");
    if (in == NULL)
    {
        return 1;
    }

    int n;
    if (fscanf(in, "%d", &n) != 1 || n < 0)
    {
        fclose(in);
        return 1;
    }

    Node *head = NULL;
    for (int i = 0; i < n; i++)
    {
        Student s;
        if (fscanf(in, "%d %d %lf", &s.id, &s.course, &s.score) != 3)
        {
            /* освободить список */
            fclose(in);
            return 1;
        }

        Node *node = malloc(sizeof(*node));
        if (node == NULL)
        {
            /* освободить список */
            fclose(in);
            return 1;
        }
        node->data = s;
        node->next = head;
        head = node;
    }
    fclose(in);

    FILE *out = fopen("output.txt", "w");
    if (out == NULL)
    {
        /* освободить список */
        return 1;
    }

    for (Node *p = head; p != NULL; p = p->next)
    {
        fprintf(out, "%d %d %.2f\n", p->data.id, p->data.course, p->data.score);
    }
    fclose(out);

    while (head != NULL)
    {
        Node *next = head->next;
        free(head);
        head = next;
    }
    return 0;
}

Задача 4. Копирование файла через список

Считайте все числа из input.txt в список, затем запишите их в output.txt в исходном порядке. Первое число — количество.

Пример input.txt:

3
10 20 30

Пример output.txt:

10 20 30
Решение
#include <stdio.h>
#include <stdlib.h>

typedef struct Node
{
    int value;
    struct Node *next;
} Node;

int main(void)
{
    FILE *in = fopen("input.txt", "r");
    if (in == NULL)
    {
        return 1;
    }

    int n;
    if (fscanf(in, "%d", &n) != 1 || n < 0)
    {
        fclose(in);
        return 1;
    }

    Node *head = NULL;
    Node *tail = NULL;
    for (int i = 0; i < n; i++)
    {
        int x;
        if (fscanf(in, "%d", &x) != 1)
        {
            fclose(in);
            return 1;
        }

        Node *node = malloc(sizeof(*node));
        if (node == NULL)
        {
            fclose(in);
            return 1;
        }
        node->value = x;
        node->next = NULL;

        if (tail == NULL)
        {
            head = tail = node;
        }
        else
        {
            tail->next = node;
            tail = node;
        }
    }
    fclose(in);

    FILE *out = fopen("output.txt", "w");
    if (out == NULL)
    {
        return 1;
    }

    for (Node *p = head; p != NULL; p = p->next)
    {
        fprintf(out, "%d%c", p->value, p->next != NULL ? ' ' : '\n');
    }
    fclose(out);

    while (head != NULL)
    {
        Node *next = head->next;
        free(head);
        head = next;
    }
    return 0;
}

Задача 5. Ошибка открытия файла

Напишите программу, которая пытается открыть input.txt, и при ошибке выводит сообщение в stderr и завершается с ненулевым кодом. При успехе — читает N и N чисел, пишет их сумму в output.txt.

Пример input.txt:

3
1 2 3

Пример output.txt:

6
Решение
#include <stdio.h>

int main(void)
{
    FILE *in = fopen("input.txt", "r");
    if (in == NULL)
    {
        perror("input.txt");
        return 1;
    }

    int n;
    if (fscanf(in, "%d", &n) != 1 || n < 0)
    {
        fclose(in);
        return 1;
    }

    int sum = 0;
    for (int i = 0; i < n; i++)
    {
        int x;
        if (fscanf(in, "%d", &x) != 1)
        {
            fclose(in);
            return 1;
        }
        sum += x;
    }
    fclose(in);

    FILE *out = fopen("output.txt", "w");
    if (out == NULL)
    {
        return 1;
    }
    fprintf(out, "%d\n", sum);
    fclose(out);
    return 0;
}

Подтверждение

—