Динамическое распределение памяти в языке С
Задание 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()?
- Как осуществляется перераспределение динамической памяти?
- Для каких типов данных возможно динамическое распределение памяти?