Тренировочные задания: Указатели и динамическая память
Десять задач на передачу по указателю, арифметику указателей и динамическую память. Сначала попробуйте решить задачу без подсказки, затем откройте решение.
Задача 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;
}