Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Paskal_uchebn_posob_chast2_26_6_7

.pdf
Скачиваний:
45
Добавлен:
09.04.2015
Размер:
670.28 Кб
Скачать

51

BEGIN REWRITE (СПИСОК,'IMY.TXT');

WRITE ('вводи длину строки =>'); READLN(N);WRITELN('вводи фамилии =>'); FOR I:=1 TO N DO

BEGIN WHILE NOT EOLN DO

BEGIN READ(C); WRITE(список С) END; (* переход к новой строке *)

READLN; WRITELN( список ) END;

CLOSE( список ) end.

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

Программа S1 записывает во внешний файл с именем imy.txt фамилии, вводимые с терминала, а программа S2 считывает из каждой

строки внешнего файла фамилию и выводит ее на терминал с новой строки.

PROGRAM S2(INPUT);

TYPE семестр=FILE OF CHAR;

VAR список,семестр;

C:CHAR;I:INTEGER;

BEGIN RESET(список,'IMY','TXT');

WHILE NOT EOF(список) DO BEGIN

WHILE NOT EOLN(список) DO BEGIN

READ(список,C);

WRITE(C); END

READLN(список); WRITELN;

END END.

Стандартные файлы INPUT и OUTPUT являются текстовыми и в программе их описывать не надо, т.к.они описаны как текстовые файлы:

TYPE TEXT=FILE OF CHAR

VAR INPUT,OUTPUT:TEXT

При обращении к стандартным процедурам READ,READLN,WRITE,WRITELN в качестве стандартного аргумента можно указывать имя любого текстового файла. Если имя файла не указано, то происходит обращение к стандартному файлу.

PDF created with pdfFactory Pro trial version www.pdffactory.com

52

ЗАДАЧА

Написать программу, которая читает фамилии и пять оценок и записывает суммарный балл в текстовый файл.

Program result(input,output); Uses crt;

Const imf='res.dat'; Var fio:string;

summa:0..100; ball:0..20; schet:1..5; simvol:char; fres:text;

Begin clrscr;

assign(fres,imf);

rewrite(fres); repeat

writeln('Введите ФИО'); readln;

read(fio);

writeln(fres,fio);

summa:=0;

for schet:=1 to 5 do begin

write('Результат='); readln(ball); summa:=summa+ball;

end;

writeln(fres,summa);

writeln('Есть ли еще студенты (y/n)'); read(simvol)

until simvol='n';

writeln('*** Программа завершена ***');

close(fres);

End.

ЗАДАЧА

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

Program izres;

PDF created with pdfFactory Pro trial version www.pdffactory.com

53

Const imf='res.dat'; Var fio:string;

summa:0..100; simvol:char; fres:text;

Begin assign(fres,imf); reset(fres);

write('Для изображения очередной записи нажмите клавишу tab'); while not eof(fres) do

begin read(simvol);

readln(fres, fio, summa); writeln(fio,'сумма=',summa:3);

end;

writeln('*** Достигнут конец файла ***');

End.

ЗАДАЧА

Написать программу, которая считывает записи и заносит их в файл, а затем печатает их по порядку (телефонный справочник) .

Program tel; Uses crt;

Type dan=record fio:string; adres:string; nomer:string;

end;

Var spisok:file of dan; simvol:char;a:dan;

Procedure chten(var tekzap:dan); Begin

with tekzap do begin

writeln('Введите ФИО'); readln(fio); writeln('Введите адрес'); readln(adres); writeln('Введите номер телефона'); readln(nomer);

end;

End;

PDF created with pdfFactory Pro trial version www.pdffactory.com

54

Procedure izobr(tekzap:dan); Begin

with tekzap do begin

writeln(fio); writeln(adres); writeln('телефон',nomer); end;

End;

Begin clrscr;

assign(spisok,'acd.dat');

rewrite(spisok); repeat chten(a);

write(spisok,a);

write('Есть ли еще записи(y/n)'); readln(simvol);

until simvol='n'; close(spisok); reset(spisok);

while not eof(spisok) do begin

