Динамическая память – это оперативная
Указатели используются для
Память, выделяемая в С функциями динамического распределения данных, находится в так называемой динамически распределяемой области памяти (heap – куча) [9.1]. Динамически распределяемая область памяти – это свободная область памяти, не используемая программой, операционной системой или другими программами. Размер этой области памяти заранее неизвестен, но, как правило, в ней достаточно памяти для размещения данных программы. Хотя размер динамически распределяемой области памяти очень большой, все же она конечна и может быть исчерпана.
Основу системы calloc(), malloc(), и free() [9.1].
Рассмотрим прототипы этих функций.
1. Функция calloc()
#include <stdlib.h> void *calloc(size_t num, size_t size);
Функция calloc() выделяет память, размер которой равен значению выражения num * size, т.е. память, достаточную для размещения массива, содержащего num объектов размером size [9.1]. Выделенная область памяти обнуляется. Функция calloc() возвращает указатель на первый байт выделенной области памяти для массива num объектов, каждый из которых имеет размер size или NULL, если запрос на память выполнить нельзя [9.2]. Если для удовлетворения запроса нет достаточного объема памяти, возвращается нулевой указатель. Перед попыткой использовать void может быть переопределен для требуемого типа, т.е. для char, int, float, double.
Пример фрагмента программного кода
double *ptr;
ptr = (double *) (calloc(10, sizeof(double)));
if (!ptr) // условие логического отрицания
{printf("Out of memory\n"); exit(1);}
В приведенном примере число 10 – это размер одномерного массива с вещественными данными (типа double ). В случае выделения памяти для двухмерного массива размера N*M строчка с функцией calloc() перепишется так:
ptr = (double *) (calloc(N*M, sizeof(double)));
При этом двухмерный массив рассматривается как аналог одномерного массива размера N*M.
Использование явного приведения типов ( double ) сделано для того, чтобы обеспечить переносимость программы, в первую очередь для обеспечения совместимости с языком программирования С++.
2. Функция malloc()
#include <stdlib.h> void *malloc(size_t size);
Функция malloc() возвращает указатель на первый байт области памяти размера size, которая была выделена из динамически распределяемой области памяти [9.3]. Если для удовлетворения запроса в динамически распределяемой области памяти нет достаточного объема памяти, возвращается нулевой указатель NULL. При этом следует иметь в виду, что попытка использовать нулевой указатель обычно приводит к полному отказу системы. Выделенная область памяти не инициализируется [9.2].
Приведем фрагмент программного кода
double *ptr;
ptr = (double *) (malloc(10*sizeof(double)));
if (!ptr) // условие логического отрицания
{ // выход за пределы памяти
printf("Out of memory. Press any key: ");
_getch();
exit(1);
}
3. Функция
#include <stdlib.h> void *realloc(void *ptr, size_t size);
В стандарте С89 функция изменяет размер блока ранее выделенной памяти, адресуемой указателем *ptr в соответствии с заданным размером size [9.1]. Значение параметра size может быть больше или меньше, чем перераспределяемая область. Функция возвращает указатель на блок памяти, поскольку не исключена необходимость перемещения этого блока. В этом случае содержимое старого блока (до size байтов) копируется в новый блок. Если новый размер памяти больше старого, дополнительное пространство не инициализируется [9.2]. Если запрос невыполним, то функция распределения памяти возвращает нулевой указатель NULL. Функция позволяет перераспределить ранее выделенную память. При этом новый размер массива может быть как меньше предыдущего, так и больше его. Если система выделит память в новом месте,
то все предыдущие значения, к которым программа обращалась по указателю *ptr, будут переписаны на новое место автоматически.
4. Функция free()
#include <stdlib.h> void free(void *ptr);
Функция free() возвращает в динамически распределяемую область памяти блок памяти, адресуемый указателем *ptr, после чего эта память становится доступной для выделения в будущем [9.1].
Вызов функции free() должен вызываться только с указателем, который был ранее получен в результате вызова одной из функций
Пример 1. Напишите программу считывания строк разной длины с использованием массива указателей, когда строки вводятся с клавиатуры, и вывода считанных строк на дисплей.
Программный код решения примера:
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#define N 79
int main (void) {
int i, m = 3;
char *str[N+1];
char *str2[] = {"st", "nd", "rd"};
for (i = 0; i < m; ++i)
str[i] = (char *) calloc((N+1), sizeof(char));
printf("\n Dynamic reading strings of different lengths\n\n");
for (i = 0; i < m; ++i) {
if (str[i] == NULL) {
printf("\n\t Error memory allocation.\n");
printf("\n Press any key: ");
_getch();
exit(1); }
printf("\t Enter %d%s string: ", i+1, str2[i]);
gets_s(str[i], sizeof(str)/sizeof(char));
}
printf("\n\t The strings are:\n");
for (i = 0; i < m; ++i)
printf("\t %s\n",str[i]);
printf("\n\n Press any key: ");
_getch();
return 0; }
calloc(). Предусматривается проверка возвращаемого значения функции calloc(), которое не должно быть нулевым указателем, т.е. NULL. В функции gets_s() используется универсальное средство ( sizeof(str)/sizeof(char) ) определения размерности массива.
Возможный результат выполнения программы показан на рис 9.1.
(рис 9.1) Пример динамического считывания строк различной длины Задание 1
calloc() примените функцию malloc() и введите (а потом выведите) свои фамилию, имя, номер группы, специальность (буквами латинского алфавита).Пример 2. Напишите программу для представления
Квадратная матрица [ $$a_{ik}$$ ] называется
В случае прямоугольной матрицы размером n $$\times$$ m переменные i и k изменяются в пределах: 1 $$\leqslant$$ i $$\leqslant$$ n, 1 $$\leqslant$$ k $$\leqslant$$ m.
Программная реализация решения примера основывается на программе из [8].
Программный код решения примера:
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <time.h>
// Макрос
#define READIn(VARIABLE) \
{printf("\n\t Enter the dimention of a square matrix (not exceeding 12):\n\t ");\
printf(#VARIABLE" = "); scanf_s("%d",VARIABLE);}
int main(void) {
int i, j, nMatr, jRow;
double **triMatr;
time_t t;
srand((unsigned int) time(t));
READIn(nMatr);
triMatr = (double **)calloc(nMatr,sizeof(double *));
for(i = 0; i < nMatr; i++)
{ jRow = (i < nMatr ? i+1 : nMatr);
triMatr[i]=(double *)calloc(jRow,sizeof(double));
for (j = 0; j < jRow; j++)
triMatr[i][j] = (12*(double)rand()/RAND_MAX);
}
printf("\n Result (triangular matrix): ");
for(i = 0; i < nMatr; i++) { printf("\n ");
jRow = (i < nMatr ? i+1 : nMatr);
for (j = 0; j < jRow; j++)
printf(" %5.2f",triMatr[i][j]);
free (triMatr[i]); }
free (triMatr);
printf("\n\n Press any key: ");
_getch();
return 0; }
В программе применена препроцессорная директива #define... – макрос для ввода размерности матрицы. Применение макросов требует к себе внимания и осторожности.
В программе применен указатель double **triMatr на массив указателей. В связи с этим определено двойное обращение к функции calloc(), с помощью которой выполняется free() для освобождения выделенной памяти.
Возможный результат выполнения программы показан на рис 9.2.
(рис 9.2) Динамическое формирование нижней треугольной матрицыЗадание 2
Пример 3. Напишите программу заполнения одномерного массива случайными числами, распределенными по стандартному нормальному закону. Размерность массива вводится с клавиатуры пользователем.
Для решения примера выберем метод Марсальи–Брея [9.3]. Его этапы:
Примечание. Нормальный закон характеризуется двумя параметрами: математическим ожиданием и среднеквадратическим отклонением (плюс корень квадратный из дисперсии), которые соответственно равны 0 и 1.
Для
где m – среднее значение заданного массива.
Программный код решения примера:
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
int main(void)
{
double *Norm, *Norm2;
double R1, R2, z1, z2, V1, V2, S;
int i, j, n;
time_t t;
srand((unsigned) time(t));
printf("\n\t Enter the size of the array: ");
scanf_s("%d", n);
// Выделение памяти для заданного массива данных
Norm = (double *)malloc(n*sizeof(double));
Norm2 = (double *)malloc(n*sizeof(double));
// Реализация алгоритма метода Марсальи-Брея
S = 1.0;
for (i = j = 0; i < n; ++i, ++j){
while (S >= 1.0) {
R1 = (double) rand()/RAND_MAX;
R2 = (double) rand()/RAND_MAX;
V1 = 2.0*R1 - 1.0;
V2 = 2.0*R2 - 1.0;
S = (V1*V1 + V2*V2);
}
z1 = V1 * sqrt(-2.0*log(S)/S);
z2 = V2 * sqrt(-2.0*log(S)/S);
Norm[i] = z1;
Norm2[j] = z2;
S = 1.0;
}
// Вывод нормально распределенных случайных чисел
printf("\n\t Normally distributed random numbers:\n");
for(i = j = 0; i < n; i++, j++)
{printf("\n\t %8.4f",Norm[i]);printf("\n\t %8.4f",Norm2[j]);}
// Освобождение памяти
free (Norm);
free (Norm2);
printf("\n\n Press any key: ");
_getch();
return 0; }
Возможный результат выполнения программы показан на рис 9.3.
(рис 9.3) Динамическое формирование нижней треугольной матрицы Задание 3
Пример 4. Напишите программу заполнения одномерного символьного массива заданным числом (вводимого с клавиатуры) символов с добавлением символа восклицательного знака "!" в конце массива символов.
Для решения примера используем функции malloc() и .
Программная реализация примера базируется на программе из [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'. Аналогично сделан запас количества символов для функции , так как функция strlen() возвращает количество символов в строке без нулевого символа. Функции gets_s() и strcat_s() определены в MS Visual Studio. В них предусматривается включение размерности символьных массивов, чего нет в стандартных функциях gets(), языка С.
Возможный результат выполнения программы показан на рис 9.4.
(рис 9.4) Пример определения динамического массива символовРазмерность выделяемой памяти превышает число вводимых символов. Поэтому функция уменьшает размерность выделяемой памяти.
Задание 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
malloc() и calloc()?Динамическая память – это оперативная
Указатели используются для
Память, выделяемая в С функциями динамического распределения данных, находится в так называемой динамически распределяемой области памяти (heap – куча) [9.1]. Динамически распределяемая область памяти – это свободная область памяти, не используемая программой, операционной системой или другими программами. Размер этой области памяти заранее неизвестен, но, как правило, в ней достаточно памяти для размещения данных программы. Хотя размер динамически распределяемой области памяти очень большой, все же она конечна и может быть исчерпана.
Основу системы calloc(), malloc(), и free() [9.1].
Рассмотрим прототипы этих функций.
1. Функция calloc()
#include <stdlib.h> void *calloc(size_t num, size_t size);
Функция calloc() выделяет память, размер которой равен значению выражения num * size, т.е. память, достаточную для размещения массива, содержащего num объектов размером size [9.1]. Выделенная область памяти обнуляется. Функция calloc() возвращает указатель на первый байт выделенной области памяти для массива num объектов, каждый из которых имеет размер size или NULL, если запрос на память выполнить нельзя [9.2]. Если для удовлетворения запроса нет достаточного объема памяти, возвращается нулевой указатель. Перед попыткой использовать void может быть переопределен для требуемого типа, т.е. для char, int, float, double.
Пример фрагмента программного кода
double *ptr;
ptr = (double *) (calloc(10, sizeof(double)));
if (!ptr) // условие логического отрицания
{printf("Out of memory\n"); exit(1);}
В приведенном примере число 10 – это размер одномерного массива с вещественными данными (типа double ). В случае выделения памяти для двухмерного массива размера N*M строчка с функцией calloc() перепишется так:
ptr = (double *) (calloc(N*M, sizeof(double)));
При этом двухмерный массив рассматривается как аналог одномерного массива размера N*M.
Использование явного приведения типов ( double ) сделано для того, чтобы обеспечить переносимость программы, в первую очередь для обеспечения совместимости с языком программирования С++.
2. Функция malloc()
#include <stdlib.h> void *malloc(size_t size);
Функция malloc() возвращает указатель на первый байт области памяти размера size, которая была выделена из динамически распределяемой области памяти [9.3]. Если для удовлетворения запроса в динамически распределяемой области памяти нет достаточного объема памяти, возвращается нулевой указатель NULL. При этом следует иметь в виду, что попытка использовать нулевой указатель обычно приводит к полному отказу системы. Выделенная область памяти не инициализируется [9.2].
Приведем фрагмент программного кода
double *ptr;
ptr = (double *) (malloc(10*sizeof(double)));
if (!ptr) // условие логического отрицания
{ // выход за пределы памяти
printf("Out of memory. Press any key: ");
_getch();
exit(1);
}
3. Функция
#include <stdlib.h> void *realloc(void *ptr, size_t size);
В стандарте С89 функция изменяет размер блока ранее выделенной памяти, адресуемой указателем *ptr в соответствии с заданным размером size [9.1]. Значение параметра size может быть больше или меньше, чем перераспределяемая область. Функция возвращает указатель на блок памяти, поскольку не исключена необходимость перемещения этого блока. В этом случае содержимое старого блока (до size байтов) копируется в новый блок. Если новый размер памяти больше старого, дополнительное пространство не инициализируется [9.2]. Если запрос невыполним, то функция распределения памяти возвращает нулевой указатель NULL. Функция позволяет перераспределить ранее выделенную память. При этом новый размер массива может быть как меньше предыдущего, так и больше его. Если система выделит память в новом месте,
то все предыдущие значения, к которым программа обращалась по указателю *ptr, будут переписаны на новое место автоматически.
4. Функция free()
#include <stdlib.h> void free(void *ptr);
Функция free() возвращает в динамически распределяемую область памяти блок памяти, адресуемый указателем *ptr, после чего эта память становится доступной для выделения в будущем [9.1].
Вызов функции free() должен вызываться только с указателем, который был ранее получен в результате вызова одной из функций
Пример 1. Напишите программу считывания строк разной длины с использованием массива указателей, когда строки вводятся с клавиатуры, и вывода считанных строк на дисплей.
Программный код решения примера:
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#define N 79
int main (void) {
int i, m = 3;
char *str[N+1];
char *str2[] = {"st", "nd", "rd"};
for (i = 0; i < m; ++i)
str[i] = (char *) calloc((N+1), sizeof(char));
printf("\n Dynamic reading strings of different lengths\n\n");
for (i = 0; i < m; ++i) {
if (str[i] == NULL) {
printf("\n\t Error memory allocation.\n");
printf("\n Press any key: ");
_getch();
exit(1); }
printf("\t Enter %d%s string: ", i+1, str2[i]);
gets_s(str[i], sizeof(str)/sizeof(char));
}
printf("\n\t The strings are:\n");
for (i = 0; i < m; ++i)
printf("\t %s\n",str[i]);
printf("\n\n Press any key: ");
_getch();
return 0; }
calloc(). Предусматривается проверка возвращаемого значения функции calloc(), которое не должно быть нулевым указателем, т.е. NULL. В функции gets_s() используется универсальное средство ( sizeof(str)/sizeof(char) ) определения размерности массива.
Возможный результат выполнения программы показан на рис 9.1.
(рис 9.1) Пример динамического считывания строк различной длиныЗадание 1
calloc() примените функцию malloc() и введите (а потом выведите) свои фамилию, имя, номер группы, специальность (буквами латинского алфавита).Пример 2. Напишите программу для представления
Квадратная матрица [ $$a_{ik}$$ ] называется
В случае прямоугольной матрицы размером n $$\times$$ m переменные i и k изменяются в пределах: 1 $$\leqslant$$ i $$\leqslant$$ n, 1 $$\leqslant$$ k $$\leqslant$$ m.
Программная реализация решения примера основывается на программе из [8].
Программный код решения примера:
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <time.h>
// Макрос
#define READIn(VARIABLE) \
{printf("\n\t Enter the dimention of a square matrix (not exceeding 12):\n\t ");\
printf(#VARIABLE" = "); scanf_s("%d",VARIABLE);}
int main(void) {
int i, j, nMatr, jRow;
double **triMatr;
time_t t;
srand((unsigned int) time(t));
READIn(nMatr);
triMatr = (double **)calloc(nMatr,sizeof(double *));
for(i = 0; i < nMatr; i++)
{ jRow = (i < nMatr ? i+1 : nMatr);
triMatr[i]=(double *)calloc(jRow,sizeof(double));
for (j = 0; j < jRow; j++)
triMatr[i][j] = (12*(double)rand()/RAND_MAX);
}
printf("\n Result (triangular matrix): ");
for(i = 0; i < nMatr; i++) { printf("\n ");
jRow = (i < nMatr ? i+1 : nMatr);
for (j = 0; j < jRow; j++)
printf(" %5.2f",triMatr[i][j]);
free (triMatr[i]); }
free (triMatr);
printf("\n\n Press any key: ");
_getch();
return 0; }
В программе применена препроцессорная директива #define... – макрос для ввода размерности матрицы. Применение макросов требует к себе внимания и осторожности.
В программе применен указатель double **triMatr на массив указателей. В связи с этим определено двойное обращение к функции calloc(), с помощью которой выполняется free() для освобождения выделенной памяти.
Возможный результат выполнения программы показан на рис 9.2.
(рис 9.2) Динамическое формирование нижней треугольной матрицыЗадание 2
Пример 3. Напишите программу заполнения одномерного массива случайными числами, распределенными по стандартному нормальному закону. Размерность массива вводится с клавиатуры пользователем.
Для решения примера выберем метод Марсальи–Брея [9.3]. Его этапы:
Примечание. Нормальный закон характеризуется двумя параметрами: математическим ожиданием и среднеквадратическим отклонением (плюс корень квадратный из дисперсии), которые соответственно равны 0 и 1.
Для
где m – среднее значение заданного массива.
Программный код решения примера:
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>
int main(void)
{
double *Norm, *Norm2;
double R1, R2, z1, z2, V1, V2, S;
int i, j, n;
time_t t;
srand((unsigned) time(t));
printf("\n\t Enter the size of the array: ");
scanf_s("%d", n);
// Выделение памяти для заданного массива данных
Norm = (double *)malloc(n*sizeof(double));
Norm2 = (double *)malloc(n*sizeof(double));
// Реализация алгоритма метода Марсальи-Брея
S = 1.0;
for (i = j = 0; i < n; ++i, ++j){
while (S >= 1.0) {
R1 = (double) rand()/RAND_MAX;
R2 = (double) rand()/RAND_MAX;
V1 = 2.0*R1 - 1.0;
V2 = 2.0*R2 - 1.0;
S = (V1*V1 + V2*V2);
}
z1 = V1 * sqrt(-2.0*log(S)/S);
z2 = V2 * sqrt(-2.0*log(S)/S);
Norm[i] = z1;
Norm2[j] = z2;
S = 1.0;
}
// Вывод нормально распределенных случайных чисел
printf("\n\t Normally distributed random numbers:\n");
for(i = j = 0; i < n; i++, j++)
{printf("\n\t %8.4f",Norm[i]);printf("\n\t %8.4f",Norm2[j]);}
// Освобождение памяти
free (Norm);
free (Norm2);
printf("\n\n Press any key: ");
_getch();
return 0; }
Возможный результат выполнения программы показан на рис 9.3.
(рис 9.3) Динамическое формирование нижней треугольной матрицыЗадание 3
Пример 4. Напишите программу заполнения одномерного символьного массива заданным числом (вводимого с клавиатуры) символов с добавлением символа восклицательного знака "!" в конце массива символов.
Для решения примера используем функции malloc() и .
Программная реализация примера базируется на программе из [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'. Аналогично сделан запас количества символов для функции , так как функция strlen() возвращает количество символов в строке без нулевого символа. Функции gets_s() и strcat_s() определены в MS Visual Studio. В них предусматривается включение размерности символьных массивов, чего нет в стандартных функциях gets(), языка С.
Возможный результат выполнения программы показан на рис 9.4.
(рис 9.4) Пример определения динамического массива символовРазмерность выделяемой памяти превышает число вводимых символов. Поэтому функция уменьшает размерность выделяемой памяти.
Задание 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
malloc() и calloc()?Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.