Лекция: Общее знакомство
Вид материала | Лекция |
СодержаниеРаспределение памяти Функция calloc( ) Функция получения случайных чисел |
- Жизнь Клима Самгина (общее знакомство) утопия, 27.58kb.
- Лекция Общее знакомство с организмом человека Человек и окружающая среда, 81.53kb.
- Цель дисциплины, 24.29kb.
- Тема пояснения, 99.97kb.
- Общее знакомство с цветковыми растениями, 1421.63kb.
- Образовательные программы : дошкольное общее образование, начальное общее образование,, 549.09kb.
- План «курсы трейдинга» День 1 Вступительная лекция Знакомство. Базовые понятие о трейдинге., 56.64kb.
- Ю. Б. Введение в общую психологию. М., 2000. Лекция, 413.91kb.
- Урок литературы по рассказу саши черного "в лунную ночь", 85.66kb.
- Лекция со студентами асс, 33.36kb.
Распределение памяти
Функция malloc( )
Пусть нам нужно распределить память для запоминания используемых данных. Некоторые ячейки памяти распределяются автоматически, Например, мы можем объявить
char str[ ] = "Символьная строка";
Будет выделена память, достаточная для запоминания этой строки. Мы можем запросить определенный объем памяти:
int mas[150];
Это описание выделяет 150 ячеек памяти, каждая из которых предназначена для запоминания целого значения. Но язык Си позволяет нам распределять дополнительную память во время работы программы. Предположим, мы пишем программу и не знаем, сколько данных нам придется вводить. Тогда можно выделить нужный нам, по нашему предположению, объем памяти, а затем, если понадобится, потребовать еще. Чтобы сделать это, нужно использовать функцию malloc( ). И без указателей тут не обойтись!
/* добавляем память, если необходимо */
#include
#define STOP " " /* сигнал прекращения ввода */
#define BLOCK 100 /*байты памяти */
#define LIM 40 /*предельная длина вводимой строки*/
#define MAX 50 /*максимальное число вводимых строк */
#define TIME 20000 /* большая задержка времени */
main ( )
{
char store[BLOCK]; /* исходный блок памяти*/
char symph[LIM]; /* приемник вводимых строк*/
char *end; /* указывает на конец памяти */
char *starts[MAX]; /* указывает на начала строк*/
int index = 0; /*количество вводимых строк */
int count; /* счетчик*/
сhar malloc( ); / * распределитель памяти */
start[o]=store;
end=starts[0]+BLOCK-1;
puts("Введите строки по одной");
puts("в начале нажимайте клавишу[ввод ]");
puts("Начинайте!.");
while(strcmp(fgets(symph,LIM,stdin),STOP) != 0
&& index
if(strlen(symph)>end - starts[index]) {
/* действия при недостатке памяти для
запоминания вводимых данных*/
puts("подождите, программа попробует найти
дополнительную память");
starts[index]=malloc(BLOCK);
end=starts[index]+BLOCK- 1;
for(count=0; count
puts("память найдена");
}
strcpy(starts[index],symph);
starts[index+1]=starts[index] + strlen(symph)+1;
if(++index
printf("Строка: %d. продолжайте.\n", index);
}
puts("Вывод программы");
for(count=0; count
puts(starts[count]);
}
Давайте посмотрим, что делает функция malloc( ). Она берет аргумент в виде целого без знака, которое представляет количество требуемых байтов памяти. Так, malloc(BLOCK) требует 100 байт. Функция возвращает указатель на тип char в начало нового блока памяти. Мы использовали описание
char *malloc( );
чтобы предупредить компилятор, что malloc( ) возвращает указатель на тип char. Поэтому мы присвоили значение этого указателя элементу массива starts[index] при помощи оператора
starts[index]=malloc(BLOCK);
Предположим, что мы хотим работать с памятью типа int, а не char. Mожете и здесь использовать malloc( ). Вот как это делается:
char malloc( );
/* по-прежнему описываем как указатель на char */
int *newmem; newmem = (int)malloc(100);
/* используем операцию приведения типа */
Снова требуется 100 байт. Операция приведения типа преобразует значение, возвращенное указателем на тип char, в указатель на тип int. Если в системе int. занимает два байта памяти, это значит, что 100 байт можно использовать для запоминания 50 целых чисел.
^
Функция calloc( )
Другую возможность распределения памяти дает нам применение функции calloc( ).
char *calloc( ); long *newmem;
newmem=(long *) calloc(100,sizeof(long));
Функция calloc( ) возвращает указатель на char. Нужно использовать оператор приведения типа, если вы хотите запомнить другой тип. calloc( ) имеет два аргумента, и оба они должны быть целыми без знака. Первый аргумент содержит количество требуемых ячеек памяти. Второй аргумент - размер каждой ячейки в байтах. Функция calloc( ) обнуляет содержимое всего блока. Ваша библиотека языка Си возможно представляет несколько других функций управления памятью, вы можете исследовать их самостоятельно!
16. Лекция: Функции в примерах
^
Функция получения случайных чисел
Сейчас мы покажем генератор псевдослучайных чисел. Это означает, что фактическая последовательность чисел предсказуема, но они разбросаны довольно равномерно в пределах возможного диапазона значений.
Схема начинает с числа, называемого "зерно". Она использует его для создания нового числа, которое становится новым зерном. Затем новое зерно можно использовать для создания более нового зерна и т.д. Чтобы эта схема работала, функция случайных чисел должна помнить зерно, которое она использовала при последнем вызове. Отметим, здесь нужно использовать статическую переменную!
/* Первая версия функции rand( )*/
rand( )
{
static int randx = 1;
randx = (randx * 25173 + 13849)%65536;
/* магическая формула */
return(randx);
}
Статическая переменная randx начинает со значения 1 и изменяется при помощи магической формулы каждый раз при вызове функции. Результатом в нашей системе является число, находящееся в диапазоне -32768 до 32767. Системы с разной длиной переменной типа int будут давать различные результаты.
Проверим работу функции при помощи этого простого драйвера:
/*драйвер 1 функции rand( ) */
main( )
{
int count;
for(count = 1; count <= 5; count++)
printf(" %d\n",rand( ));
}
Получим результат:
-26514
-4449
20196
-20531
3882
Эта последовательность чисел выглядит довольно случайной. Запустим драйвер еще раз. Теперь имеем
-26514
-4449
20196
-20531
3882
Получилось абсолютно то же самое. Это и есть псевдоэффект. Каждый раз, когда работает основная программа, мы начинаем с одного и того же значения зерна, равного 1. Можно обойти эту проблему, введя вторую функцию srand( ), которая позволяет вновь устанавливать зерно в начальное значение. Хитрость заключается в том, чтобы сделать randx внешней статической переменной, известной только функциям rand( ) и srand( ). Эти две функции нужно хранить в своем собственном файле и компилировать этот файл отдельно. Вот модификатор программы:
/* Файл для rand( ) и srand( ) */
static int randx = 1;
rand( )
{
randx = (randx * 25173 + 13849) % 65536;
return(randx);
}
srand(x)
unsigned x;
{
randx = x;
}
Используем другой драйвер:
/* драйвер 2 функции rand( ) */
main( )
{
int count;
int seed;
printf(" Введите свое значение зерна.\n");
scanf("%d", & seed);
srand(seed);
/* установите зерно в начальное значение */
for(count = 1; count <= 5; count++)
printf("%\n",rand( ));
}
Программа проработала один раз:
Введите свое значение зерна.
1
-26514
-4449
20196
-20531
3882
Используя значение 1 для переменной seed, получаем те же значения, что и прежде. Введем значение 2 и посмотрим, что получится:
2
23832
20241
-1858
-30417
-16204
Мы получили другую последовательность чисел.