Информатика | Динамикалық ұғым принципімен программа құру технологиясы
Мазмұны
I. Кіріспе.......................................................................2-3
II. Негізгі бөлім
1. Көрсеткіштер. Көрсеткіштерді анықтау.........4-5
2. Динамикалық ұғымды ерекшелеу және босату...................................................................6-12
3. Көрсеткіштерді қолдану.................................12-16
4. Динамикалық ұғыммен жұмыс істеу үшін процедуралар мен функцияларды пайдалану……………………………………..16-19
5. Үйінтек әкімдігі...............................................19-21
III. Қорытынды..............................................................22-23
IV. Есептің қойылымы................................................24
V. Пайдаланған әдебиеттер.......................................25
Көрсеткіштер.Көрсеткіштерді анықтау. Дербес компьютердің жедел жады әрқайсысы 1 байт информация сақтай алатын, нөмірленген элементар ұяшықтардың жиынтығы болып табылады. Ұяшықтардың нөмірлері олардың тұрақтары деп аталады. Динамикалық мәліметтер жедел жадыдағы тұрақтары бойынша анықталады.
Турбо Паскальда программистке динамикалық ұғым принципін басқаруға үлкен мүмкіндік беретін ол - көрсеткіштер.
Көрсеткіш - өз мағынасы ретінде жедел жады байтының тұрағын құрайтын айнымалы.
Дербес компьютерде тұрақтар екі он алты разрядты сөздермен беріледі. Олар сегмент және ығысу деп аталады.
Дербес компьютер жадынан әрбір тұрақ төрт байт орын алады. Тұрақтың алғашқы екі байтын оның сегменті, ал соңғыларын ығысу деп атайды. Сегмент - жады аумағы, оның ұзындығы 65536 байт (64 Кбайт) және ол физикалық тұрақтан басталады. Олар көрсеткіш мәнінің жедел жадыдағы орнын толық анықтайды. Сегмент көрсеткіш мәнінің алғашқы байтын көрсетсе, ығысу байт санын анықтайды.
Дербес компьютердің тұрақ аумағы 1 Мбайтты құрайды. Дербес компьютердің қазіргі заманғы процессорлі компьютерлерде 80386 және одан да көп тұрақ Турбо Паскальда 1 Мбайт шеңберінде тұрақтандыру үшін 20 екілік разряд керек, олар екі он алты разрядтық сөздерден (сегмент және ығысу ) келесі ретпен құрылады (1 – сурет ): сегмент құрамы солға төрт разрядқа ығысады, босаған оң разрядтар нөлмен толады, жауабы ығысу құрамына қосылады.
Жадының 16 байттық фрагменті параграф деп аталады, сондықтан, сегмент жадыны параграф нақтылығымен тұрақтандырады деп айтуға болады. Әр сегментке үздіксіз және жеке тұрақтандырылған жады обласы сәйкес келеді. Сегменттер жадыда бірінен соң бірі үзіліссіз немесе бірнеше интервалмен, немесе бір - бірін жауып жүруі мүмкін.
Сегмент
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+
Ығысу
=
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Адрес
19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
1- сурет. ДК – ң тұрағының құрылу схемасы.
Сонымен, өзінің ішкі құрылысы бойынша кез келген көрсеткіш сегмент немесе ығысу арқылы берілген екі сөзінің қосылуын білдіреді. Көрсеткіш көмегімен динамикалық ұғым принципінде кез келген Турбо Паскальда белгілі мәліметтер типін орналастыруға болады. Олардың тек кейбіреуі ғана (Byte, Char, Shortint, Boolean) 1 байт орын алады, ал басқалары - бірнеше көршілес орын алады. Сондықтан іс жүзінде көрсеткіш тек алғашқы мәлімет байтын тұрақтайды.
Негізінде, Турбо Паскальда көрсеткіш кейбір мәлімет типімен байланыстырылады. Бұндай көрсеткіштерді типтендірілген деп атаймыз. Типтендірілген көрсеткіштерді анықтағанда тип атының алдына ^ таңбасы тіркеледі:
< Көрсеткіш айнымалысының аты > : ^ < базалық тип > ; Көрсеткіштің базалық типіне ешқандай шектеу қойылмайды. Көрсеткіштің бір ғана тұрақты nil мәні бар, ол айнымалы мәнінің жоқ екендігін білдіреді. Сілтемелерді nil мәнімен, не өзара салыстыруға да болады. Типтері бірдей болғанда ғана сілтемелердің біреуінің мәнін екіншісіне беруге де рұқсат етіледі. Турбо Паскальда көрсеткішті анықтай отырып, оны қандай да бір нақты мәлімет типімен байланыстырмаса да болады. Сол үшін Pointer стандартты типі қызмет істеді;
< Көрсеткіш айнымалысының аты > : pointer.
Көрсеткіштің мұндай түрін типтендірілмеген деп атаймыз. Типтендірілмеген көрсеткіштер нақты типпен байланысты еместіктен, олардың көмегімен құрылымы мен типі программа барысында өзгеріп отыратын мәліметтерді динамикалық орналастыру ыңғайлы.
Жоғарыда айтылғандай, көрсеткіш мәні жадыдағы айнымалылар тұрақтары болып табылады, сондықтан бір көрсеткіштің мәнін басқа көрсеткішке беруге болатынын күтуге болады. Бірақ іс жүзінде бұл дәл осылай емес. Турбо Паскальда мәндерді тек бірдей мәлімет типімен байланысты көрсеткіш арасында беруге болады.
Егер, мысалы :
var
p1,p2:^integer;
p3:^real;
pp:pointer;
алайда p1:=p2 ;
меншіктеуге болады, ал осы кезде
p1 : = p3;
болмайды, себебі p1 және p3 әр түрлі мәлімет типін көрсетеді. Бұл алайда, шектеу типтедірілмеген көрсеткіштерге таралмайды, сондықтан бізге
pp : = p3 ;
p1 : = pp; деп жазып, керек шешім алуға болар еді.
Динамикалық ұғымды ерекшелеу және босату. Барлық Турбо Паскальда динамикалық ұғым массив байттары ретінде қарастырылады. Оларды үйінтек деп атайды. Үйінтек үлкен тұрақта , жады облысынан кейін орналасады, оны программа денесі алып тұрады.
Үйінтек басы стандартты айнымалы HEAPORG – та (2 - сурет), соңы - айнымалы HEAPPTR көрсеткіші көрсетілед. Кез келген динамикалық орналастырылған айнымалы жадысы New процедурасымен ерекшелңнеді. Осы процедураға жүктелу параметрі типтелген көрсеткіш динамикалық тұраққа сәйкес мағына алады.
Содан бастап мәліметтерді орналастыруға болады.
Мысалы:
Var
I , j : ^ integer;
R : ^ real;
Begin
New (i); … end.
Үлкен тұрақ
Жүйелік
аймақ
Үйінтек
программа
Жүелік
аймақ
HeapEn
HeapPt
HeapOrg
Кіші тұрақ
Осы көрсеткіштің фрагменті орындалғаннан кейін I HEAPPTR үйінтек көрсеткішінің мәнін алады, ал HEAPPTR өз мәнін екіге арттырады, себебі I көрсеткішімен байланысты INTEGER – нің ішкі көрінісінің ұзындығы 2 байтқа тең. Оператор
New (r ); Қайтадан HEAPPTR көрсеткішінің ығысуына әкеп соғады, бірақ енді 6 байтқа, себебі REAL типінің ішкі көрінісінің ұзындығы осындай. Осындай ретпен басқа да кез келген типтің айнымалылары үшін жады ерекшелінеді.
Көрсеткіш кейбір мән алғаннан кейін, яғни, жадының нақты физикалық байтын көрсете бастауы, сондай- ақ тұрақ кез келген сәйкес типтің мәнін орналастыра алады. Ол үшін көрсеткіштен кейін ешқандай бос орынсыз ^ белгісі қойылады, мысалы :
I ^ : = 2 I ұғымының обылысына 2 мәні орналастырылған
R ^ : = 2 * pi ; r ұғымының обласына 6.28 мәні орналастырдық.
Осылайша, көрсеткіш көрсететін мән, яғни үйінтекте орналасқан мәлімет, ^ белгісімен белгіленіп, көрсеткіштен кейін қойылады. Егер көрсеткіштен кейін ^ белгісі қойылмаса, онда бұл мәлімет орналасқан тұрақты білдіреді. Осы туралы ойланудың мәні бар : кез келген көрсеткіштің мәні тұрақ болып табылады, ал әңгіме тұрақ туралы емес, осы тұрақта орналасқан мәлімет туралы екенін көрсету үшін көрсеткіштен кейін ^ қойылады. Егер осыны нақты түсініп алса, динамикалық ұғым принципімен жұмыс істеуде кедергі болмайды.
Динамикалық орналасқан мәліметтерді программаның кез келген жерінде, константтар мен сәйкес типті айнымалыларды орналастыруға болатын жерінде қолдануға болады. Мысалы:
R ^ : = sgr (r ^) + I ^ - 17;
Ешқашан мұндай оператор болмайды :
R : = sgr (r ^) + I ^ - 17;
R көрсеткішіне нақты мән меншіктеуге болмайды. Сол сияқты бұндай оператор болмайды:
R ^ : = sgr (r );
R көрсеткішінің мәні тұрақ болып табылады, және оны квадратқа енгізуге болмайды. Мынандай меншіктеу қате болады:
R ^ := I ;
R көрсеткіші көрсететін мәліметтеріне көрсеткіш мәнін меншіктеуге болмайды.
Динамикалық ұғымды үйінтектен алып қана қоюға болмайды, оны қайтаруға да болады. Ол үшін Dispose процедурасы қолданылады. Мысалы:
Dispose (r );
Dispose (I );
Операторлары үйінтекке бұрыш I және R көрсеткіштерімен ерекшелінген 8 байтты қайтарады.
Айтып кетейік, Dispose (RTR ) процедурасы RTR көрсеткішінің мәнін өзгертпейді, тек қана үйінтекке бұрын осы көрсеткішпен байланысты болған ұғымды қайтарады.
Алайда, процедураны бос көрсеткішке қайталап қолдану орындалу периодында қате пайда болуына әкеп соғады. Босаған көрсеткішті програмист резервтелген сөз NIL - мен белгілеуі болады. Қандай да бір көрсеткіш белгіленген бе әлде жоқ па екенін келесі жолмен тексеруге болады:
Const
P : ^ real = NIL ;
begin
. . . . .
if p = NIL then
new (p );
. . . . .
dispose (p);
p: = NIL ;
, . . . .
end.
Басқа көрсеткіштермен ешқандай салыстыру операцияларын істеуге болмайды.
Жоғарыда келтірілген фрагмент көрсеткішті анықтауының типтелген константа түрін бір уақытта оған Nil мәнін меншіктеу арқылы көрсетеді. Көрсеткіштің бастапқы мәні еркін болуы мүмкін айта кету керек. New процедурасының мәні меншіктелген көрсеткіштерді қолдану жүйемен қадағаланбайды, ол күтпеген шешімдерге әкеп соғуы мүмкін.
NEW және DISPOSE процедураларын меншіктелуінің қайталануы ұяшықталынған құрылымға әкеп соғады. Өйткені барлық программалар үйінтек әкімдігі деген ерекше көмекші программаның басқаруымен орындалады. Ол автоматты түрде сөздің программаңызға тіркелген және үйінтектегі бос фрагменттердің есебін жүргізеді. New процедурасына қайтадан меншіктелгенде бұл көмекші программа керекті айнымалы орналаса алатын ең аз бос фрагмент іздейді. Табылған фрагменттің тұрақ басы көрсеткішке оралады, ал көрсеткіштің өзі немесе оның керекті ұзындықты бөлігі үйінтектің бос емес бөлігі ретінде белгіленеді.
Басқа мүмкіншілігі - толық үйінтек фрагментінің босауы да. Осы мақсатпен динамикалық ұғымды ерекшелеу алдында. HEAPTR көрсеткішінің ағымды мәні MARK процедурасының көмегімен айнымалы - көрсеткіште есте сақталады. Енді кез келген уақытта MARK процедурасы еске сақтаған тұрақтан бастап, динамиканың ұғымының аяғына дейін үйінтек фрагментін босатуға болады. Ол үшін RELEASE процедурасы қолданылады.
Мысалы:
Var
P, p1, p2,
P3, p4, p5 : ^ integer;
Begin
New (p1) ;
New (p2) ;
Mark (p );
New (p3);
New (p4);
New (p5);
. . . . . .
release (p);
end.
Бұл мысалды HEAPPTR ағымды айнымалысы MARK (P)
процедурасы арқылы P көрсеткішіне орналастырылған, алайда жады айнымалыға резервтелген жоқ.
Release (P) динамикалық ұғымды белгіленген жерден бастап үйінтек басына дейін босатты. 3 – сурет NEW - DISPOSE және NEW - MARK - RELEASE процедураларының қаралған және RELASE (P) операторының орнына DISPOSE (P) үшін қолданылатын жағдайға жұмыс механизімін бейнелейді.
p1^
p2^
p3^
p4^
p5^
p1^
p2^
p1^
Mark(p) Dispose(p) Release (p)
3 – сурет. Динамикалық ұғым құрылымы
а) босау алдында; б) DISPOSE(P3)-тен кейін; в) RELEASE(P)-тен кейін;
Ескере кету керек, RELEASE – ты шақыру DISPOSE процедурасымен құрылған үйінтектегі бос фрагмент тізімін жояды. Сондықтан екі бірдій жадыны босату механизмін бірге бір программа көлемінде қолдану ұсынылады. Бұрын айтылғандай NEW процедурасының параметрі тек қана көрсеткіш бола алады. Типтелмеген көрсеткішпен жұмыс істеу үшін:
GETMEM (P,SIZE) – жадыны резервтеу
FREEMEM (P,SIZE) – жадыны босату
қолданылады.
Мұндағы P – типтелмеген көрсеткіш;
SIZE – үйінтектің керекті немесе босатылатын бөлігінің байтпен берілген көлемі.
GETMEM процедурасының үйінтекке бір жүктелуінде 65521 байтқа дейін динамикалық ұғымды резервтеуге болады.
GETMEM - FREEMEM процедурасын қолдану және динамикалық ұғыммен жұмыс ерекше абайлылықты және қарапайым ережелерді тиянақты орындауды қажет етеді: қанша жады резервтелсе, сонша жады босату керек, қай тұрақтан резервтелсе, сол тұрақтан босатылу керек.
Турбо Паскальда типтелмеген көрсеткіштердің бар болуы типтердің білінбейтін қалыптасуына кең мүмкіндік береді. Өкінішке орай NEW және DISPOSE процедураларында атауларды дұрыс қолданбаудан программада кеткен қателіктерді табу қиын, және де ол қаламайтын тип қалыптасуына әкеп соғуы мүмкін. Іс жүзінде, мынандай программа бар болсын:
Var
i,j : ^ integer;
r : ^ real;
begin
new (i); {i:=HeapOrg; HeapPtr:= HeapOrg+2}
j:=i; {j:= HeapOrg}
j^:=2;
dispose(i); { HeapPtr:= HeapOrg }
new(r); { r:= HeapOrg; HeapPtr:= HeapOrg+6}
r^:=pi;
writeln(j^) { ?? }
end.
Экран бетіне шығады? Бұл сұраққа жауап беру үшін HEAPPTR көрсеткішін бақылайық. Программа орындалуы алдында бұл көрсеткіш I көрсеткішіне сосын I көрсеткішіне жіберілген HEAPORG үйінтегінің тұрақ басының мәнін қабылдаған. DISPOSE(I) – ды орындаған соң үйінтектің көрсеткіші қайтадан HEAPORG мәнін қабылдайды. Бұл тұрақ NEW(r) процедурасында R көрсеткішіне жіберілген. R көрсеткішіне π=3,14159 саны орналасқан соң, үйінтектің бірінші 2 байты осы санның ішкі көрінісімен толған болып шықты. Ал J әлі де HEAPORG – ның тұрағын сақтайды, сондықтан оператор WRITELN(J^) π санының 2 байтын бүтін санның ішкі көрінісі ретінде қарастырады. (Себебі J бұл INTEGER типіне көрсеткіш) және 8578 шығарады.
Көрсеткіштерді қолдану. Біраз қорытынды жасайық. Сонымен, динамикалық ұғым 200 … 300 немесе одан да көп Кбайт құрайды, оның басы HEAPORG айнымалысында сақталады, ал соңы HEAPEND айнымалысының тұрағына сәйкес келеді. Динамикалық ұғымның бос аймағының ағымды тұрағы HEAPPTR көрсеткішінде сақталады.
Үлкен мәліметтер массивін орналастыру үшін динамикалық ұғымды қалай пайдалану керек екені қарастырайық. Мысалы, 100x200 EXTENDED типті тікбұрышты .....
I. Кіріспе.......................................................................2-3
II. Негізгі бөлім
1. Көрсеткіштер. Көрсеткіштерді анықтау.........4-5
2. Динамикалық ұғымды ерекшелеу және босату...................................................................6-12
3. Көрсеткіштерді қолдану.................................12-16
4. Динамикалық ұғыммен жұмыс істеу үшін процедуралар мен функцияларды пайдалану……………………………………..16-19
5. Үйінтек әкімдігі...............................................19-21
III. Қорытынды..............................................................22-23
IV. Есептің қойылымы................................................24
V. Пайдаланған әдебиеттер.......................................25
Көрсеткіштер.Көрсеткіштерді анықтау. Дербес компьютердің жедел жады әрқайсысы 1 байт информация сақтай алатын, нөмірленген элементар ұяшықтардың жиынтығы болып табылады. Ұяшықтардың нөмірлері олардың тұрақтары деп аталады. Динамикалық мәліметтер жедел жадыдағы тұрақтары бойынша анықталады.
Турбо Паскальда программистке динамикалық ұғым принципін басқаруға үлкен мүмкіндік беретін ол - көрсеткіштер.
Көрсеткіш - өз мағынасы ретінде жедел жады байтының тұрағын құрайтын айнымалы.
Дербес компьютерде тұрақтар екі он алты разрядты сөздермен беріледі. Олар сегмент және ығысу деп аталады.
Дербес компьютер жадынан әрбір тұрақ төрт байт орын алады. Тұрақтың алғашқы екі байтын оның сегменті, ал соңғыларын ығысу деп атайды. Сегмент - жады аумағы, оның ұзындығы 65536 байт (64 Кбайт) және ол физикалық тұрақтан басталады. Олар көрсеткіш мәнінің жедел жадыдағы орнын толық анықтайды. Сегмент көрсеткіш мәнінің алғашқы байтын көрсетсе, ығысу байт санын анықтайды.
Дербес компьютердің тұрақ аумағы 1 Мбайтты құрайды. Дербес компьютердің қазіргі заманғы процессорлі компьютерлерде 80386 және одан да көп тұрақ Турбо Паскальда 1 Мбайт шеңберінде тұрақтандыру үшін 20 екілік разряд керек, олар екі он алты разрядтық сөздерден (сегмент және ығысу ) келесі ретпен құрылады (1 – сурет ): сегмент құрамы солға төрт разрядқа ығысады, босаған оң разрядтар нөлмен толады, жауабы ығысу құрамына қосылады.
Жадының 16 байттық фрагменті параграф деп аталады, сондықтан, сегмент жадыны параграф нақтылығымен тұрақтандырады деп айтуға болады. Әр сегментке үздіксіз және жеке тұрақтандырылған жады обласы сәйкес келеді. Сегменттер жадыда бірінен соң бірі үзіліссіз немесе бірнеше интервалмен, немесе бір - бірін жауып жүруі мүмкін.
Сегмент
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
+
Ығысу
=
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
Адрес
19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
1- сурет. ДК – ң тұрағының құрылу схемасы.
Сонымен, өзінің ішкі құрылысы бойынша кез келген көрсеткіш сегмент немесе ығысу арқылы берілген екі сөзінің қосылуын білдіреді. Көрсеткіш көмегімен динамикалық ұғым принципінде кез келген Турбо Паскальда белгілі мәліметтер типін орналастыруға болады. Олардың тек кейбіреуі ғана (Byte, Char, Shortint, Boolean) 1 байт орын алады, ал басқалары - бірнеше көршілес орын алады. Сондықтан іс жүзінде көрсеткіш тек алғашқы мәлімет байтын тұрақтайды.
Негізінде, Турбо Паскальда көрсеткіш кейбір мәлімет типімен байланыстырылады. Бұндай көрсеткіштерді типтендірілген деп атаймыз. Типтендірілген көрсеткіштерді анықтағанда тип атының алдына ^ таңбасы тіркеледі:
< Көрсеткіш айнымалысының аты > : ^ < базалық тип > ; Көрсеткіштің базалық типіне ешқандай шектеу қойылмайды. Көрсеткіштің бір ғана тұрақты nil мәні бар, ол айнымалы мәнінің жоқ екендігін білдіреді. Сілтемелерді nil мәнімен, не өзара салыстыруға да болады. Типтері бірдей болғанда ғана сілтемелердің біреуінің мәнін екіншісіне беруге де рұқсат етіледі. Турбо Паскальда көрсеткішті анықтай отырып, оны қандай да бір нақты мәлімет типімен байланыстырмаса да болады. Сол үшін Pointer стандартты типі қызмет істеді;
< Көрсеткіш айнымалысының аты > : pointer.
Көрсеткіштің мұндай түрін типтендірілмеген деп атаймыз. Типтендірілмеген көрсеткіштер нақты типпен байланысты еместіктен, олардың көмегімен құрылымы мен типі программа барысында өзгеріп отыратын мәліметтерді динамикалық орналастыру ыңғайлы.
Жоғарыда айтылғандай, көрсеткіш мәні жадыдағы айнымалылар тұрақтары болып табылады, сондықтан бір көрсеткіштің мәнін басқа көрсеткішке беруге болатынын күтуге болады. Бірақ іс жүзінде бұл дәл осылай емес. Турбо Паскальда мәндерді тек бірдей мәлімет типімен байланысты көрсеткіш арасында беруге болады.
Егер, мысалы :
var
p1,p2:^integer;
p3:^real;
pp:pointer;
алайда p1:=p2 ;
меншіктеуге болады, ал осы кезде
p1 : = p3;
болмайды, себебі p1 және p3 әр түрлі мәлімет типін көрсетеді. Бұл алайда, шектеу типтедірілмеген көрсеткіштерге таралмайды, сондықтан бізге
pp : = p3 ;
p1 : = pp; деп жазып, керек шешім алуға болар еді.
Динамикалық ұғымды ерекшелеу және босату. Барлық Турбо Паскальда динамикалық ұғым массив байттары ретінде қарастырылады. Оларды үйінтек деп атайды. Үйінтек үлкен тұрақта , жады облысынан кейін орналасады, оны программа денесі алып тұрады.
Үйінтек басы стандартты айнымалы HEAPORG – та (2 - сурет), соңы - айнымалы HEAPPTR көрсеткіші көрсетілед. Кез келген динамикалық орналастырылған айнымалы жадысы New процедурасымен ерекшелңнеді. Осы процедураға жүктелу параметрі типтелген көрсеткіш динамикалық тұраққа сәйкес мағына алады.
Содан бастап мәліметтерді орналастыруға болады.
Мысалы:
Var
I , j : ^ integer;
R : ^ real;
Begin
New (i); … end.
Үлкен тұрақ
Жүйелік
аймақ
Үйінтек
программа
Жүелік
аймақ
HeapEn
HeapPt
HeapOrg
Кіші тұрақ
Осы көрсеткіштің фрагменті орындалғаннан кейін I HEAPPTR үйінтек көрсеткішінің мәнін алады, ал HEAPPTR өз мәнін екіге арттырады, себебі I көрсеткішімен байланысты INTEGER – нің ішкі көрінісінің ұзындығы 2 байтқа тең. Оператор
New (r ); Қайтадан HEAPPTR көрсеткішінің ығысуына әкеп соғады, бірақ енді 6 байтқа, себебі REAL типінің ішкі көрінісінің ұзындығы осындай. Осындай ретпен басқа да кез келген типтің айнымалылары үшін жады ерекшелінеді.
Көрсеткіш кейбір мән алғаннан кейін, яғни, жадының нақты физикалық байтын көрсете бастауы, сондай- ақ тұрақ кез келген сәйкес типтің мәнін орналастыра алады. Ол үшін көрсеткіштен кейін ешқандай бос орынсыз ^ белгісі қойылады, мысалы :
I ^ : = 2 I ұғымының обылысына 2 мәні орналастырылған
R ^ : = 2 * pi ; r ұғымының обласына 6.28 мәні орналастырдық.
Осылайша, көрсеткіш көрсететін мән, яғни үйінтекте орналасқан мәлімет, ^ белгісімен белгіленіп, көрсеткіштен кейін қойылады. Егер көрсеткіштен кейін ^ белгісі қойылмаса, онда бұл мәлімет орналасқан тұрақты білдіреді. Осы туралы ойланудың мәні бар : кез келген көрсеткіштің мәні тұрақ болып табылады, ал әңгіме тұрақ туралы емес, осы тұрақта орналасқан мәлімет туралы екенін көрсету үшін көрсеткіштен кейін ^ қойылады. Егер осыны нақты түсініп алса, динамикалық ұғым принципімен жұмыс істеуде кедергі болмайды.
Динамикалық орналасқан мәліметтерді программаның кез келген жерінде, константтар мен сәйкес типті айнымалыларды орналастыруға болатын жерінде қолдануға болады. Мысалы:
R ^ : = sgr (r ^) + I ^ - 17;
Ешқашан мұндай оператор болмайды :
R : = sgr (r ^) + I ^ - 17;
R көрсеткішіне нақты мән меншіктеуге болмайды. Сол сияқты бұндай оператор болмайды:
R ^ : = sgr (r );
R көрсеткішінің мәні тұрақ болып табылады, және оны квадратқа енгізуге болмайды. Мынандай меншіктеу қате болады:
R ^ := I ;
R көрсеткіші көрсететін мәліметтеріне көрсеткіш мәнін меншіктеуге болмайды.
Динамикалық ұғымды үйінтектен алып қана қоюға болмайды, оны қайтаруға да болады. Ол үшін Dispose процедурасы қолданылады. Мысалы:
Dispose (r );
Dispose (I );
Операторлары үйінтекке бұрыш I және R көрсеткіштерімен ерекшелінген 8 байтты қайтарады.
Айтып кетейік, Dispose (RTR ) процедурасы RTR көрсеткішінің мәнін өзгертпейді, тек қана үйінтекке бұрын осы көрсеткішпен байланысты болған ұғымды қайтарады.
Алайда, процедураны бос көрсеткішке қайталап қолдану орындалу периодында қате пайда болуына әкеп соғады. Босаған көрсеткішті програмист резервтелген сөз NIL - мен белгілеуі болады. Қандай да бір көрсеткіш белгіленген бе әлде жоқ па екенін келесі жолмен тексеруге болады:
Const
P : ^ real = NIL ;
begin
. . . . .
if p = NIL then
new (p );
. . . . .
dispose (p);
p: = NIL ;
, . . . .
end.
Басқа көрсеткіштермен ешқандай салыстыру операцияларын істеуге болмайды.
Жоғарыда келтірілген фрагмент көрсеткішті анықтауының типтелген константа түрін бір уақытта оған Nil мәнін меншіктеу арқылы көрсетеді. Көрсеткіштің бастапқы мәні еркін болуы мүмкін айта кету керек. New процедурасының мәні меншіктелген көрсеткіштерді қолдану жүйемен қадағаланбайды, ол күтпеген шешімдерге әкеп соғуы мүмкін.
NEW және DISPOSE процедураларын меншіктелуінің қайталануы ұяшықталынған құрылымға әкеп соғады. Өйткені барлық программалар үйінтек әкімдігі деген ерекше көмекші программаның басқаруымен орындалады. Ол автоматты түрде сөздің программаңызға тіркелген және үйінтектегі бос фрагменттердің есебін жүргізеді. New процедурасына қайтадан меншіктелгенде бұл көмекші программа керекті айнымалы орналаса алатын ең аз бос фрагмент іздейді. Табылған фрагменттің тұрақ басы көрсеткішке оралады, ал көрсеткіштің өзі немесе оның керекті ұзындықты бөлігі үйінтектің бос емес бөлігі ретінде белгіленеді.
Басқа мүмкіншілігі - толық үйінтек фрагментінің босауы да. Осы мақсатпен динамикалық ұғымды ерекшелеу алдында. HEAPTR көрсеткішінің ағымды мәні MARK процедурасының көмегімен айнымалы - көрсеткіште есте сақталады. Енді кез келген уақытта MARK процедурасы еске сақтаған тұрақтан бастап, динамиканың ұғымының аяғына дейін үйінтек фрагментін босатуға болады. Ол үшін RELEASE процедурасы қолданылады.
Мысалы:
Var
P, p1, p2,
P3, p4, p5 : ^ integer;
Begin
New (p1) ;
New (p2) ;
Mark (p );
New (p3);
New (p4);
New (p5);
. . . . . .
release (p);
end.
Бұл мысалды HEAPPTR ағымды айнымалысы MARK (P)
процедурасы арқылы P көрсеткішіне орналастырылған, алайда жады айнымалыға резервтелген жоқ.
Release (P) динамикалық ұғымды белгіленген жерден бастап үйінтек басына дейін босатты. 3 – сурет NEW - DISPOSE және NEW - MARK - RELEASE процедураларының қаралған және RELASE (P) операторының орнына DISPOSE (P) үшін қолданылатын жағдайға жұмыс механизімін бейнелейді.
p1^
p2^
p3^
p4^
p5^
p1^
p2^
p1^
Mark(p) Dispose(p) Release (p)
3 – сурет. Динамикалық ұғым құрылымы
а) босау алдында; б) DISPOSE(P3)-тен кейін; в) RELEASE(P)-тен кейін;
Ескере кету керек, RELEASE – ты шақыру DISPOSE процедурасымен құрылған үйінтектегі бос фрагмент тізімін жояды. Сондықтан екі бірдій жадыны босату механизмін бірге бір программа көлемінде қолдану ұсынылады. Бұрын айтылғандай NEW процедурасының параметрі тек қана көрсеткіш бола алады. Типтелмеген көрсеткішпен жұмыс істеу үшін:
GETMEM (P,SIZE) – жадыны резервтеу
FREEMEM (P,SIZE) – жадыны босату
қолданылады.
Мұндағы P – типтелмеген көрсеткіш;
SIZE – үйінтектің керекті немесе босатылатын бөлігінің байтпен берілген көлемі.
GETMEM процедурасының үйінтекке бір жүктелуінде 65521 байтқа дейін динамикалық ұғымды резервтеуге болады.
GETMEM - FREEMEM процедурасын қолдану және динамикалық ұғыммен жұмыс ерекше абайлылықты және қарапайым ережелерді тиянақты орындауды қажет етеді: қанша жады резервтелсе, сонша жады босату керек, қай тұрақтан резервтелсе, сол тұрақтан босатылу керек.
Турбо Паскальда типтелмеген көрсеткіштердің бар болуы типтердің білінбейтін қалыптасуына кең мүмкіндік береді. Өкінішке орай NEW және DISPOSE процедураларында атауларды дұрыс қолданбаудан программада кеткен қателіктерді табу қиын, және де ол қаламайтын тип қалыптасуына әкеп соғуы мүмкін. Іс жүзінде, мынандай программа бар болсын:
Var
i,j : ^ integer;
r : ^ real;
begin
new (i); {i:=HeapOrg; HeapPtr:= HeapOrg+2}
j:=i; {j:= HeapOrg}
j^:=2;
dispose(i); { HeapPtr:= HeapOrg }
new(r); { r:= HeapOrg; HeapPtr:= HeapOrg+6}
r^:=pi;
writeln(j^) { ?? }
end.
Экран бетіне шығады? Бұл сұраққа жауап беру үшін HEAPPTR көрсеткішін бақылайық. Программа орындалуы алдында бұл көрсеткіш I көрсеткішіне сосын I көрсеткішіне жіберілген HEAPORG үйінтегінің тұрақ басының мәнін қабылдаған. DISPOSE(I) – ды орындаған соң үйінтектің көрсеткіші қайтадан HEAPORG мәнін қабылдайды. Бұл тұрақ NEW(r) процедурасында R көрсеткішіне жіберілген. R көрсеткішіне π=3,14159 саны орналасқан соң, үйінтектің бірінші 2 байты осы санның ішкі көрінісімен толған болып шықты. Ал J әлі де HEAPORG – ның тұрағын сақтайды, сондықтан оператор WRITELN(J^) π санының 2 байтын бүтін санның ішкі көрінісі ретінде қарастырады. (Себебі J бұл INTEGER типіне көрсеткіш) және 8578 шығарады.
Көрсеткіштерді қолдану. Біраз қорытынды жасайық. Сонымен, динамикалық ұғым 200 … 300 немесе одан да көп Кбайт құрайды, оның басы HEAPORG айнымалысында сақталады, ал соңы HEAPEND айнымалысының тұрағына сәйкес келеді. Динамикалық ұғымның бос аймағының ағымды тұрағы HEAPPTR көрсеткішінде сақталады.
Үлкен мәліметтер массивін орналастыру үшін динамикалық ұғымды қалай пайдалану керек екені қарастырайық. Мысалы, 100x200 EXTENDED типті тікбұрышты .....
Толық нұсқасын 30 секундтан кейін жүктей аласыз!!!
Әлеуметтік желілерде бөлісіңіз:
Facebook | VK | WhatsApp | Telegram | Twitter
Қарап көріңіз 👇
Пайдалы сілтемелер:
» Туған күнге 99 тілектер жинағы: өз сөзімен, қысқаша, қарапайым туған күнге тілек
» Абай Құнанбаев барлық өлеңдер жинағын жүктеу, оқу
» Дастархан батасы: дастарханға бата беру, ас қайыру
Соңғы жаңалықтар:
» 2025 жылы Ораза және Рамазан айы қай күні басталады?
» Утиль алым мөлшерлемесі өзгермейтін болды
» Жоғары оқу орындарына құжат қабылдау қашан басталады?