Редко встретишь программу, которая решала бы только одну задачу. Среди наших
примеров нашлась только одна такая программа — самая первая, которая печатает строчку
Hello, world!
и не умеет ничего кроме этого. Обычно
программа способна решать целый класс похожих задач
в зависимости от поступивших данных.
Каким образом информация может попасть в программу извне и повлиять на её работу? Существует несколько способов.
Во-первых, с помощью файлового ввода. Настройки программы, а также данные, предназначенные для обработки, помещаются в файлы, а программа извлекает всё, что ей нужно, из этих файлов. Файловая система является важной частью операционной системы, которая, в свою очередь, служит «окружающей средой» по отношению к работающей программе. Если и возможна программа, которая никак не взаимодействует с окружающей средой, то такая программа уж точно совершенно бесполезна. Типичная программа обменивается информацией со своей средой, и, как правило, изменяет среду — такое изменение как раз и является предназначением программы. Файловый ввод можно понимать и в более широком смысле: в качестве «файлов» как источников информации могут выступать и соединения по сети, и клавиатура компьютера. Файловый ввод становится совершенно незаменимым способом передачи данных в программу, если
Во-вторых, программа может получить информацию через переменные окружения. Мы обсудим этот способ в главе 37. ««Жизнь» Джона Конвея» в разделе «Определение размера экрана». Возможности, предоставляемые переменными окружения, очень ограничены, что, впрочем, не уменьшает важность переменных окружения.
Наконец, ещё одна возможность — передача данных через командную строку при запуске программы. Любой текст, который мы напишем в командной строке после имени программы, эта программа способна получить и использовать по своему разумению. Имеется ограничение на объём текста, но во многих случаях достичь разрешённого предела сложно.
Сравним разные способы передачи данных в программу на примере воображаемой программы sum.pl, которая находит сумму некоторого количества чисел. Пусть, для начала, программа побуждает пользователя вводить числа с клавиатуры. Чтобы пользователь не терялся, программа подсказывает, что делать, выдавая так называемые приглашения ввода:
%
./sum.pl
введите число>
13
введите число>
11
введите число>
-3
введите число>
8.25
введите число>
0
введите число>
2.3
введите число>
сумма: 31.55
В этом примере после каждого приглашения пользователь вводит число и нажимает Enter. Чтобы обозначить, что числа закончились, вводится пустая строка (сразу нажимается Enter).
Теперь представьте себе процесс отладки такой программы (а программа редко получается с первого раза). Каждый раз, проверяя программу, придётся вводить много чисел. Даже если программа работает правильно, пользователь (это, как правило, человек, которому свойственно ошибаться) может ввести вместо числа какую-нибудь ерунду вместо числа или нажать Enter раньше времени:
%
./sum.pl
введите число>
13
введите число>
11
введите число>
-3
введите число>
8.25
введите число>
0op
тьфу ты! это не число! запускайте программу заново!
Всё это делает процесс отладки и использования программы чрезвычайно мучительным для программиста и для пользователя. К этому замечанию следует добавить, что текст диалогов стоит приспособить для пользователей, говорящих на других языках в зависимости от региональных настроек (эти настройки, кстати, программа может узнать через упоминавшиеся переменные окружения):
%
./sum.pl
enter a number>
13
enter a number>
11
enter a number>
-3
enter a number>
8.25
enter a number>
0op
damn it! this isn’t a number! re-run the program!
Никто не захочет из-за маленькой опечатки заново вводить длинный список чисел.
Гораздо удобнее разместить список чисел (если он не слишком велик) прямо в командной строке:
%
./sum.pl 13 11 -3 8.25 0 2.3
31.55
%
./sum.pl 13 11 -3 8.25 0op 2.3
ошибка: «0op»: это не число!
Если пользователь ошибся, он легко повторит только что запущенную командную строку (нажав клавишу Up), исправит её, и запустит снова. Программист, отыскивая ошибку в программе точно так же будет повторять предыдущую команду запуска после каждого исправления, пока не добьётся от программы правильного поведения.
Способ передачи чисел в программу через командную строку не годится, если список чисел очень велик. В этом случае можно предусмотреть ввод чисел из файла. Если программа будет рассчитывать, что числа находятся в каком-то конкретном файле, она получится недостаточно гибкой. Вместо этого через командную строку передадим имя файла. Чтобы программа не приняла это имя за неправильно заданное число, которое мы хотим сложить с другими числами, укажем имя после так называемого ключа (обычно это буква после дефиса):
%
./sum.pl -f numbers.dat
31.55
Тогда в файл numbers.dat
можно поместить хоть миллион
чисел (скажем, по одному в строке), и программа их просуммирует. В командную
строку миллион чисел включить не получится — командная оболочка этого не
позволит.
Мы будем избегать, когда это возможно, интерактивных программ, то есть таких, которые нуждаются в присутствии пользователя и в общении с ним во время исполнения программы. Нужно иметь в виду, что многие программы запускаются не через командную строку, а в автоматическом режиме другими программами, которые готовят строку запуска, добавляя в неё нужные параметры и ключи. Диалоги в таком режиме полностью исключены.
Впрочем, среди наших примеров всё-таки встретятся интерактивные программы, в которых без взаимодействия с пользователем не обойтись. Они обсуждаются в главах 11. «Угадывание чисел» и 40. «Тетрис».