1. Получить случайное число но модулю 6. Это даст целое число из диапазона от 0 до 5.
2. Добавить к нему 1. Новое число находится в диапазоне от 1 до 6.
3. Для обобщения этого алгоритма просто замените 6 в первом шаге количеством граней.
Описанные идеи реализованы в следующем коде:
#include /* для rand() */ int rollem(int sides)
{
int roll;
roll = rand() % sides + 1;
return roll;
}
506 глава 12
Давайте немного расширим возможности и сделаем так, чтобы функция позволяла бросать произвольное количество костей и возвращала общее число очков. Это реализовано в листинге 12.11.
Листинг 12.11. Файл dicerol1.c

В этом файле предпринято несколько действий. Во-первых, rollem() сделана функцией, закрытой для файла. Она выступает в качестве вспомогательной функции для roll_n_dice(). Во-вторых, для демонстрации работы внешнего связывания в файле объявлена внешняя переменная по имени roll count, которая отслуживает количество вызовов функции rollem(). Пример несколько надуман, но он показывает, как работают внешние переменные.
В-третьих, файл содержит следующий оператор:
#include "diceroll.h"
В случае использования стандартных библиотечных функций, таких как rand(), вы включаете стандартный заголовочный файл (stdlib.h для rand()) вместо объявления функции. Причина в том, что такой заголовочный файл уже содержит корректное объявление. Мы эмулируем этот подход, предоставляя заголовочный файл diceroll.h для применения функции roll_n_dice(). Заключение имени файла в двойные кавычки, а не в угловые скобки, указывает компилятору на необходимость
Классы хранения, связывание и управление памятью 507
поиска этого файла локально, а не в стандартных местоположениях, которые используются для хранения стандартных заголовочных файлов. Смысл выражения “поиска локально” зависит от реализации. Распространенные интерпретации предполагают помещение заголовочного файла в тот же каталог или папку, где находится исходный код или файл проекта (если ваш компилятор имеет делос ним). Содержимое заголовочного файла приведено в листинге 12.12.
Листинг 12.12. Файл diceroll.li

Данный заголовочный файл содержит прототипы функций и объявление extern. Поскольку dicer oil. с включает этот заголовочный файл, diceroll.c в действительности содержит два объявления переменной roll_count:
extern int roll_count; //из заголовочного файла
int roll_count =0; //из файла исходного кода
Можно иметь только одно определяющее объявление переменной. Однако объявление с ключевым словом extern является ссылочным, и таких объявлений может быть столько, сколько пожелаете.
Программа, в которой применяется функция roll_n_dice(), должна включать указанный заголовочный файл. Это не только предоставляет прототип функции roll_n_dice(), но также делает доступной переменную roll count в программе. Все сказанное иллюстрируется в листинге 12.13.
Листинг 12.13. Файл manydice.c


Глава 12
Скомпилируйте файл с кодом из листинга 12.13 вместе с файлом, содержащим код из листинга 12.11. Для простоты поместите файлы с исходным кодом из листингов 12.11, 12.12 и 12.13 в одну и ту же папку или каталог. Запустите результирующую программу. Вывод должен иметь примерно такой вид:
Введите количество граней кости или 0 для завершения программы.
6
Сколько костей?
2
Вы бросали 12 раз(а), используя 2 кости с 6 гранями.
Сколько граней? Для прекращения введите 0.
6
Сколько костей?
2
Вы бросали 4 раз(а), используя 2 кости с 6 гранями.
Сколько граней? Для прекращения введите 0.
6
Сколько костей?
2
Вы бросали 5 раз (а), используя 2 кости с 6 гранями.
Сколько граней? Для прекращения введите 0.
О
Функция rollemO была вызвана 6 раз(а) .
Пусть удача не покидает вас!
Из-за того, что в программе используется функция srand() для рандомизации начального случайного числа, скорее всего, вы не получите один и тот же вывод при том же самом входном значении. Обратите внимание, что функция main() в manydice.c имеет доступ к переменной roll_count, определенной в diceroll.c.
Читать дальше