Смекни!
smekni.com

Алгоритмический язык Паскаль (стр. 14 из 31)

Наша Маша громко плачет,Уронила в речку мячик.$Тише, Машенька, не плачь,$Не утонет в речке мяч.$.

Во второй части программы с помощью функции EOLN подсчитывается число строк текста и он выводится на экран построчно, т.е. в виде:

Наша Маша громко плачет,

Уронила в речку мячик.

Тише, Машенька, не плачь,

Не утонет в речке мяч.

Итак, для записи литеры "конец строки" используется процедура WRITELN(F), где F находится в режиме записи.

T a g c d
^
окно

WRITELN(T):

T a g c d #
^
окно

Таким образом сформированный файл легко выводится на печать построчно с помощью оператора WRITE, т.к. признак конца строки в файле иницирует переход на другую строку экрана (эффект оператора WRITELN).

В режиме чтения для работы с литерой "конец строки" есть процедура READLN. По этой процедуре окно файла устанавливается на первый элемент следующей строки файла.

T d b c d # e f
^
окно

READLN(T):

T d b c d # e f
^
окно

ПРИМЕР 4. Дано некоторое стихотворение в виде текстового файла ACROSTIH. Напечатать слово, образованное первыми буквами строк стихотворения (акростих)

program SLOVO(ACROSTIH); program FORMFIL;

var L:char; T: text; var F: text; S: char;

begin begin

¦ assign(T,'ACROSTIH'); ¦ assign(F,'ACROSTIH');

reset(T); ¦ rewrite(F); read(S);

¦ while not eof(T) do ¦ while S <> '?' do

¦ ¦ begin

¦ begin ¦ while S <> '#' do

¦ ¦ begin

read(T,L); write(L); ¦ write(F,S); read(S);

¦ ¦ end;

¦ readln(T); ¦ writeln(F);read(S); end;

¦ end; ¦ close(F);

end. end.

ПОЯСНЕНИЕ. Программа FORMFIL формирует текстовый файл ACROSTIH как было показано в примере 3. В программе SLOVO файл ACROSTIH выступает как внешний. Ему соответствует файловая переменная T. Оператор READLN(T) последовательно устанавливает окно файла на начало строк текста.

Файлы, как переменные величины, могут выступать в качестве аргументов и результатов при создании функций-процедур, причем эти переменные должны быть всегда оформлены как параметры-переменные, даже если файл в процедуре играет роль аргумента.

ПРИМЕР 5. Посчитать число знаков препинания в указанном текстовом файле

function PUNCTUATION(var CHARFILE: text): integer;

var SYMBOLNOMB: integer;

SYMBOL: char;

begin

SYMBOLNOMB:=0; reset(CHARFILE);

while not eof(CHARFILE) do

begin

read(CHARFILE, SYMBOL);

if SYMBOL in ['.',',',' ',':','...] then

SYMBOLNOMB:= SYMBOLNOMB + 1

end;

PUNCTUATIОN:= SYMBOLNOMB

end.

С помощью этой функции можно теперь произвести подсчет числа вхождений знаков препинания в любой текст, представленный некоторым текстовым файлом. Рассмотрим в качестве примера фрагмент программ для файла с именем FIL:

assign(FIL,'FIL');

reset(FIL);

n:=PUNCTUATION(FIL);

close(FIL);

writeln('число знаков препинания в тексте FIL =', n).

11. ССЫЛОЧНЫЙ ТИП. ПЕРЕМЕННЫЕ С УКАЗАТЕЛЯМИ

До сих пор мы рассматривали только так называемые статические программные объекты, т.е. объекты, порожденные в процессе компиляции программы и существующие в течение всего времени ее выполнения, размеры которых (объем машинной памяти для их размещения)не изменяются. Статические объекты определяются с помощью соответствующих описаний в разделе объявлений Паскаль-программ.

НАПРИМЕР:

а) с помощью описания VAR A, B: INTEGER в программе вводятся в употребление две статические переменные с именами А и В, значениями которых будут целые числа;

б) описание VAR X: ARRAY[1..10] OF REAL oпределяет (порождает) переменную регулярного типа (массив), значением которой может быть упорядоченная последовательность из десяти вещественных чисел.

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

При трансляции Паскаль-программа превращается в программу на машинном языке (в цифровых кодах), где аналогом переменной является ячейка, а имя переменной превращается в адрес ячейки. Появление этого адреса происходит в результате работы специального оператора языка (NEW), однако его значение в большинстве случаев не используется при программировании на алгоритмических языках типа Паскаль.

Условимся считать, что адрес ячейки, которая будет хранить переменную А, есть А. Или, другими словами, А - это общее имя переменной и соответствующей ячейки памяти.

