Динамическое распределение памяти в языке С
Задание 3
- Рассчитайте минимальные и максимальные значения сформированных случайных чисел.
- Размерность массива случайных чисел примите за 100*Х, где Х – номер компьютера, за которым выполняется лабораторная работа. Вывод на экран дисплея не производите.
- С учетом пункта 2 рассчитайте среднее значение сформированного массива. Сравните с теоретическим значением.
- Напишите программу расчета массива нормально распределенных случайных чисел, для которых среднее значение отличается от теоретического математического ожидания на заданную величину (вводимую с клавиатуры). Первый вариант – за счет увеличения размерности массива, второй вариант – за счет увеличения числа прогона программы с заданной величиной размерности массива.
Пример 4. Напишите программу заполнения одномерного символьного массива заданным числом (вводимого с клавиатуры) символов с добавлением символа восклицательного знака "!" в конце массива символов.
Для решения примера используем функции динамического распределения памяти malloc() и realloc().
Программная реализация примера базируется на программе из [9.1].
Программный код решения примера:
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
int n, m;
char *ptr;
// Размерность символьного массива
printf("\n Enter a dimention of character array: ");
scanf_s("%d", &n);
_flushall();
// Выделение памяти для заданного объема символов
ptr = (char *)malloc((n+1)*sizeof(char));
if (!ptr) {
printf("\n\t 1st Error! ");
printf("\n\n Press any key: ");
_getch(); return -1; }
// Ввод строки символов
printf(" Enter a character array of no more than %d characters: ", n);
gets_s(ptr, n+1);
// Число символов в строке
m = strlen(ptr);
printf("\n Start line:\n");
printf(" %s\n", ptr);
// Перераспределение памяти
ptr = (char *)realloc(ptr, (m+2)*sizeof(char));
if (!ptr) {
printf("\n\t 2nd Error! ");
printf("\n\n Press any key: ");
_getch(); return -1; }
// Присоединение к массиву символов еще одного символа
strcat_s(ptr, m+2, "!");
printf("\n Start line and character \"%c\":\n", '!');
printf(" %s\n", ptr);
// Освобождение памяти
free (ptr);
printf("\n\n Press any key: ");
_getch();
return 0; }В функции malloc() размер требуемой памяти делается с запасом на символ окончания строки, т.е. '\0'. Аналогично сделан запас количества символов для функции realloc(), так как функция strlen() возвращает количество символов в строке без нулевого символа. Функции gets_s() и strcat_s() определены в MS Visual Studio. В них предусматривается включение размерности символьных массивов, чего нет в стандартных функциях gets(), strcat() языка С.
Возможный результат выполнения программы показан на рис. 9.4.
Размерность выделяемой памяти превышает число вводимых символов. Поэтому функция realloc() уменьшает размерность выделяемой памяти.
Задание 4
- Проверьте размерность итогового массива символов.
- Выведите сформированный массив символов в обратном порядке.
- Введите свою фамилию и свое имя через пробел. Подсчитайте количество вводимых символов и введите это число.
- Осуществите вывод массива символов с дополнительным случайным символом без применения функции strcat().
Пример 5. Напишите программу транспонирования матрицы, размерности которой (количество строк и количество столбцов) вводятся с клавиатуры, а элементы – вещественные случайные числа, распределенные по равномерному закону из интервала [0;15].
По определению транспонированная матрица – это матрица
, полученная из исходной матрицы
заменой строк на столбцы.
Программный код решения примера:
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <time.h>
#include <locale.h>
int main (void) {
int i, j, n, m;
double *A_ptr, *B_buf;
// Для рандомизации псевдослучайных чисел
srand((unsigned)time(NULL));
setlocale(LC_ALL, "Russian");
printf("\n Введите размерность матрицы - \n число строк и число столбцов через пробел: ");
scanf_s("%d%d", &n, &m);
A_ptr = (double *) calloc((n*m),sizeof(double));
B_buf = (double *) calloc((n*m),sizeof(double));
for (i = 0; i < n*m; ++i)
A_ptr[i] = 15.0*rand()/RAND_MAX;
setlocale(LC_NUMERIC, "English");
printf("\n Исходная матрица:\n");
for (i = 0; i < n; ++i) { printf("\n");
for(j = 0; j < m; ++j)
printf(" %8.4f", A_ptr[i*m+j]); }
// Основной фрагмент транспонирования
for (i = 0; i < n; ++i)
for (j = 0; j < m; ++j)
B_buf[j*n+i] = A_ptr[i*m+j];
printf("\n\n Транспонированная матрица:\n");
for (j = 0; j < m; ++j) {
printf("\n");
for(i = 0; i < n; ++i)
printf(" %8.4f", B_buf[j*n+i]); }
// Освобождение выделенной памяти
free(A_ptr); free(B_buf);
printf("\n\n Press any key: ");
_getch(); return 0; }В программе использованы библиотечные функции для установки русских шрифтов setlocale(LC_ALL, "Russian") и вывода элементов матрицы с плавающей точкой: setlocale(LC_NUMERIC, "English"). Для этих функций подключен заголовочный файл locale.h.
Возможный результат работы программы показан на рис. 9.5.
Задание 5
- Подсчитайте число итераций циклов, необходимых для транспонирования.
- Выполните двойное транспонирование исходной матрицы. Выведите результат на консоль первого и второго транспонирования.
- Выполните решение примера с применением указателей на указатели.
- Заполните исходную матрицу натуральными числами начиная с номера компьютера, за которым выполняется лабораторная работа.
Контрольные вопросы
- Что такое динамическая память?
- Какие средства языка С используются для хранения данных с динамическим выделением памяти компьютера?
- Какие основные библиотечные функции языка С используются для динамического распределения памяти?
- Какое различие в действии функций malloc() и calloc()?
- Как осуществляется перераспределение динамической памяти?
- Для каких типов данных возможно динамическое распределение памяти?

