Ввод с клавиатуры в Pascal — readln и read

Создано: 30.03.2026

Любая из всех тех программ, которые мы писали до этого, при каждом запуске выдавала один и тот же результат. Это происходило потому, что исходные данные в коде всегда были одинаковыми, они были в него "вшиты". Допустим, если переменной присвоено число 10, то какие бы вычисления с ее участием не происходили в программе, все они будут иметь однозначный, предсказуемый результат.

Однако большинство компьютерных программ предполагает обработку какого-то диапазона различных данных. То есть алгоритм работы программы один и тот же, последовательность команд в ней та же, но значения переменных определяются не тогда, когда пишется код, а тогда, когда программа исполняется. Программист не знает конкретных значений переменных, он оперирует только их именами.

Тогда появляется вопрос, а откуда возьмутся значения для переменных? Данные могут поступать с клавиатуры, от генератора случайных чисел, из файла, базы данных, передаваться по сети. В этом уроке мы рассмотрим только ввод данных с клавиатуры, и как они присваиваются переменным.

В языке программирования Pascal ввод данных в программу осуществляется с помощью процедур read и readln. Они как бы обратны уже изученным нами процедурам write и writeln, с помощью которых данные выводятся.

Следует отметить, что клавиатура является стандартным устройством ввода, а монитор — стандартным устройством вывода. Стандартные — значит "работающие по-умолчанию". Это значит, что если не указано ничего иного, то программа будет считывать данные с клавиатуры, а выводить их на монитор. Вместе клавиатуру и монитор называют консолью. Таким образом консоль представляет собой стандартное устройство ввода-вывода.

Итак, пусть имеется программа, в которой над значением переменной выполняются операции, результат которых выводится на экран:

var 
    x: integer;

begin
    x := 10;

    writeln(x * x - 4 * x - 8);  // 52
    writeln(x * -1 / 3  :5:2);   // -3.33
end.

Чтобы эта программа ожидала ввода числа с клавиатуры, а получив его, присваивала переменной x, надо строку x := 10; заменить на readln(x);. Процедура readln так устроена, что не только "заберет" введенные данные, но и сама присвоит их переданной в ее скобках переменной.

Имейте в виду, что когда вы вводите данные, вы их видите на экране. Это сделано для удобства ввода. Когда программа ждет от вас ввода данных, то "зависает". При этом на экране отображается или мигает курсор.

Спишите приведенный выше код, но сделайте так, чтобы значение для переменной бралось со стандартного ввода. Выполните программу несколько раз, передавая в нее различные целые числа. Отличается ли при этом вывод на экран?

Если переменная определена как целочисленная, а вводится вещественное число или текст, то выполнение программы прервется ошибкой времени выполнения (runtime error). Эта ошибка возникает из-за того, что переменной типа integer невозможно присвоить значение типа real или string. А "времени выполнения" она потому, что такой ошибки еще нет на момент компиляции программы. С точки зрения написания кода и для компилятора программа безошибочная. Ошибка возникает только при работе программы и то не всегда. Пример некорректного ввода и "ответа" программы:

4.5
Runtime error 106 at $00000000004010BB
  $00000000004010BB
  $0000000000422F5C

В Паскале код ошибки 106 говорит, что она была вызвана неверным числовым форматом. Далее идут адреса в оперативной памяти, где ошибка произошла. Как сделать так, чтобы при неверном вводе программа аварийно не завершалась, мы узнаем в следующих уроках. Пока же запомним правило: если ожидаются данные определенного типа, надо таковые и вводить.

С другой стороны, если переменная объявлена как вещественная, то ей можно через ввод с клавиатуры передавать целое число. Оно будет преобразовано в вещественное.

Напишите программу, которая запрашивает с ввода строку и выводит ее на экран с восклицательным знаком в конце? Что будет если ввести не текст, а число? Почему не возникает ошибки?

Процедуры readln и read настолько "умные", что если им передать несколько переменных даже разного типа, они их все заполнят данными:

var 
    a, b: integer;
    f: real;
    s: string;

begin
    readln(a, b, f, s);

    writeln('Целые числа: ', a, ' и ', b);
    writeln('Дробное число: ', f:5:2);
    writeln('Строка: ', s);
end.

Примеры исполнения программы:

2  5  -0.58  Hello World  Test
Целые числа: 2 и 5
Дробное число: -0.58
Строка:   Hello World  Test
3
4
8.23
Целые числа: 3 и 4
Дробное число:  8.23
Строка:

Мы не можем в read и readln передать две строковые переменные, потому что пробел здесь — это разделитель между числами, но не строками.

Чтобы прочитать две строки, надо использовать разные вызовы readln:

var 
    s, t: string;

begin
    readln(s);
    readln(t);

    writeln('s: ', s);
    writeln('t: ', t);
end.
one two three
four five six seven eight
s: one two three
t: four five six seven eight

Когда используются разные readln, то завершителем ввода для каждого всегда является Enter. Разные вызовы read могут получать данные на одной строке.

Таким образом, при вводе данных их разделяют пробелом, табуляцией или переходом на новую строку (Enter). Данные символьного типа не разделяются или разделяются переходом на новую строку.

Существуют особенности ввода данных с помощью операторов read и readln. Если используются подряд несколько read, то вводимые данные можно разделять всеми допустимыми способами. При использовании нескольких вызовов readln каждый последующий срабатывает только после нажатия Enter. Программа ниже иллюстрирует это. Комментарии поясняют последовательность возможных действий при вводе данных.

var
    a, b, c, d: integer;

begin
    read(a); // a -> Пробел или Tab или Enter -> b
    read(b);
    writeln(a, ' ', b);

    readln(c); // c -> только Enter -> d
    readln(d);
    writeln(c, ' ', d);

    read(a, b); // a -> Пробел или Tab или Enter -> b
    writeln(a, ' ', b);

    readln(c, d); // c -> Пробел или Tab или Enter -> d
    writeln(c, ' ', d);
end.

Задания для дополнительной или самостоятельной работы:

  1. Можно ли для одной и той же переменной несколько раз вызывать read? Напишите программу, демонстрирующую ответ на этот вопрос.
  2. Что произойдет, если код предусматривает получение с ввода значения только для одной численной переменной, а человек введет две или введет число и текст?
  3. Как известно, нельзя делить на ноль. Напишите программу, которая запрашивает два числа, делит одно на другое, результат выводит на экран. Возникает ли в программе на Pascal ошибка времени выполнения, если в качестве делителя используется 0?