Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
AEP_LEKTsII.doc
Скачиваний:
90
Добавлен:
28.03.2015
Размер:
1.27 Mб
Скачать

13 Лекция

13.1 Сыртқы сақтауыш құрылғыларын (файлдық шамаларды) және динамикалық жадыны пайдалану арқылы программалау

Файлдармен жұмыс жасау. Компьютерлердің программалық ұйымдастырылуы, олардың сыртқы құрылғылармен байланысы, деректер қорлары файлдық құрылымға негізделген. Файлдар келесіні қамтамасыз етеді:

  • басқа программаларда пайдалану үшін мәндерді қалыптастыру және сақтау мүмкіндігін;

  • программалардың сырқы енгізу-шығару құрылғылармен өзара әрекеттесуін.

Паскальда файлдық типтегі құрылымдалған деректер пайдаланылады. Программада деректердің бұл типі келесі түрде беріледі: type <аталуы> = file of <тип>

Файлдың компоненттерінің типі ретінде файлдық типтен басқа деректердің кез келген типтерін пайдалануға рұқсат етілген. Мысалы:

type

intfile = file of integer;

refile = file of real;

chfile = file of char;

ran =1..10;

st = set of ran;

vector = array[ran] of real;

compl = record

re,im : integer;

end;

setfile = file of st;

vecfile = file of vector;

compfile= file of compl;

Файлдық айнымалыны сипаттау кәдімгі тәсіл бойынша сипаттау бөлімінде беріледі. Мысалы: var f: intfile; немесе var f : file of integer; Файлдық айнымалы программа мен сыртқы құрылғы арасындағы буфер болып табылады да, онымен логикалық түрде байланысуы тиіс, ол байланыс оператор арқылы жүзеге асырылады:

