Тренировочные задания: Структуры и пользовательские типы

Десять задач на структуры, массивы структур, typedef, enum и union. Данные — только числа: без строк, char[] и strcmp.

Задача 1. Запись Student

Опишите структуру Student (id, course, score), считайте одну запись и выведите её.

Пример ввода:

1 2 4.5

Пример вывода:

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

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

int main(void)
{
    Student s;
    if (scanf("%d %d %lf", &s.id, &s.course, &s.score) != 3)
    {
        return 1;
    }

    printf("%d %d %.2f\n", s.id, s.course, s.score);
    return 0;
}

Задача 2. Средний балл группы

Считайте N записей в динамический массив и выведите средний score.

Пример ввода:

2
1 2 4.5
2 2 3.5

Пример вывода:

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

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

int main(void)
{
    int n;
    if (scanf("%d", &n) != 1 || n <= 0)
    {
        return 1;
    }

    Student *group = malloc((size_t)n * sizeof(*group));
    if (group == NULL)
    {
        return 1;
    }

    double sum = 0.0;
    for (int i = 0; i < n; i++)
    {
        if (scanf("%d %d %lf",
                  &group[i].id,
                  &group[i].course,
                  &group[i].score) != 3)
        {
            free(group);
            return 1;
        }
        sum += group[i].score;
    }

    printf("%.2f\n", sum / n);
    free(group);
    return 0;
}

Задача 3. Лучшая запись

Найдите запись с максимальным score.

Пример ввода:

3
1 1 4.1
2 1 4.9
3 1 4.5

Пример вывода:

2 4.90
Решение
#include <stdio.h>
#include <stdlib.h>

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

int main(void)
{
    int n;
    if (scanf("%d", &n) != 1 || n <= 0)
    {
        return 1;
    }

    Student *group = malloc((size_t)n * sizeof(*group));
    if (group == NULL)
    {
        return 1;
    }

    for (int i = 0; i < n; i++)
    {
        if (scanf("%d %d %lf",
                  &group[i].id,
                  &group[i].course,
                  &group[i].score) != 3)
        {
            free(group);
            return 1;
        }
    }

    int best = 0;
    for (int i = 1; i < n; i++)
    {
        if (group[i].score > group[best].score)
        {
            best = i;
        }
    }

    printf("%d %.2f\n", group[best].id, group[best].score);
    free(group);
    return 0;
}

Задача 4. Сортировка по score

Отсортируйте записи по убыванию score.

Пример ввода:

3
1 1 4.1
2 1 4.9
3 1 4.5

Пример вывода:

2 1 4.90
3 1 4.50
1 1 4.10
Решение
#include <stdio.h>
#include <stdlib.h>

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

int main(void)
{
    int n;
    if (scanf("%d", &n) != 1 || n <= 0)
    {
        return 1;
    }

    Student *group = malloc((size_t)n * sizeof(*group));
    if (group == NULL)
    {
        return 1;
    }

    for (int i = 0; i < n; i++)
    {
        if (scanf("%d %d %lf",
                  &group[i].id,
                  &group[i].course,
                  &group[i].score) != 3)
        {
            free(group);
            return 1;
        }
    }

    for (int i = 0; i < n - 1; i++)
    {
        for (int j = 0; j < n - 1 - i; j++)
        {
            if (group[j].score < group[j + 1].score)
            {
                Student tmp = group[j];
                group[j] = group[j + 1];
                group[j + 1] = tmp;
            }
        }
    }

    for (int i = 0; i < n; i++)
    {
        printf("%d %d %.2f\n", group[i].id, group[i].course, group[i].score);
    }

    free(group);
    return 0;
}

Задача 5. Поиск по id

Считайте N записей и id; выведите запись или -1, если её нет.

Пример ввода:

2
1 1 4.1
2 2 4.9
2

Пример вывода:

2 2 4.90
Решение
#include <stdio.h>
#include <stdlib.h>

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

