Опубликован: 14.12.2010 | Уровень: для всех | Доступ: платный
Лекция 10:

Динамическое распределение памяти в языке С

< Лекция 9 || Лекция 10: 123 || Лекция 11 >

Задание 3

  1. Рассчитайте минимальные и максимальные значения сформированных случайных чисел.
  2. Размерность массива случайных чисел примите за 100*Х, где Х – номер компьютера, за которым выполняется лабораторная работа. Вывод на экран дисплея не производите.
  3. С учетом пункта 2 рассчитайте среднее значение сформированного массива. Сравните с теоретическим значением.
  4. Напишите программу расчета массива нормально распределенных случайных чисел, для которых среднее значение отличается от теоретического математического ожидания на заданную величину (вводимую с клавиатуры). Первый вариант – за счет увеличения размерности массива, второй вариант – за счет увеличения числа прогона программы с заданной величиной размерности массива.

Пример 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.

Пример определения динамического массива символов

Рис. 9.4. Пример определения динамического массива символов

Размерность выделяемой памяти превышает число вводимых символов. Поэтому функция realloc() уменьшает размерность выделяемой памяти.

Задание 4

  1. Проверьте размерность итогового массива символов.
  2. Выведите сформированный массив символов в обратном порядке.
  3. Введите свою фамилию и свое имя через пробел. Подсчитайте количество вводимых символов и введите это число.
  4. Осуществите вывод массива символов с дополнительным случайным символом без применения функции strcat().

Пример 5. Напишите программу транспонирования матрицы, размерности которой (количество строк и количество столбцов) вводятся с клавиатуры, а элементы – вещественные случайные числа, распределенные по равномерному закону из интервала [0;15].

По определению транспонированная матрица – это матрица A^T, полученная из исходной матрицы A заменой строк на столбцы.

Программный код решения примера:

#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.

Пример транспонирования матрицы

Рис. 9.5. Пример транспонирования матрицы

Задание 5

  1. Подсчитайте число итераций циклов, необходимых для транспонирования.
  2. Выполните двойное транспонирование исходной матрицы. Выведите результат на консоль первого и второго транспонирования.
  3. Выполните решение примера с применением указателей на указатели.
  4. Заполните исходную матрицу натуральными числами начиная с номера компьютера, за которым выполняется лабораторная работа.

Контрольные вопросы

  1. Что такое динамическая память?
  2. Какие средства языка С используются для хранения данных с динамическим выделением памяти компьютера?
  3. Какие основные библиотечные функции языка С используются для динамического распределения памяти?
  4. Какое различие в действии функций malloc() и calloc()?
  5. Как осуществляется перераспределение динамической памяти?
  6. Для каких типов данных возможно динамическое распределение памяти?
< Лекция 9 || Лекция 10: 123 || Лекция 11 >
Мухаммадюсуф Курбонов
Мухаммадюсуф Курбонов
Александр Соболев
Александр Соболев
Россия
Артем Полутин
Артем Полутин
Россия, Саранск