assign (< файлдық айнымалы>,'<құрылғының аталуы:’)

Әдетте, деректерді сақтау үшін файлдар магниттік тасымалдаушыдағы сыртқы жадтың құрылғысымен байланысқан және сыртқы файлдар деп аталады. Егер, мысалы, primer.dat атаулы файл А: дисководпен логикалық түрде байланысқан болса, онда файлға салынатын барлық деректер дискілік жинақтаушыда сақталады, ал программамен файл арасындағы байланысты файлдық f айнымалы арқылы assign (f,'primer.dat') оператор орнатады. Егер сыртқы құрылғы ретінде принтер пайдаланылатын болса, онда байланыс assign(f, '1st:') оператор арқылы жүзеге асырылады. Мұндағы lst – баспаға шығаратын құрылғының логикалық аталуы.

Сыртқы енгізу-шығару құрылғылардың логикалық атаулары:

con - консоль;

trm - терминал;

kbd - клавиатура;

1st - принтер;

auxжелінің буфері;

usr- тұтынушының драйвері.

Байланыс жүзеге асырылғаннан кейін файлдық f айнымалы сәйкесінше файл ұқсастырылады. Файлмен жұмыс жасау үшін оны ашу, ал жұмыс аяқталғаннан кейін жабу керек. Файл оқу үшін reset(f) оператор, жазу үшін - rewrite(f) оператор арқылы ашылады.

Деректерді оқу және жазу жоғарыда аталып кеткен read/write командалар арқылы жүзеге асырылады, бырақ тізімнің басында файлдық айнымалының аталуы қойылады, мысалы:

read (f, <тізім>); readln (f, <тізім>); write(f, <тізім>); writeln(f, <тізім>).

Файлды жабу close(f) командасы арқылы жүзеге асырылады.

Шартты түрде файлды бас жағы бар ал соңы бекітілмейтін лента түрінде бейнелеуге болады. Файлдың компоненттері лентаға ретімен бірінен кейін бірі жазылады:

f0

f1

f2

f3

м.к.

^т.м.

мұндағы т.м. - ағымдағы маркер, ол файлдың жұмыс позициясын (терезені) көрсетеді; м.к. (файлдың соңын белгілейтін маркер) - файлдың соңғы элементінен кейін автоматты түрде қалыптастырылатын арнайы код.

Мұндай түрдегі файлдар тізбекті түрде ену файлдары деп аталады. Тікелей түрде енуді мысалы, seek функциясы арқылы жүзеге асыруға болады.

rewrite(f) – файлды жазу үшін бұйрығы – файлды жазу режимінің бастапқы қалып-күйіне орнатады; ағымдағы маркер файлдың соңын белгілейтін маркерге орналастырылады. Егер f файлында осыған дейін ақпарат болса, онда ол жойылады. rеset(f) бұйрығы арқылы оқу үшін ашылған файлда ағымдағы маркер нөлдік қалып-күйіге орналастырылады, бырақ майлдағы нәрсе жойылмайды. Файлды жабу close(f) бұйрығы міндетті, себебі бұл бұйрық файлдың соңын белгілейтін маркерді қалыптастырады, ол көп жағдайда қажетті болып табылады (мысалы, eof(f) функциямен жұмыс жасау үшін). Паскальда файлдармен жұмыс жасауға арналған кірістірілген функциялар көзделген:

filesize(f) – ашылған файл компоненттерінің ағымдық мөлшер саны;

filepos(f) – маркердің ағымдық позициясының нөмірі;

геnаmе(f,имя) – f-пен байланысқан файл аталуын ауыстыру;

erase(f) - файла файлды жою;

execute(f) - СОМ-файлды орындау;

chain(f) - СНМ-файлды орындау;

seek(f,N) - маркерді N позициясына орнатады;

eof(f) – файлдың соңы табылса, TRUE қайтарады;

eoln(f) - жолдың соңы табылса, TRUE қайтарады.

Тәжірибеде литерлік (логикалық) жолдардан тұратын мәтіндік файлдар кең пайдаланылады. Сондықтан, Паскальда TEXT стандартты файлдық тип көзделген (ол file of char болып табылмайды, ол file of string[n] – ке жақындау). Логикалық жолдардың ұзындығы әртүрлі болады, соның қатарында, нөльдік. Әр жолдың соңында «жолдың соңы» (eoln - «end of line») арнайы символ қойылады. Жолдың соңын белгілейтін баспалық символ ретінде # литераны қолданады. Мәтіндік файл (text) қатаң тізбекті болып табылады, оған кейбір кірістірілген, мысалы, seek сияқты функцияларды қолдануға болмайды. Типтелген файлдармен салыстырғанда, мәтіндік файлмен бір мезгілде оқу (read) және жазу (write) операцияларын орындауға болмайды. Бырақ, writeln және readln операторлары рұқсат етілген. Сандық деректер, бүтін және нақты, мәтіндік файлда бос орын арқылы жазылуы тиіс.

Р33 программада деректерді принтерге (1st:) шығару мысалы келтірілген.

program Р33;

var

fal:text; x :real; name :string[25];

begin

assign(fal,'1st: ' );rewrite(fal);x:=2.5; name:='Салтанат';

writeln(fal,x:8:2);

writeln{fal,'Сәлем, ',name); close(fal)

end. {файлдық fal айнымалы 1st: принтермен байланысады, fal файлына жазу негізінде баспаға шығаруды білдіреді}

Р34 программада 10 дан 20 дейін бүтін сандар тізбегі құрылады да «xxx.dat» файлда сақталады.

program Р34;

var

f: file of integer; i:integer;

begin

assign{f,'xxx.dat'); rewrite(f};

for i:=10 to 20 do write(f,i); close {f};

end. {Программа орындалып болғаннан кейін сыртқы xxx.dat файлы қалыптастырылады}

Р35 программада бар «xxx.dat» файлдан алғашқы бес компоненттері оқылып, осы мәндердің квадраттары дисплейге шығарылады.

program Р35;

var ff: file of integer; j,i: integer;

begin

assign(ff,'xxx.dat'); reset(ff);

for j:=l to 5 do begin read(ff,i); writeln(i*i);

end;

close(ff);

end.

Динамикалық айнымалылар және нұсқағыштар. Кеңінен қолданылатын статикалық айнымалылар олар сипатталатын блокқа кірген кезде автоматты түрде пайда болады да, бүкіл блоктың жұмыс жасау барысында орын алады да, осы блоктан шыққан кезде жойылады. Статикалық айнымалылар программаны іске қосқан кезде жадыда орналасады да сол программаның орындалу барысында үнемі жадыда орын алады. Статикалық айнымалыларға атаулары бойынша сілтейді, ал типтері олардың сипатталуы арқылы анықталады. Статикалық объекттерді машинаның жадына орналастыру жұмысы трансляциялау кезеңінде орындалады. Бырақ, тек статикалық айнымалыларды ғана пайдалану тиімді программаларды құру барысында қиындықтарды тудыруы мүмкін. Көп жағдайларда кейдір деректер құрылымының өлшемі алдын-ала белгісіз, немесе құрылым программаның орындалу барысында өзгеруі мүмкін. Осыған ұқсама құрылымдардың бірі ертерек қарастырылған - тізбекті файл.

Айнымалыны орналастыру үшін жадының қажетті көлемін тек программаның орындалу барысында ғана анықтауға болатын жағдайлар программалауда жиі кездеседі. Нұсқағыштар айнымалыларды «жүру барысында», яғни, динамикалық түрде құруға мүмкіндік береді. Қажет болған жағдайда жадыға жаңа айнымалыларды орналастырып, олар қажет болмай қалған кезде жадыны босатуға болады.

Паскальда динамикалық шамаларды қолдану мүмкіндігі көзделген. Олар үшін жадыны бөліп беру және тазарту трансляциялау кезеңінде емес, программаның өзінің орындалу барысында жүзеге асырылады. Динамикалық шамалармен жұмыс жасау үшін Паскальда мәндердің арнайы типі – сілтеуіш (Pointer) көзделген. Бұл тип жай типтердің де, құрама типтердің де қатарына жатпайды. Сілтеуіш типті айнымалылар, немесе нұсқағыштар статикалық айнымалылар болып табылады. Сілтеуіш типті айнымалының мәні ұяшық адресі – сәйкес динамикалық шаманың жадыдағы орны болып табылады. Өз мәніне сілтеуіш айнымалы программаның орындалу барысында, сәйкес динамикалық шаманың пайда болған моментінде ие болады.

Сілтеуіш типті айнымалылар (нұсқағыштар) пайдалану үшін оларды айнымалылар бөлімінде сипаттау арқылы кәдімгі жолмен енгізіледі, ал олардың (программада құрылатын сәйкес динамикалық шамалардың типін көрсететін) типі де айнымалыларды сипаттауда типті беру арқылы немесе ертерек сипатталған типтің аталуын көрсету арқылы анықталады. Динамикалық айнымалыларға сілтеу олардың жадыдағы адресі бойынша жүзеге асырылады. Динамикалық айнымалының адресін сақтау үшін сілтеуіш тип пайдаланылады, ал сілтеуіш типті айнымалы нұсқағыш деп аталады. нұсқағыштар типтелген және типтелмеген болады.

Нұсқағыштың мәні содан бастап сәйкес динамикалық шама жадыда орналаса бастайтын ұяшықтың адресі болып табылады. Сілтеуіш типті беру келесі схема бойынша орындалады:

type<сілтеуіш типтің аталуы > = ^ <динамикалық шама типтің аталуы>

( ^ белгі шаманың динамикалық болғандығын көрсетеді).

Мысалы:

type

р = ^ integer;

q = ^ record

х:integer;

у:string[20]

end;

Екі р және q сілтеуіш тип жарияланған. Біріншісі – бүтінсанды мәндерге нұсқағыш, екіншісі - на екі өрісі бар жазбаға. Нұсқағыштың динамикалық объектпен байланысын келесі түрде бейнелеуге болады:

Бұл схемада р – нұсқағыштың аталуы; жұлдызша арқылы нұсқағыштың мәні бейнеленген, ал стрелка нұсқағыштың мәні объекттің адресі болып табылатындығының фактін бейнелейді (объектке сілтеу), сол арқылы программада объектке қол жеткізуге болады.

Кейбір жағдайларда нұсқағыштың мәні ретінде нұсқағышпен ешқандай объектті байланыстырмайтын «бос» сілтеуді қабылдау қажеттілігі пайда болады. Мұндай мән nil қызметші сөз арқылы беріледі де кез келген сілтеуіш типке тиесілі болады. p:=nil оператордың орындалу нәтижелерін келесі түрде бейнелеуге болады:

Жарияланған типтерге ие бола отырып, осы типті айнымалыларды кәдімгідей сипаттауға болады. Мысалы, var i:p; zap: q;.

Базалық типті динамикалық айнымалыларды тікелей «айнымалыларды сипаттау» бөлімінде енгізуге болады: var i: ^integer;,

Нұсқағышты сипаттау сәйкесінше динамикалық объекттің мәні үшін жадыны әлі резервтемейді. Мысалы, жоғарыда келтірілген әр сипаттау адресті * - сілтеніштің мәнін жазу үшін жажыдан екі байт орын бөліп береді, бырақ, жадыда р немесе q типті ешқандай шама құрылмайды және тіпті * адрес те әлі жоқ.

Оған сілтеуіш і айнымалысы сілтеп тұрған динамикалық объектті туындылау үшін, стандартты new(i) процедура қызмет атқарады, мұндағы new - «жаңа» - процедураның аталуы, i – нұсқағыштың аталуы. new(i) процедурасы аталуы і болатын сәйкес типті динамикалық объектті жайғастыру үшін жадыдан орын резервтейді, ал і нұсқағышқа динамикалық і объекттің адресін меншіктейді. Бырақ, writeln(i) процедура арқылы динамикалық объекттің адресін білуге болмайды.

Динамикалық объекттер стек типі бойынша жадының арнайы облысында орналастырылады, ол «үйінді» деп аталатын программадан және статикалық айнымалылардан бос жадының орыны.

Жоғарыда айтылғандай нұсқағыш аталуынан кейін қойылған ^ символ мәселе сілтеуіш айнымалының мәні туралы емес, ал осы сілтеуіш айнымалы сілтеп тұрған динамикалық объекттің мәні туралы екендігін білдіреді. Сондай ақ, егер программада айнымалыны сипаттау var i:^integer; бар болса, онда new(i) процедура орындалғанда integer типті динамикалық айнымлы құрылады. Егер одан кейін меншіктеу i^:= 58 операторы орындалса, онда осы динамикалық айнымалыға 58 мәні меншіктеледі.

Одан кейін ^ символы қойылған сілтеуіш айнымалының аталуын «нұсқағышы бар айнымалы» деп атайды. Дәл сол синтаксикалық тұрғыда динамикалық айнымалының рөлін атқарады да типі динамикалық айнымалының типі болатындай айнымалыларды пайдалануға рұқсат етілген жерлерде тілдің кез келген конструкцияларында пайдалануға болады. Мысалы, егер j - integer типті статикалық айнымалы болса, онда келесі меншіктеу операторлар орынды: j: = j + i^ + 2; i^:=i^ div 3 + 7; i^:=sqr(i^) және с.с. Егер сілтеуіш b айнымалы массивке сілтейтін болса:

type mas = array[1..100] of integer; var b:^mas

онда бұ жағдайда нұсқағышы бар айнымалылардың түрі, мысалы: b^[2], b^[k+5] болуы мүмкін.

Егер new(p) оператордың орындалу нәтижесінде құрылған кейбір динамикалық р^ объект программаның орындалу барысында қажет болмай қалатын болса, онда стандартты dispose(p) процедура арқылы оны жоюға (жадыдағы оған бөлінген орынды тазалауға) болады. dispose(p) түрдегі оператордың орындалу нәтижесінде оған сілтеуіш р айнымалы сілтеп тұрған динамикалық объект өз тіршілігін аяқтайды, ол алатын жадыдағы орын босатылады, ал р нұсқағыштың мәні анықталмаған (бырақ nil–ге тең емес) болып қалады

Егер dispose(p) процедураны шақырудың алдында ол бос nil мәнге ие болған, немесе осы процедураны шақырудың алдында р нұсқағыш анықталмаған болса, онда бұл апаттық аяқталуға әкелуі мүмкін.

Бір нұсқағыштың мәнін типі сондай болатын басқа нұсқағышқа меншіктеуге болады. Сонымен қатар, типтері бірдей болатын нұсқағыштарды «=» немесе «<>» қатынастарды пайдаланып бір бірімен салыстыруға болады.

Стандартты new және dispose процедуралары динамикалық түрде программалық объекттерді құруға және оларды жоюға мүмкіндік береді, бұл машина жадың тиімді пайдалануға мүмкіндік береді.

Деректердің байланысқан тізімдері. Деректердің байланысқан түрлі құрылымдарының қатарында массивтер мен файлдар стандартталған, ал олардан басқа және соларға ұүқсас басқа құрылымдар да қажет болуы мүмкін. Олар үшін келесі қасиеттер тән:

  • элементтерінің саны алдын-ала анықталмаған;

  • жедел жадыда сақтау қажеттілігі.

Мұндай құрылымдарды жүзеге асыруға арналған құралды динамикалық айнымалылар аппараты ұсынады. Мұндай құрылымдардың ең қарапайымы бір жаққа бағытталған тізім болып табылады. Ол дәрігердің қабылдауына тұратын кезек сияқты құрылады: пациенттер кез келген бос орындарда отыра береді, бырақ, әрқайсысы өзінің кезегін біледі (яғни, деректер жадының бос орындарында орналасады, бырақ әр элемент алдындағы немесе келесі элементке сілтеуді қамтиды). Пациенттердің саны алдын-ала анық болмайтын себебіне байланысты, құрылым динамикалық болып табылады. Сонымен, байланысқан тізім жазбалар – түйіндер тізбегі болып табылады, ол тізбектегі әр жазба негізгі деректерді және тізбектегі келесі жазбаға сілтеуді қамтиды. Тізімнің басында тізімнің бірінші жазбасына сілтейтін нұсқағыш («түбір») орналасқан.

Тізімнің соңғы жазбасындағы нұсқағышқа әдетте nil мәні меншіктеледі, ол тізімнің соңын білдіретін белгі. Мұндай құрылым динамикалық болып табылады, ол программаның орындалу барысында өзгере алады.

Тізімдерге қолданылатын негізгі операциялар: тізімге жазбаны кірістіру және оны тізімнен жою. Байланысқан тізімге жаңа түйінді қосу үшін бір нұсқағышты өзгерту жеткілікті, бұл кезде түйіндердің өздері жылжымауы тиіс. Түйінді жою да сәйкес нұсқағышты ол жойылатын түйіннен кейінгі түйінге сілтейтіндей етіп өзгерту арқылы жүзеге асырылады не должны.

Ұқсама басқа құрылым - стек. Стектің моделі ретінде оның ішіне шариктер домалатып кіргізілетін бір жағы дәнекерленген түтікті (трубканы) қарастыруға болады. Бұл жағдайда LIFO (Last In First Out – соңында кірген – бірінші шығады) принципі жүзеге асырылады. Стектегі элементтердің мүмкін болатын саны бекітілмеген. Стек оған тек түбірлік нүктесінде ғана қол жеткізуге болатын тізімнің жеке жағдайы болып табылады. Жаңа элементті қосу немесе жою амалдары тізімнің басында орындалады. Стек үшін стекке енгізу және стектен алу операциялары анықталған. Элементті стекке енгізу операциясы тек элементтің мәні арқылы анықталады. Элементті стектен алу операциясының мағынасы - стектегі бірінші элементтік мәнін айнымалыға меншіктеп сол элементті стектен жою.

Стекті программада жүзеге асыру мысалын қарастырайық. Бұл кезде техникалық тұрғыда бір қатар есептерді шешу керек, олардың ішінде ең ерекшелері:

  • стектің келесі компоненттерін байланыстыру;

  • стек бойынша әр жылжыған сайын сілтеулерді ығыстыру.

Әр элементтің мәнімен қатар келесі элементке сілтеуді де қамту қажеттілігіне байланысты элементтердің әрқайсысы екі өрісі бар жазбада сақталады, одағы бірінші өріс – элементтің мәні, ал екінші – келесі элементке сілтеу. Схемалы түрінде бұл құрылымды келесідей сипаттауға болады (бірінші келген элемент ешнәрсеге сілтей алмайды, ол туралы «бос сілтеу» nil білдіреді).

Нақытылық үшін стектің элементтері – нақты сандар болсын, және тізбектеліп толтырған кезде стектің 1-2-3 қалып-күйлері келесідей болсын:

1

2

3

1

2

3

1

2

3

1,75

35,7

1,75

-6,94

35,7

1,75

Р36 программа екі процедураны қамтиды: кезекті компонентті стекке қосу және оны стектен алу. Программа көрсетілген стекті қалыптастырады және одан элементті алады. Ерекше назарды сілтеулерді жылжыту ұйымдастырылуына аудару керек.

Ағаш құрылымы сызықты тізімнің жалпылануы болып табылады. Тізімде әр түйін басқа түйінге сілтейтін нұсқағышты қамтиды. Ағашта әр түйін бірнеше түйіндерге сілтейтін бірнеше нұсқағыштарды қамтиды. Егер нұсқағыштар саны екеу («оң жақ» және «сол жақ») болса, онда мұндай ағаш бинарлы деп аталады. Нұсқағыштардың біреуі nil–ге тең болуы мүмкін. Ағаштың бастапқы нүктесі түбірлік түйін деп аталады. Түбірлік түйіннің оған кіретін бұтақтары жоқ, тек шығатын бұтақтары бар. Басқа төбеден осы төбеге сілтейтін нұсқағышы бар төбені сол төбенің ұрпағы, ал біріншісін сәйкесінше - тегі деп атайды. Егер төбе ұрпақтарға ие болмаса, онда ол терминалды төбе деп аталады. Бүтінсанды мәндердің бинарлы ағашында сол жақтағы бұтақтарда кіші сандар, ал оң жақтағы бұтақтарда үлкен сандар орналасуы тиіс деген келісімді ұстанады. Ағаштарға қолданылатын негізгі операциялар – элементті ағашқа ендіру, элементті ағаштан жою және ағашты айналып шығу.

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