Процедуры ввода информации (с клавиатуры.
Есть две процедуры ввода информации на Паскале: ReadLn и Read.
Для ReadLn существует 2 варианта: со списком параметров и без списка
переменная1, переменная2, переменная3, … |
ReadLn;
ReadLn (список ввода);
Read (список ввода);
Список параметров для процедуры ввода будем называть списком ввода.
Список ввода может состоять только из имен переменных (имя переменной в программе является синонимом адреса переменной). Эти переменные могут быть только одного из следующих типов: целый, вещественный, строковый и символьный (массивы, записи и множества м.б. введены лишь поэлементно).
Выполнение процедур ввода Read и ReadLn начинается с того, что программа переходит в состояние ожидания ввода. Из этого состояния программа выйдет только тогда, когда самая правая в списке ввода переменная получит значение. Значения переменные из списка ввода получают из т.н. входного потока.
На вход процедур Read и ReadLn данные (из входного потока) поступают только после нажатия клавиши “Ввод” (Enter) на клавиатуре. В этом случае к потоку символов, который уже введен до нажатия клавиши “Ввод”, добавляются два символа с кодами #13 и #10. Символ с кодом #13 часто называют “Возвратом каретки” (ВК или CR). При попытке вывода символа на экран курсор на экране установился в начало текущей строки. Символ с кодом #10 («Перевод строки» = LF) относится (также как и символ с кодом #13) к множеству пустых символов. При попытке вывода его на экран курсор устанавливается на следующей строке в текущей позиции. После нажатия клавиши "Ввод" процедура ввода начинает интерпретацию введенного. То, что введено, представляет собой входной поток для процедуры ввода.
#13 CR LF
#10 изображает данную пару символов с кодами #13 и #10.
Интерпретация входного потока зависит от того, какие переменные находятся в списке ввода. Поэтому рассмотрим интерпретацию входного потока для некоторых сочетаний типов.
разделители |
Значение1 Р Значение2 Р .Значение3 Р …
Ul iJVBtne6iY3omVSnPVJW+qxjkC40tCv9oT7EYuWz8EI4qk1zRGXBnFobRxE3vYGflIzY1hV1P3YM BCXqg8bqLLM8D3MQjbx4i+UlcO2prz1Mc4SqqKfktN340+zsLMiux5eyKIc2t1jRVkaxn1md+WPr xhqcxyzMxrUdo55/ButfAAAA//8DAFBLAwQUAAYACAAAACEA0j8Odd4AAAAKAQAADwAAAGRycy9k b3ducmV2LnhtbEyPwU7DMBBE70j8g7VI3KhTN4ogxKkQqEgc2/TCzYmXJBCvo9hpA1/PcqLH0Yxm 3hTbxQ3ihFPoPWlYrxIQSI23PbUajtXu7h5EiIasGTyhhm8MsC2vrwqTW3+mPZ4OsRVcQiE3GroY x1zK0HToTFj5EYm9Dz85E1lOrbSTOXO5G6RKkkw60xMvdGbE5w6br8PsNNS9OpqfffWauIfdJr4t 1ef8/qL17c3y9Agi4hL/w/CHz+hQMlPtZ7JBDKyzjL9EDSrdgOBAlqb8pWZHrRXIspCXF8pfAAAA //8DAFBLAQItABQABgAIAAAAIQC2gziS/gAAAOEBAAATAAAAAAAAAAAAAAAAAAAAAABbQ29udGVu dF9UeXBlc10ueG1sUEsBAi0AFAAGAAgAAAAhADj9If/WAAAAlAEAAAsAAAAAAAAAAAAAAAAALwEA AF9yZWxzLy5yZWxzUEsBAi0AFAAGAAgAAAAhANozgXcwAgAAVAQAAA4AAAAAAAAAAAAAAAAALgIA AGRycy9lMm9Eb2MueG1sUEsBAi0AFAAGAAgAAAAhANI/DnXeAAAACgEAAA8AAAAAAAAAAAAAAAAA igQAAGRycy9kb3ducmV2LnhtbFBLBQYAAAAABAAEAPMAAACVBQAAAAA= " o:allowincell="f">
Поля (последовательности символов), интерпретируемые как константы целого или вещественного типов |
Процесс интерпретации входного потока производится следующим образом. Вначале рассматривается самая первая (левая) переменная из списка ввода. Для нее начиная с самого первого символа во входном потоке просматриваются все символы до первого разделителя. Особенностью процедур ввода в Паскале является то, что преобразования типа значения к типу переменной при вводе не производится (бесформатный ввод). Поэтому делается попытка интерпретировать последовательность символов из входного потока как значения (константы) того типа, который имеет первая переменная из списка ввода. Такая попытка будет удачной, если символы входного потока образуют константу, записанную по правилам для констант нужного нам типа.
Например, для рассматриваемого случая входной поток будет интерпретирован следующим образом:
разделитель (пробел) |
a, b: byte;
begin 12 3.4 ------------ изображение входного потока
разделитель (конец строки) |
end. a b
При попытке присваивания (в процессе интерпретации) переменной b (целого типа) значения 3.4 (вещественная константа) будет получено сообщение об ошибке ввода. Программа аварийно завершится, поскольку 3.4 не является правильной константой целого типа.
Если попытка интерпретации текущей последовательности символов из входного потока как значения текущей переменной из списка ввода закончилась удачно (успешно), то текущая переменная из списка ввода получает соответствующее значение, происходит перемещение в списке ввода на следующую переменную. Во входном потоке также происходит перемещение на начало последовательности символов, расположенной справа от последнего найденного разделителя до следующего разделителя. После этого производится попытка интерпретации последовательности символов между двумя разделителями как значения текущей переменной из списка ввода. Если такая попытка будет удачной, то текущая переменная получает значение и осуществляется переход к следующей переменной из списка ввода. Так продолжается до тех пор, пока не закончится список ввода.
Примечание. Если входной поток исчерпан раньше, чем количество переменных в списке ввода, то программа перейдет (или останется) в состояние ожидания ввода (без упоминания вас об этом).
Исходя из сказанного, оператор ввода (процедуру ввода) можно рассматривать как форму оператора присваивания. При этом левую часть оператора (операторов) составляют переменные из списка ввода , а в правую часть входят константы из соответствующих полей из входного потока.
Если в списке ввода находятся переменные символьного типа, то в отличие от случая для переменных целого и вещественного типов, во входном потоке для переменных символьного типа нет разделителей. То есть входной поток для переменных символьного типа рассматривается как поток символов, в котором (из которого) для каждой переменной из списка ввода выбирается один символ.
ПРИМЕР:
Var
a,
b,
c,
d, 1 2 3 4 входной поток
e,
f, g: char;
begin
read ( a , b , c , d , e , f , g );
Для заданного входного потока переменные с a по f получат следующие значения, при этом пробел рассматривается не как разделитель во входном потоке, а как его информационная часть:
a = ‘1’
b = ‘2’;
с = ’ ’
d = ’3’
e = ’4’
f = #13
g = #10
Следует обратить внимание на то, что во входном потоке для переменной символьного типа апострофы не задаются. Каждый апостроф во входном потоке будет рассматриваться как отдельный символ.
Для переменной строкового типа интерпретация производится следующим образом.
а) если Список ввода состоит только из единственной переменной – строкового типа - то входной поток рассматривается как одна строка;
б) если переменная строкового типа в списке ввода соседствует с переменными других типов, то из входного потока для строковой переменной берется последовательность символов, начиная с позиции, следующей за последним обработанным разделителем до конца строки (но не включая признак - символ конца строки).
ПРИМЕР 1.
12 34 |
a = 12; b = ‘34’; c = ‘’; |
a:integer,
b, c: string;
begin
read (a,b);
read(c); для переменной c
end.
Значение переменных a и b получатся таким, какие и ожидались. Переменная c получит указанное значение (пустая строка), поскольку что при вводе значений строкового типа с использованием процедуры Read никогда не происходит во входном потоке переход через символ конца строки (т. е. через символ с кодом #13). В данном случае после ввода значений переменной b текущий указатель во входном потоке установился не на начало следующей строки во входном потоке, а на символ с кодом #13. Поэтому значение следующей переменной (с ) будет начинаться с этого символа (с кодом #13 ) и на нем же и заканчиваться. Но, так как символ с кодом #13 в строку-результат не включается, то в строку c попадет 0 значащих символов.
Вывод: никогда не следует пользоваться для считывания последовательности строк процедурой Read. Надо использовать процедуру ReadLn.
Действие ReadLn отличается от действия Read следующим:
- после достижения конца входного потока происходит переход к началу следующего входного потока,
- после достижения конца списка ввода оставшаяся часть входного потока пропускается и осуществляется переход через символ конца строки к началу следующего входного потока.
Таким образом, если в ПРИМЕРЕ 1 заменить Read на ReadLn, то переменные получат следующие значения:
а = 12, b = ’34’, c = ’5678’.
Один и тот же входной поток для переменных разных типов интерпретируется по разному:
Var
c1,
c2, Пусть входной поток имеет вид:
c3,
c4: char; 1234
i: word;
s: string; Тогда переменные получат следующие значения:
begin
read(c1,c2,c3,c4); c1 = '1' c2 = '2' c3 = '3' c4 = '4'
или i = 1234
read(i); s = '1234'
или
read(s);
end.
Существует следующая особенность использования процедуры ReadLn, которую не следует забывать. Эта особенность проявляется при вводе значений символьного, целого и вещественного типов.
Пусть входной поток имеет вид: |
1 2 3 4 5 6 |
a,
b,
c,
d:byte; это будет пропущено (исчерпан список ввода)
begin
readln (a,b);
readln (c,d);
Для той программы переменные a и b получают значения, которые ожидаются (а = 1, b = 2). Возникает вопрос, получат ли переменные c и d значения 3 и 4? Особенностью использования процедуры readln, при работе с не строковыми переменными, является то, что после исчерпания в readln списка ввода, оставшаяся часть входного потока для нее пропускается. В данном случае, после считывания значения переменной b будет достигнут конец списка ввода для этой процедуры, и остаток текущего входного потока будет пропущен. После чего переменные c и d получат значения, которые вы введете в следующий входной поток.
9.3 Процедуры вывода в ТР.
Writeln;
Writeln(список вывода);
Write(список вывода);
Выражение1, Выражение2, Выражение3, …..
Число цифр после точки
или Выражение [: L[: D]] -------------------- Полный формат
Полная ширина поля под значение
или Выражение : L ------------------- Сокращенный формат
Две процедуры имеются в TP для вывода данных writeln и write.
Поговорим вначале о write. В этой процедуре параметры образуют список, называемый списком вывода. Рассмотрим различия в использовании процедур ввода и вывода.
Первое отличие процедур выводаот процедур ввода состоит в том, что в списке вывода могут быть использованы не 4 типа значений, а 5: символьные, строковые, целые, вещественные, и булевские (логические). Причем так же, как и при вводе, здесь не производится преобразование типа выводимого выражения (бесформатный вывод) .
Второе отличие в том, что в списке вывода размещаются не только переменные, а в общем случае - выражения (т.е. допускаются и константы и вызовы функций). Т.о. список вывода - это список выражений.
При этом надо различать: write('x'); и write(x); |
a,b,c:byte;
d: char;
begin
read(a, b, c);
read(‘c’); - нельзя!
read(1,2,3,a+b); - нельзя! вывод символа 'x' вывод значения
Write(1,2,3,a+b); - верно! переменной x
End.
Третье отличие состоит в том, что каждый элемент списка вывода может снабжаться т.н. форматом вывода. Формат вывода образуется в общем случае из 2-х полей :поле l и поле d, разделенных двоеточием. Поле l задает минимальную ширину поля (в символах), в котором должно быть размещено значение того выражения, для которого этот формат приписан. Поле d задает количество знаков после точки для вещественного значения выражения. Отсюда следует, что полный формат можно задавать только для вывода вещественного значения (в формате с фиксированной точкой). Для всех прочих вы можете задавать значение с указанием в формате только поля l.
Замечание: если вы задаете из формата вывода из формата вывода только одно поле, то подразумевается, что вы задали поле l.
Если ширина поля больше количества символов, реально необходимых для вывода значения, то значение выводится в поле шириной l со смещением его вправо так, что слева это значение дополняется необходимым числом пробелов.
Var
c: char; На экране получится следующее:
a |
c := 'a';
write ('a':6);
end. текущая позиция в строке (до начала вывода)
Если ширина поля l меньше, чем количество символов, реально необходимых для вывода значений, то значение l игнорируется и выводится на экране столько символов, сколько необходимо для вывода значения. На экране получится:
s: string;
begin
s:='1234' текущая позиция в строке (до начала вывода)
write (s:1);
end.
Четвертое отличие процедуры вывода от процедуры ввода в том, что процедура вывода выводит информацию на экран безо всяких разделителей (между выводимыми полями данных).
Var
a,
b, На экране получится:
begin
a:='1';
b:='2';
c:='3'; текущая позиция в строке (до начала вывода)
write(a, b, c,);
end.
Вывод: Если вы хотите, чтобы выводимые значения чем - то разделялись на экране (т.е. воспринимались как отдельные значения), то делайте это сами (указывайте для каждого выводимого значения ширину больше, чем нужно. Например, если в примере выше написать write(a:3, b:3, c:3); то на экране будет выведено как: 1 2 3).
При выводе целых чисел знак "-" отображает знак "-", а знак "+" не печатается (вместо него даже пробел не отображается). Так, что для данного примера получится следующая картина:
(для целых чисел)
Var
a,
b,
begin
a:=1;
b:=2; текущая позиция в строке (до начала вывода)
c:=3;
write(a, b, c,);
end.
Наибольшие сложности на TP обычно вызывает вывод вещественных значений.
Формат представления вещественного значения при выводе его в форме с плавающей точкой:
Знак числа точка
{+/-}Ц.ЦЦЦ E {+/-}ЦЦЦ
знак порядка порядок
дробная часть
обязательная цифра <>0
(нормализация)
Особенностью вывода чисел с плавающей точкой является то, что эти числа при выводе нормализуются,чтобы в целой части оказывалась цифра, отличная от нуля. Следовательно, если и в программе встречается вызов вида write(0.25), то на экране получится
2.50000000000000000E-001 --- всего 22 позиции на экране
Видно, что при выводе на экран знак "+" заменяется на пробел, знак "-" печатается.
Формат представления значения при выводе его в формате с фиксированной точкой:
до нужной ширины поля для отрицат. чисел
[пробелы][ /- ]Ц.[цифры]
для положит. чисел дробная часть
не менее одной цифры
В общее количество выводимых символов надо включать: число символов дробной части, точка, одна цифра в целой части и знак.
Теперь обещанные правила:
if (l задана) and (d задано) and (d >= 0)
then
begin
if (d > 15)
write(111.111:1:1); выведет на экран 111.1 |
d := 15;
if (d = 0)
then
дробная часть не выводится;
if (l < чем нужно для представления значения)
then
l := столько, сколько минимально нужно для представления значения ;
вывод значения в формате с ФТ
write(111.111:1); выведет на экран 1.1E+002 |
else { либо l или d не задано, либо d задано, но d < 0}
if (l задана) and (d пропущено) or (d < 0)
then
if (l < чем нужно для представления значения)
then
begin
write(111.111); выведет на экран 1.111111000000000E+002 9 нулей |
d :=1;
end
else { l пропущено (и d тоже, естественно)}
begin
l := 22 ;
d :=15;
end
вывод значения в формате с ПТ (в соответствии с указанными выше l и d)
При выводе значений булевского типа на экране выводятся слова: true или false.
Вызов процедуры writeln без списка вывода
Writeln;
производит следующие действия: в файл Output записывается пустая строка, включающая только признак конца строки (EOLN=#10#13), что при выводе на экран приводит к тому, что курсор на экране перескакивает на начало следующей строки. Исходя из этого, выполнения процедуры writeln со списком вывода выполняется как бы в два этапа:
1-й этап: write(список вывода);
2-й этап: writeln; (без списка вывода).
Замечание1: При указании формата вывода отрицательным может быть не только значение d, но и значение l. Когда указывается l<0 , то значение выводится в поле шириной l с выравниванием влево, а l = столько, сколько нужно для представления значения на экране.
Замечание2: В процедурах вывода write и writeln для полей формата можно использовать не только константы, но и переменные. (l и d могут быть константами или переменными). Это можно использовать при выводе на экран графиков функций.
Замечание3:если в процессе вывода информация как бы переползает за 80-ю позицию (правой границы экрана), то в этом случае не производится скроллинг вправо т.е. выводимая информация начинает выводится с начала следующей строки.
Когда выводимая информация перелезает за нижнюю границу экрана, т.е. за 25-ю строку экрана, то производится скроллинг вверх, т.е. вся ранее выделенная информация как бы смещается вверх на одну строку, освобождая строку снизу.
10. Вычисление по формулам (продолжение)
Дата добавления: 2016-05-28; просмотров: 2793;