int main(void)
{
    int n;
    if (scanf("%d", &n) != 1 || n <= 0)
    {
        return 1;
    }

    Student *group = malloc((size_t)n * sizeof(*group));
    if (group == NULL)
    {
        return 1;
    }

    for (int i = 0; i < n; i++)
    {
        if (scanf("%d %d %lf",
                  &group[i].id,
                  &group[i].course,
                  &group[i].score) != 3)
        {
            free(group);
            return 1;
        }
    }

    int query;
    if (scanf("%d", &query) != 1)
    {
        free(group);
        return 1;
    }

    for (int i = 0; i < n; i++)
    {
        if (group[i].id == query)
        {
            printf("%d %d %.2f\n", group[i].id, group[i].course, group[i].score);
            free(group);
            return 0;
        }
    }

    printf("-1\n");
    free(group);
    return 0;
}

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

Для каждого курса посчитайте количество записей. Выведите только непустые курсы.

Пример ввода:

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

Пример вывода:

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

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

int main(void)
{
    int n;
    if (scanf("%d", &n) != 1 || n <= 0)
    {
        return 1;
    }

    Student *group = malloc((size_t)n * sizeof(*group));
    if (group == NULL)
    {
        return 1;
    }

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

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

    free(group);
    return 0;
}

Задача 7. Следующий день

Опишите структуру Date и выведите следующий день. Учитывайте високосные годы.

Пример ввода:

28 2 2024

Пример вывода:

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

typedef struct
{
    int day;
    int month;
    int year;
} Date;

int days_in_month(int month, int year)
{
    int days[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

    if (month == 2 && (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)))
    {
        return 29;
    }
    return days[month - 1];
}

int main(void)
{
    Date d;
    if (scanf("%d %d %d", &d.day, &d.month, &d.year) != 3)
    {
        return 1;
    }

    d.day++;
    if (d.day > days_in_month(d.month, d.year))
    {
        d.day = 1;
        d.month++;
        if (d.month > 12)
        {
            d.month = 1;
            d.year++;
        }
    }

    printf("%02d.%02d.%04d\n", d.day, d.month, d.year);
    return 0;
}

Задача 8. Сложение комплексных чисел

Опишите структуру Complex и функцию сложения.

Пример ввода:

1 2
3 4

Пример вывода:

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

typedef struct
{
    double re;
    double im;
} Complex;

Complex add(Complex a, Complex b)
{
    Complex result;
    result.re = a.re + b.re;
    result.im = a.im + b.im;
    return result;
}

int main(void)
{
    Complex a, b;
    if (scanf("%lf %lf %lf %lf", &a.re, &a.im, &b.re, &b.im) != 4)
    {
        return 1;
    }

    Complex c = add(a, b);
    printf("%g + %gi\n", c.re, c.im);
    return 0;
}

Задача 9. Расстояние между точками

Опишите структуру Point и функцию расстояния. Используйте sqrt из math.h; при сборке может понадобиться -lm.

Пример ввода:

0 0
3 4

Пример вывода:

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

typedef struct
{
    double x;
    double y;
} Point;

double distance_between(Point a, Point b)
{
    double dx = a.x - b.x;
    double dy = a.y - b.y;
    return sqrt(dx * dx + dy * dy);
}

int main(void)
{
    Point a, b;
    if (scanf("%lf %lf %lf %lf", &a.x, &a.y, &b.x, &b.y) != 4)
    {
        return 1;
    }

    printf("%.2f\n", distance_between(a, b));
    return 0;
}

Задача 10. Tagged union

Опишите Value (enum + union для int/double) и выведите значения с типом: 1 — int, 2 — double.

Пример ввода:

3
1 42
2 3.14
1 -7

Пример вывода:

1 42
2 3.14
1 -7
Решение
#include <stdio.h>

typedef enum
{
    VALUE_INT = 1,
    VALUE_DOUBLE = 2
} ValueType;

typedef struct
{
    ValueType type;
    union
    {
        int i;
        double d;
    } as;
} Value;

int main(void)
{
    int n;
    if (scanf("%d", &n) != 1 || n < 0)
    {
        return 1;
    }

    for (int k = 0; k < n; k++)
    {
        int type;
        if (scanf("%d", &type) != 1)
        {
            return 1;
        }

        if (type == VALUE_INT)
        {
            int x;
            if (scanf("%d", &x) != 1)
            {
                return 1;
            }
            printf("%d %d\n", VALUE_INT, x);
        }
        else if (type == VALUE_DOUBLE)
        {
            double x;
            if (scanf("%lf", &x) != 1)
            {
                return 1;
            }
            printf("%d %.2f\n", VALUE_DOUBLE, x);
        }
        else
        {
            return 1;
        }
    }

    return 0;
}

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

—