write('Для изображения следующей записи нажмите клавишу

ENTER');

readln;

read(spisok,a);

izobr(a);

{ get(spisok) } end;

writeln('*** Конец записей ***');

End.

PDF created with pdfFactory Pro trial version www.pdffactory.com

55

ЛЕКЦИЯ 1, 2 для 2-го семестра 1 курса УКАЗАТЕЛИ И ДИНАМИЧЕСКАЯ ПАМЯТЬ

Динамическая память.

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

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

Динамическая память - это оперативная память ПК, предоставляемая программе при ее работе, за вычетом сегмента данных (64 Кбайт), стека (обычно 16 Кбайт) и собственно тела программы. По умолчанию этот размер определяется всей доступной памятью ПК и,как правило, составляет не менее 200...300 Кбайт.

Динамическая память- это фактически единственная возможность обработки массивов данных большой размерности. Многие практические

задачи трудно или невозможно решить без использования динамической памяти. Такая необходимость возникает, например ,при разработке систем автоматезированного проектирования (САПР): размерность математических моделей, используемых в САПР, может значительно отличаться в разных проектах; статическое (т.е. на этапе разработки САПР) распределение памяти в этом случае, как правило, невозможно.

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

запоминания данных при работе с графическими и звуковыми средствами ПК.

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

PDF created with pdfFactory Pro trial version www.pdffactory.com

56

Оперативная память

0

 

ОС

 

 

100-130Кб

 

Паскаль+прога

64Кб

 

 

 

 

Динамическая память

 

 

640

 

 

 

 

1024Кб

 

 

 

 

 

Адреса и указатели.

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

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

Указатель- это переменная, которая в качестве своего значения содержит адрес байта памяти.

В ПК адреса задаются совокупностью двух шестнадцатиразрядных слов, которые называются сегментом и смещением.

Сегмент- это участок памяти, имеющий длину 65536 байт (64 Кбайт) и начинающийся с физического адреса, кратного 16 (т.е.0,16,32,48

и т.д.).

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

Адресное пространство ПК составляет 1 Мбайт (речь идет о так называемой основной памяти ПК; на компьютерах класса IBM PC/AT адресное пространство составляет 16 Мбайт; такие ПК могут иметь до 15 Мбайт дополнительной памяти, однако в Турбо Паскале нет средств, поддерживающих работу с дополнительной памятью). Для адресации в пределах 1 Мбайта нужно 20 двоичных разрядов, которые получаются из двух шестнадцатиразрядных слов (сегмента и смещения) следующим образом: содержимое сегмента смещается влево на 4 разряда, освободившиеся правые разряды заполняются нулями, результат складывается с содержимым смещения.

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

PDF created with pdfFactory Pro trial version www.pdffactory.com

57

непрерывная и отдельно адресуемая область памяти. Сегменты могут

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

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

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

(BYTE,CHAR,SHORTINT,BOOLEAN) занимают во внутреннем представлении один байт, остальные - несколько смежных. Поэтому на самом деле указатель адресует лишь первый байт данных.

Объявление указателей.

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

type

PerconPointer = ^PerconRecord; PerconRecord = record

Name : string; Job : string;

Next : PerconPointer end;

var

p1 : ^integer;

p2 : ^real;

Обратите внимание: при обьявлении типа PERCONPOINYER мы сослались на тип PERCONRECORD, который предварительно в программе объявлен не был. Как уже отмечалось, в Турбо Паскале последовательно проводиться в жизнь принцип, в соответствии с которым перед использованием какого- либо идентификатора он должен быть описан.

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

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

PDF created with pdfFactory Pro trial version www.pdffactory.com

58

1-ый элемент

 

2-ой элемент

 

 

Последний

списка

 

списка

 

 

 

Элемент

 

 

 

 

 

 

 

 

 

 

Списка

 

 

 

 

 

 

 

указатель

 

указатель

 

 

 

NIL

 

 

 

 

 

 

 

Пример списочной структуры данных

В Турбо Паскале можно обьявлять указатель и не связывать его при этом с каким-либо конкретным типом данных. Для этого служит стандартный тип POINTER, например:

var

pp : pointer;

Указатели такого рода будем называть нетипизированными.

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

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

В Турбо Паскале можно передавать значения только между указателями, связанными с одним и тем же типом данных. Если, например,

var

p1, p2 : ^integer; p3 : ^real;

pp : pointer;

то присваивание

p1 := p2;

вполне допустимо, в то время как p1 := p3;

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

pp := p3; p1 := pp;

и тем самым достичь нужного результата.

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

PDF created with pdfFactory Pro trial version www.pdffactory.com

59

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

программиста дополнительных усилий и таким образом свидетельствует о вполне осознанном действии.

Выделение и освобождение динамической памяти.

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

Начало кучи хранится в стандартной переменной HEAPORG , конец- в переменной HEAPEND. Текущую границу незанятой динамической памяти указывает указатель HEAPPTR.

0

 

 

 

 

Старшие адреса

640

Системная область

Программа

 

 

 

 

КУЧА

 

 

Системная область

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

HeapOrg

 

 

 

 

 

 

 

 

 

 

 

 

 

HeapPtr

 

 

 

 

 

 

 

 

 

 

 

 

 

HeapEnd

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Память под

любую

динамически размещаемую

переменную

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

var

i, j : ^integer; r : ^real; begin new(i);

.....

После выполнения этого фрогмента указатель I приобретает значение, которое перед этим имел указатель кучи HEAPPTR, а сам HEAPPTR увеличивает свое значение на 2, так как длина внутреннего представления типа INTEGER, с которым связан указатель I, составляет 2 байта (на самом деле это не совсем так: память под любую переменную выделяется порциями, кратными 8 байтам). Оператор new(r); вызовет еще раз смещение указателя HEAPPTR, но теперь уже на 6 байт, потому что

PDF created with pdfFactory Pro trial version www.pdffactory.com

60

такова длина внутреннего представления типа REAL. Аналогичным образом выделяется память и для переменной любого другого типа.

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

i^ := 2; {в область памяти i помещено значение 2}

r^ := 2*pi; {в область памяти r помещено значение 6.28}

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

Динамически размещенные данные можно использовать в любом месте программы, где это допустимо для констант и переменных соответствующего типа, например:

r^ := sqr(r^) + i^ - 17;

Разумеется, совершенно недопустим оператор

r := sqr(r^) + i^ - 17;

так как

указателю

R нельзя присвоить

значение вещественного

выражения. Точно так же недопустим оператор

 

r^ := sqr(r);

 

 

поскольку значением R является адрес, и его (в отличие от того значения,

которое

размещено

по этому адресу) нельзя возводить в квадрат.

Ошибочнным будет и такое присваивание: r^ := i;

так как вещественным данным, на которые указывает R^, нельзя присвоить значение указателя (адрес).

Динамическую память можно не только забирать из кучи, но и возращать обратно. Для этого используется DISPOSE. Например,

операторы

dispose(r);

dispose(i);

вернут в кучу 8 байт, которые ранее были выделены указателям I и R (см.выше).

Отметим, что процедура DISPOSE (PTR) не изменяет значение указателя PTR, а лишь возращает в кучу память ранее связанную с этим указателем. Однако повторное применение процедуры свободному

PDF created with pdfFactory Pro trial version www.pdffactory.com

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]