Вывод имеет следующий вид:
16838
5758
10113
17515
31051
Выходные данные производят впечатление случайных, но давайте запустим программу снова. И вот какие результаты получены на этот раз:
16838
5758
10113
17515
31051
Числа выглядят знакомыми; в этом и заключается аспект “псевдо”. Каждый раз, когда главная программа запускается, старт происходит с одного и того же начального числа 1. Проблему можно обойти путем ввода второй функции по имени srandl(), которая позволит переустанавливать начальное число. Трюк заключается в том, чтобы сделать next статической переменной с внутренним связыванием, которая известна только функциям randl() и srandl(). (Эквивалент srandl() в библиотеке С называется srand().) Добавьте функцию srandl() в файл, содержащий randl().
В листинге 12.9 представлена модифицированная версия.
Листинг 12.9. Программа s_and г.с

504 глава 12
Обратите внимание, что next — это статическая переменная с областью видимости в пределах файла и внутренним связыванием. Это означает, что она может использоваться как randl(), так и srandl(), но не функциями в других файлах. Для тестирования этих функций применяйте драйвер из листинга 12.10.
Листинг 12.10. Драйвер г drivel. с

Снова скомпилируйте два файла и запустите программу:
Введите желаемое начальное число.
1
16838
5758
10113
17515
31051
Введите следующее начальное число (q для завершения):
513
20067
23475
8955
20841
15324
Введите следующее начальное число (q для завершения) :
q
Программа завершена.
Использование значения 1 для seed выдает те же псевдослучайные числа, что и ранее, но значение 3 для seed обеспечивает выдачу новых результатов.
НА ЗАМЕТКУ! Автоматическая переустановка начального значения
Если ваша реализация С предоставляет доступ к какой-то меняющейся величине, такой как показание системных часов, ее можно применять (возможно, с усечением) для инициализации начального числа.
Классы хранения, связывание и управление памятью 505
s Например, в ANSI С имеется функция time(), которая возвращает системное время, к Единицы измерения времени зависят от системы, однако здесь важно то, что возвращаемое значение имеет арифметический тип и меняется с течением времени. Точный тип может отличаться от системы к системе, и он получил метку time t, но можно воспользоваться приведением. Вот как выглядит базовый подход:
#include /* прототип ANSI для timet) */
srandl((unsigned int) time(O)); /* инициализация начального числа */
В общем time() принимает аргумент, который является адресом объекта типа time_t. В данном случае значение времени также сохраняется по этому адресу. В качестве аргумента можно передать нулевой указатель (0), тогда значение будет передаваться только с помощью механизма возврата из функции.
Вы можете применять тот же самый метод с функциями srand() и rand() из ANSI С. Если вы планируете использовать эти функции, включите заголовочный файл stdlib.h. Фактически теперь, когда вы увидели, каким образом в srandl() и randl() применяется статическая переменная с внутренним связыванием, вы можете также воспользоваться версиями, которые поставляет компилятор. Мы сделаем это в следующем примере.
Игра в кости
Мы собираемся эмулировать весьма популярное действие со случайным характером — игру в кости. В наиболее распространенной форме этой игры участвуют две шестигранных кости, но существуют и другие разновидности. Во многих азартных играх применяются все пять геометрически возможных костей — с 4, 6, 8, 12 и 20 гранями. Талантливые древние греки доказали, что лишь у пяти правильных тел все грани имеют одинаковую форму и размер, и эти тела являются основой для всего разнообразия костей. Можно было бы сделать кости с другим числом граней, но не все грани имели бы одинаковый размер, что не способствовало бы уравниванию шансов их выпадения.
Компьютерные вычисления не ограничиваются этими геометрическими соображениями, так что мы можем придумать электронную игральную кость, которая имеет любое количество граней. Давайте начнем с варианта с шестью гранями, после чего займемся обобщением. Нам необходимо случайное значение от 1 до 6. Тем не менее, функция rand() генерирует целое число из диапазона от 0 до RAND_MAX; значение RAND_MAX определено в stdlib.h. Обычно это INT_MAX. Следовательно, понадобятся провести ряд настроек. Ниже представлен один из подходов.
Читать дальше