Так, например, при описании VAR A, B: INTEGER в памяти ЭВМ резервируются две ячейки, которые маркируются соответственно А и В.

Будем считать, что до начала работы программы эти ячейки пусты (на самом деле они содержат "мусор" или 0). Если теперь в программе переменным А и В присвоить значения А:= 1 и В:= 2, то эти ячейки заполнятся соответствующими данными значениями.

При описании VAR X: ARRAY[1..10] OF REAL в памяти ЭВМ резервируются подряд 10 ячеек памяти, которые идентифицируются соответственно X[1], X[2],..., X[10].

Еслитеперьсделать

FOR I:= 1 TO 10 DO READ(X[I]),

то эти ячейки заполнятся десятью числами, вводимыми с клавиатуры. При упоминании в программе имен А и В фактически указывается на содержимое ячеек А и В, т.е. на значение переменных. Так, если следует оператор WRITE(A), то печатается не А, а значение переменной А, т.е. число 2.

Из этих рассуждений следует, что для таких переменных (статических) область памяти закрепляется на все время работы программы. Поэтому ячейка с адресом А всегда будет хранить только целые числа, а группа ячеек с адресами Х[1],...,X[10] - 10 вещественных чисел. Ничто другое в эти части памяти не может быть помещено.

Однако такое постоянное распределение памяти удобно для быстродействия и хорошо, когда объемы информации невелики или заранееизвестны. На практике же бывают ситуации, когда программные объекты могут возникнуть только в процессе выполнения программы или когда такие объекты известны, но их размер определится только в процессе работы программы.

Мы уже сталкивались с такой ситуацией:

CONST N =.....

VAR X: ARRAY [1..N];

или

VAR Y: STRING [N].

В последнем случае нужно указать заранее длину, что ведет к нерациональному расходу памяти, т.к. длина на практике может оказаться излишней. Для разрешения этой проблемы и вводят динамические объекты, необходимость порождения которых возникает в следующих случаях.

1. Пусть в заданном тексте из слов произвольной длины требуется найти первое по порядку слово, которое обладает некоторым свойством (не содержит, например, букву "а").

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

2. Бывает, что какой-то программный объект (например, массив чисел, множество, список) нужен не на все время работы программы, а только на какую-то часть. Хотелось бы после отработки данного объекта разместить на этом месте памяти другой объект.

11.1 Определение ссылочного типа

Для работы с динамическими объектами статические переменные не подойдут, здесь предусматривается специальный тип значений - ссылочный. Значением данного типа является ссылка на какой-либо программный объект, осуществляющая непосредственный доступ к этому объекту. На машинном языке такая ссылка указывает на место памяти, т.е. адрес соответствующего объекта. А так как ссылочная переменная есть переменная, то возможно изменение значения ссылок и одна и та же переменная может указывать на любую ячейку памяти.

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

Имя ячейки

Такие переменные называются переменными типа указатель (переменными ссылочного типа) или просто указателями (ссылками).

Итак, слова - синонимы:

Значение указателя есть адрес объекта (ссылка на объект), посредством которого он и доступен в программе.

Итак, указываемый объект есть динамический объект. Он хранится в ячейке, которая не имеет своего собственного имени (не обозначается именем переменной), а используется лишь ссылка на эту ячейку. Здесь для сравнения можно привести ситуацию, когда называют зрителя в зале театра: "Зритель, сидящий на 3-м месте в 5-м ряду".

Обращение к динамической переменной происходит посредством указателя, являющегося статической переменной, которая имеет имя и может быть явно упомянута в программе. Динамическая переменная - "невидимая переменная", т.к. она не обозначается самостоятельным идентификатором. Память для значений такой переменной резервируется и освобождается в процессе работы программы (с помощью специальных процедур).

Как задать ссылочный тип, т.е. как описать указатель? Указатель обозначают обычным идентификатором. О том, что это указатель, говорит присутствие символа "^".

Значениями переменных такого ссылочного типа являются ссылки на динамические объекты, а сами динамические объекты имеют указанный в описании тип.

НАПРИМЕР:

TYPE MAS = ARRAY [1..100] OF INTEGER;

DINMAS = ^MAS;

VAR P: ^INTEGER; Q: ^CHAR;

RABMAS: DINMAS.

ЗДЕСЬ: P - ссылка на динамический объект целого типа, Q - ссылка на динамический объект литерного типа, RABMAS - ссылка на динамический объект, значением которого является массив из 100 чисел.

11.2 Создание динамических переменных. Процедура NEW

Описание переменных P и Q ссылочного типа в разделе объявлений еще не резервирует память для записи значений динамической переменной соответствующего типа.