- •Структуры даных і праца з імі сродкамі мовы Pascal Парадкавыя тыпы
- •Мноствы
- •Тыпізаваныя канстанты тыпу «мноства»
- •Дзеянні над масівамі
- •Дзеянні над элементамі масіву
- •Пераменныя тыпу «масіў» са стартавым значэннем, ці тыпізаваныя канстанты-масівы
- •Канстанты з тыпам «масіў»
- •Камбінаваны тып «запісы»
- •Змяненне (прывядзенне) тыпаў і значэнняў
- •Радкі сімвалаў
- •Наданне значэння радкам
- •Радковыя выразы
- •Рэдагаванне радкоў
- •Пераўтварэнне радкоў
Камбінаваны тып «запісы»
Гэты тып даных больш падрабязна разгледзім далей. Цяпер зробім такое азначэнне запісу.
Запіс – гэта структура неаднародных даных, у якой ёсць найменныя палі розных тыпаў.
Для азначэння запісу прымяняюць службовыя словы RECORD і END.
Напрыклад, наступны запіс мае сваімі палямі рознахарактарныя даныя:
TYPE
Person=RECORD
F_I_O : STRING;
{прозвішча, імя, імя па бацьку 255 сімвалаў}
Ves, Rost : Real;
Telephone : Longint; {нумар тэлефона}
Ozenki : ARRAY[1..4] OF Byte;
END;
Тып Person цяпер задае даныя з радка (F_I_O), двух лікаў з дробавай часткай (Ves, Rost), аднаго цэлага доўгага ліку.
VAR Nehta : person;
Пад іменем Nehta разумеецца данае з канкрэтнымі значэннямі. Доступ да палёў здзяйсняецца пры дапамозе селектара запісу:
імя_пераменнай.імя_поля
Nehta.F_I_O – гэта значэнне радка з прозвішчам.
Nehta.Telephone – тэлефон.
Палямі запісаў можа быць што заўгодна, нават іншыя запісы, а колькасць палёў – вялікай. У адрозненне ад масіваў і мностваў палі запісу могуць мець розныя тыпы. Доступ да палёў адбываецца па імені.
Пры заданні першапачатковых значэнняў даным тыпу «запіс» робяць так:
CONST Htosti : person=(F_I_O : 'XXX'; Ves : 50.5;
Rost : 158; Telephone : 265539;
Ozenki : (5,4,3,4));
Поле ад свайго значэння аддзяляецца знакам «:». Парадак чаргавання палёў павінен адпавядаць парадку іх апісання ў тыпе, палі павінны раздзяляцца не коскай, а «;», як гэта робіцца ў апісанні тыпу «запіс».
Падрабязна гэты тып разгледзім потым.
Змяненне (прывядзенне) тыпаў і значэнняў
У мове Pascal існуе вельмі магутны сродак, які дазваляе абысці ўсе магчымыя абмежаванні на сумяшчальнасць тыпаў ці значэнняў (напрыклад, у аператары «:=»). Гэта аперацыя прывядзення тыпаў. Яна прымяняецца толькі для пераменных і значэнняў.
Сутнасць гэтай аперацыі ў наступным. Пры вызначэнні тыпу мы вызначаем форму захавання інфармацыі ў аператыўнай памяці, і пераменная дадзенага тыпу будзе прадстаўлена ў памяці наперад вядомай структурай. Але калі «паглядзець» на яе вобраз у памяці з пункту гледжання машыннага ўяўлення другога тыпу, тады можна будзе трактаваць тое ж самае значэнне як значэнне, прыналежнае да другога тыпу.
Фармат аперацыі прывядзення тыпаў:
Імя_тыпу (пераменная_ці_значэнне);
Гэта імя_тыпу павінна быць вядома ў праграме (азначана праграмістам або стандартнае).
Прывядзенне тыпаў не перавызначае тыпы пераменных, а толькі дае магчымасць парушыць правілы сумяшчэння тыпаў пры ўмове, што адпаведныя значэнні сумяшчальныя ў машынным уяўленні.
Прыклад.
VAR Si : 0..255;
Тады аператар Si:='A' дасць памылку на этапе кампіляцыі, а аператар Char(Si):='A' дазволіць зрабіць наданне значэння. Магчымы і другі падыход: Si:=Ord('A'), у гэтым выпадку вынік вяртаецца як Byte.
Аналагічна змяненню тыпу пераменных можна змяняць уласна тып значэнняў, а таксама выніковы тып выразаў, г. зн. дазволены такія пераўтварэнні:
Boolean(1) |
Гэта лагічнае значэнне TRUE |
Longint(1) |
Гэта 1, размешчаная ў 4 байтах |
Char(130-1) |
Сімвал з кодам ASCII нумар 129 |
Integer('Y') |
Код сімвала 'Y' у фармаце Integer, (ord('Y') вяртае вынік як Byte) |
Новы тып можа быць даўжэйшым ці карацейшым, чым першапачатковы тып значэння.
Прывядзенне тыпаў як пераменных, так і значэнняў – нетрывіяльная аперацыя. Яна патрабуе даволі высокага ўзроўню ведаў тэхнічных падрабязнасцей мовы. Напрыклад, трэба ведаць, як захоўваюцца складаныя тыпы даных (масівы, запісы, мноствы), адрасы, лікі, радкі ў памяці, якія памеры ім адводзяцца. Прывядзенне тыпаў мае сэнс толькі пры супастаўнасці машынных уяўленняў значэнняў. Успомнім, што цэлыя і сапраўдныя значэнні маюць зусім рознае машыннае кадзіраванне. Значыць, прывядзенне цэлых пераменных да сапраўдных тыпаў і наадварот – вельмі рызыкоўная аперацыя.
Калі адзін парадкавы тып пераўтвараецца ў іншы, такое пераўтварэнне можа прывесці да ўсячэння ці павелічэння памераў памяці, пры параўнанні з зыходным значэннем. Пры гэтым можна атрымаць «дрэнныя» адказы:
VAR li : Longint; i : Integer;
BEGIN
li := 1234567; {>32767}
I := Integer(li+1);
Writeln(i);
END.
Першапачаткова ў пераменнай l маем: (1 234 567)10 = (12D 687)16 Longint. Пераменная lі атрымае значэнне двух апошніх байтаў, пры гэтым старэйшы біт гэтага поля змяшчае значэнне 1, г. зн. пераменная і будзе мець адмоўнае значэнне і надрукуецца –10 616. Гэта добра відаць з наступнай схемы.
Заўвага 1. Пры прывядзенні значэння ў больш шырокі тып (напрыклад, Longint(1)) значэнні будуць цалкам запісаны ў малодшыя байты, калі ж значэнне прыводзіцца да больш кароткага тыпу, ад яго бяруцца зноў жа малодшыя байты (а старэйшыя ігнаруюцца). У такім выпадку прыведзенае значэнне можа не раўняцца зыходнаму.
Прыклад. Вынік выканання Byte(534)будзе роўны 22;
534 кадзіруецца ў тып Word як 2 162 + 22 = 2 162 + 16 + 6. Значыць,
53410 = 21616.
0 |
2 |
1 |
6 |
Малодшы байт (16)16 = 16 + 6 = 22 мы атрымалі, а старэйшы – асноўны – згубіўся.
Заўвага 2. Калі зыходнае значэнне адмоўнае, а зададзены тып пашырае памер яго захавання, тады знак будзе захоўвацца.
Калі ж практычна трэба карыстацца аперацыяй прывядзення тыпаў? Тады, напрыклад, калі працуем на мяжы значэнняў для дадзенага тыпу.
VAR A, B : Word;
BEGIN
A := 55000;
B := A-256;
Write ( А + B );
Паколькі А + В 65535, а А + В дае тып выразу Word, значыць, вынік дзеяння Word(A+B) заведама дрэнны. Выправім гэтую сітуацыю так:
Write(Longint(A)+B)