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

Десять задач на передачу по указателю, арифметику указателей и динамическую память. Сначала попробуйте решить задачу без подсказки, затем откройте решение.

Задача 1. Обмен через указатели

Напишите функцию, меняющую два числа местами через указатели.

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

1 2

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

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

void swap(int *a, int *b)
{
    int tmp = *a;
    *a = *b;
    *b = tmp;
}

int main(void)
{
    int x, y;
    if (scanf("%d %d", &x, &y) != 2)
    {
        return 1;
    }

    swap(&x, &y);
    printf("%d %d\n", x, y);
    return 0;
}

Задача 2. Сумма массива через указатель

Найдите сумму элементов массива, обходя его через указатель.

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

4
1 2 3 4

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

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

int main(void)
{
    int n;
    int a[100];

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

    for (int i = 0; i < n; i++)
    {
        if (scanf("%d", &a[i]) != 1)
        {
            return 1;
        }
    }

    int sum = 0;
    for (int *p = a; p < a + n; p++)
    {
        sum += *p;
    }

    printf("%d\n", sum);
    return 0;
}

Задача 3. Динамический массив

Выделите память под N чисел через malloc, заполните массив и выведите сумму. Не забудьте освободить память.

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

5
1 2 3 4 5

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

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

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

    int *a = malloc((size_t)n * sizeof(*a));
    if (a == NULL)
    {
        return 1;
    }

    int sum = 0;
    for (int i = 0; i < n; i++)
    {
        if (scanf("%d", &a[i]) != 1)
        {
            free(a);
            return 1;
        }
        sum += a[i];
    }

    printf("%d\n", sum);
    free(a);
    return 0;
}

Задача 4. Расширение массива

Считайте N чисел, затем ещё одно число и добавьте его в конец через realloc.

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

3
1 2 3
4

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

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

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

    int *a = malloc((size_t)n * sizeof(*a));
    if (a == NULL)
    {
        return 1;
    }

    for (int i = 0; i < n; i++)
    {
        if (scanf("%d", &a[i]) != 1)
        {
            free(a);
            return 1;
        }
    }

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

    int *bigger = realloc(a, (size_t)(n + 1) * sizeof(*a));
    if (bigger == NULL)
    {
        free(a);
        return 1;
    }
    a = bigger;
    a[n] = extra;

    for (int i = 0; i <= n; i++)
    {
        printf("%d%c", a[i], i < n ? ' ' : '\n');
    }

    free(a);
    return 0;
}

Задача 5. Динамический массив структур

Считайте N записей Student (id, course, score) в динамический массив, выведите их и освободите память.

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

2
1 1 4.50
2 2 3.80

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

1 1 4.50
2 2 3.80
Решение
#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 && n != 0)
    {
        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; i++)
    {
        printf("%d %d %.2f\n", group[i].id, group[i].course, group[i].score);
    }

    free(group);
    return 0;
}

Задача 6. Среднее через параметр-указатель

Функция считает среднее и возвращает его через параметр-указатель, а возвращаемым значением сообщает успех.

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

4
2 4 6 8

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

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

int average(const int *a, int n, double *out)
{
    if (n <= 0)
    {
        return 0;
    }

    int sum = 0;
    for (int i = 0; i < n; i++)
    {
        sum += a[i];
    }

    *out = (double)sum / n;
    return 1;
}

int main(void)
{
    int n;
    int a[100];

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

    for (int i = 0; i < n; i++)
    {
        if (scanf("%d", &a[i]) != 1)
        {
            return 1;
        }
    }

    double avg;
    if (average(a, n, &avg))
    {
        printf("%.2f\n", avg);
    }

    return 0;
}

Задача 7. Минимум и максимум через указатели

Функция находит минимум и максимум и отдаёт их через параметры-указатели.

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

5
4 -1 7 0 7

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

min = -1, max = 7
Решение
#include <stdio.h>

void minmax(const int *a, int n, int *mn, int *mx)
{
    *mn = a[0];
    *mx = a[0];

    for (int i = 1; i < n; i++)
    {
        if (a[i] < *mn)
        {
            *mn = a[i];
        }
        if (a[i] > *mx)
        {
            *mx = a[i];
        }
    }
}

int main(void)
{
    int n;
    int a[100];

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

    for (int i = 0; i < n; i++)
    {
        if (scanf("%d", &a[i]) != 1)
        {
            return 1;
        }
    }

    int mn, mx;
    minmax(a, n, &mn, &mx);
    printf("min = %d, max = %d\n", mn, mx);
    return 0;
}

Задача 8. Копирование массива

Скопируйте массив в другой, не используя индексацию — только указатели.

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

4
9 8 7 6

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

9 8 7 6
Решение
#include <stdio.h>
#include <stdlib.h>

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

    int *a = malloc((size_t)n * sizeof(*a));
    int *b = malloc((size_t)n * sizeof(*b));
    if (a == NULL || b == NULL)
    {
        free(a);
        free(b);
        return 1;
    }

    for (int i = 0; i < n; i++)
    {
        if (scanf("%d", &a[i]) != 1)
        {
            free(a);
            free(b);
            return 1;
        }
    }

    for (int i = 0; i < n; i++)
    {
        *(b + i) = *(a + i);
    }

    for (int i = 0; i < n; i++)
    {
        printf("%d%c", *(b + i), i < n - 1 ? ' ' : '\n');
    }

    free(a);
    free(b);
    return 0;
}

Задача 9. Сумма динамической матрицы

Считайте размеры N и M, выделите матрицу int **, найдите сумму всех элементов и освободите память.

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

2 3
1 2 3
4 5 6

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

Сумма: 21
Решение
#include <stdio.h>
#include <stdlib.h>

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

    int **a = malloc((size_t)n * sizeof(*a));
    if (a == NULL)
    {
        return 1;
    }

    for (int i = 0; i < n; i++)
    {
        a[i] = malloc((size_t)m * sizeof(*a[i]));
        if (a[i] == NULL)
        {
            for (int k = 0; k < i; k++)
            {
                free(a[k]);
            }
            free(a);
            return 1;
        }
    }

    int sum = 0;
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < m; j++)
        {
            if (scanf("%d", &a[i][j]) != 1)
            {
                for (int k = 0; k < n; k++)
                {
                    free(a[k]);
                }
                free(a);
                return 1;
            }
            sum += a[i][j];
        }
    }

    printf("Сумма: %d\n", sum);

    for (int i = 0; i < n; i++)
    {
        free(a[i]);
    }
    free(a);
    return 0;
}

Задача 10. Количество положительных

Считайте N чисел в динамический массив и найдите количество положительных элементов, используя обход через указатель.

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

6
-1 2 0 3 -4 5

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

Положительных: 3
Решение
#include <stdio.h>
#include <stdlib.h>

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

    int *a = malloc((size_t)n * sizeof(*a));
    if (a == NULL)
    {
        return 1;
    }

    for (int i = 0; i < n; i++)
    {
        if (scanf("%d", &a[i]) != 1)
        {
            free(a);
            return 1;
        }
    }

    int count = 0;
    for (int *p = a; p < a + n; p++)
    {
        if (*p > 0)
        {
            count++;
        }
    }

    printf("Положительных: %d\n", count);
    free(a);
    return 0;
}

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

—