6. Деклариране на нови типове в Pascal. Тип диапазон. Масиви: едномерни, двумерни и тримерни масиви. Индексиране на масив. Обхождане на масив.
  Освен вградените в езика типове като integer, real, char и др. програмистът може да дефинира нови типове. Дефинирането на нови типове става в декларативната част на програмата преди декларирането на променливи и след декларирането на константи. То започва с резервираната дума type и следват дефинициите на новите типове. Дефиницията на нов тип има вида

    нов_тип = дефиниция;

Новият тип може да се ползва за дефиниране на променливи от този тип.

Пример 6.1:

    type
        broj_studenti = integer;
        zaveril = boolean;
        ocemka = real;
    var
        n: broj_studenti;
        sem, god: zaveril;
         uspeh: ocenka;

В този пример имаме всъщност предефиниране на съществуващи типове. Това понякога се прави с цел по-добра четаемост на програмата. По-нататък ще бъдат показани по-сложни дефиниции на нови типове.

Тип диапазон. Този тип се дефинира въз основата на изброим тип данни. Изброими данни са тези, които за всяка тяхна стойност може да се посочи, коя е следващата или предходната стойност и между две поредни стойности няма трета между тях. Такива са вградените типове integer, boolean и char. Например: при integer след 5 следва 6 и между тях няма друго цяло число. real не е изброим тип. Ако си спомняте в оператор case се ползва израз от изброим тип. Тип диапазон се дефинира по следния начин

    начална_стойност .. крайна_стойност

където начална_стойност е константа задаваща началото на диапазона, а крайна_стойност е константа задаваща неговия край. Трябва да е изпълнено, че 

    начална_стойност Ј крайна_стойност.

Между начална_стойност и крайна_стойност се поставят точно две последователни точки "..". Те са една буква от езика Pascal и не могат да се разделят една от друга с интервал, нов ред и т.н..

Пример 6.2:

    type
        mesec = 1 .. 12;
        sedmica = 1 .. 7;
    var
        m: mesec;
        day: sedmica;
         glavna_bukva: 'А'  .. 'Я';

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

Масиви. Данните, с които работи една програма, са единични (скаларни) данни и структури от данни. Единични данни са число, буква или логическа стойност. Скаларни типове са вградените типове integer, real, char и boolean, а също и тип диапазон. 

Дефиниция 6.1

Структури от данни са организирани и подредени по някакви правила съвкупности от данни. Те биват статични и динамични. Статични са такива структури, чието организация и брой елементи се задава при тяхната дефиниция и не може повече да се променя. 

Езикът Pascal подържа следните вградени структури:

Дефиниция 6.2 Масив е крайна, наредена съвкупност от еднотипни данни. 

Еднотипните елементи на масива могат да бъдат, както скаларни данни, така и структури от данни с изключение на файлове. Те могат да са, както от вградените в езика типове, така и от типове дефинирани от програмиста. Според наредбата на елементите си масивите биват едномерни, двумерни, тримерни и т. н. Масивът е статична структура от данни. Броят на елементи му се задава при неговата декларация и трябва да бъде константен. Могат да се дефинират типове-масиви и направо променливи-масиви.

Едномерни масиви. Променлива едномерен масив се дефинира по следния начин

    име: array [целочислен_диапазон] of тип;

където целочислен_диапазон определя, от къде до къде се изменят номерата (индексите) на елементите на масива, а тип определя типа на тези елементи. Границите на диапазона трябва да са целочислени константи и от тях и от типа компилатора определя, колко памет да отпусне за масива. Едномерният масив отговаря на математическото понятие вектор.

Пример 6.3:

    const
        max = 100;
    type
        diapazon = 1 .. max;
        masiv = array [ diapazon ] of integer;
    var
        a: masiv;
         b, c: array [-3 .. 4] of real;

Масивът a е от 100 цели числа, а масивите b и c са от по 8 реални числа.

Вътре в тялото на програмата се работи с елементите на масива по същия начин както с променливи от съответния тип. Обръщението към отделните елементи става по следния начин

    име[индекс]

където име е името на променливата масив, а индекс е целочислен израз със стойност в диапазона на номерацията на неговите елементи. Програмистът внимателно трябва да следи индекса да не излиза извън рамките на този диапазон, защото в едни случаи това води до прекъсване на програмата, а в други - до погрешна работа на програмата.

Пример 6.4 ( виж Пример 6.3):

    var
        i, j: integer;
    begin
         ..........
         readln(a[2 * i + j - 1]);     { стойността на 2*i + j - 1 трябва да от 1 до 100 }
         b[-2] := -5.3;
          c[5] := b[-2] / 4;             { Грешка ! Индекс 5 е извън диапазона на c. }
          for i := 1 to max do
             writeln(a[i]);
        .............
    end.

Една от най-често използваните дейности с масиви е обхождане на масив. Обхождане на една структура е достигане с някаква цел до всеки неин елемент. Обхождането на едномерен масив става чрез цикъл - обикновено for. В края на последния пример се обхожда масива а, с цел извеждане на екрана всички негови елементи.

Задача 6.1. Да се изчисли следната формула , където .

Анализ
Входни данни: N>0 цяло,
                           a1, a2, ..., aN - реални.
Изходни данни 

Алгоритъм

    Начало
        1. Повтаряй                         ;контролира се въведеното N>0
            Въведи N
        докато N > 0
        2. s <- 0
        3. За i<-1 до N повтаряй     ;въвеждат се елементите на а и се сумират в s
            Въведи ai
            s <-s + ai
        4. s <- s / N
        5. G <- 0
        6. За i<-1 до N повтаряй     ;намира се сумата вътре във формулата
            G <- G + (ai+s)2
        7. 
        8. Изведи G
    Край

Програма

program deviation;
    uses WinCrt;
    const max = 100;
    var
        a: array [1 .. max ] of real;
        s, g: real;
        i, n: integer;
    begin
        repeat     { контролера се n да е в границите на масива }
             write( ' N = ' );
             readln( n );
         until (n > 0) and (n <= max);
        s := 0;
         for i := 1 to n do begin
            write( 'Въведете ', i, '-то число:');
            readln( a[i] );
            s := s + 1;
        end;
        s := s / n;
        g := 0;
         for i := 1 to n do
            g := g + sqr(a[i] + s);
        g := sqrt(g / n);
        writeln('G = ', g:10:4);
    end.

Забележка. sqr е библиотечна функция за повдигане на квадрат.

Двумерен масив. В този масив елементите са подредени по редове и стълбове. Той отговаря на математическото понятие матрица или таблица. Променлива двумерен масив се декларира по следния начин

    име: array [целочислен_диапазон1, целочислен_диапазон2] of тип;

където целочислен_диапазон1 задава диапазона на номерация на редовете на масива, а целочислен_диапазон2 - на стълбовете.

Пример 6.5:

    const
        max = 100;
    type
        diapazon = 1 .. max;
        masiv2d = array [diapazon, diapazon ] of integer;
    var
        m: masiv2d;
         x, y: array [-3 .. 4, -1 .. 9] of real;

Масивът m е от 10 000 цели числа, а масивите x и y са от по 88 реални числа.

Обръщението към елемент но двумерен масив става чрез два индекса:

    име[ индекс1, индекс2]

където индекс1 и индекс2 са целочислени изрази със стойности съответно в целочислен_диапазон1 и целочислен_диапазон2. И в този случай програмистът трябва да следи тези стойности да не напускат съответните диапазони.

Пример 6.6 ( виж Пример 6.5):

    var
        i, j: integer;
    begin
        ...............
        m[25, 34] := 143;
        i := 10;
        j := 15;
        x[i - 7, j div 5 -1] := 3.43;
         for i := -3 to 4 do
              for j := -1 to 9 do
                 readln( y[i, j\);
        ....................
    end.

Обхождането на двумерен масив става чрез двоен цикъл т. е. цикъл вътре в тялото на друг цикъл. В последния пример имаме обхождане на масива y с цел въвеждане на стойности на елементите му от клавиатурата. Обхождането на двумерни масиви става по два начина: по редове и по стълбове. В горния пример имаме обхождане по редове, където във външния цикъл се изменя първия индекс (за редовете), а във вътрешния цикъл се изменя втория индекс (за стълбовете). Т. е. за i-то завъртане на външния цикъл имаме i-ти ред и с вътрешният цикъл преминаваме през елементите на този ред. При обхождане по стълбове във външния цикъл се изменя втория индекс, а във вътрешния - първия.

Задача 6.2. Дадена е таблица от N реда и M стълба с реални числа. Да се състави програма, която изчислява сумите от стълбовете на таблицата, входните данни и резултатите да се покажат в табличен вид.

Анализ

Входни данни: N > 0, M > 0 - цели,
a1,1, a1,2, ..., a1,M
a2,1, a2,2, ..., a2,M
.............
aN,1, aN,2, ..., aN,M - реални

Изходни данни
a1,1, a1,2, ..., a1,M
a2,1, a2,2, ..., a2,M
.............
aN,1, aN,2, ..., aN,M
----------------------------------
b1, b2, ..., bM
Знание: 

Алгоритъм

    Начало
        1. Повтаряй
            Въведи N, M
        докато N > 0 и M > 0
        2. За i <-1 до N повтаряй     ;Двоен цикъл - обхождане на a по редове
            За j <- 1 до M повтаряй
                Въведи ai,j
        3. За j <-1 до N повтаряй     ;Двоен цикъл - обхождане на a по стълбове
            bj <- 0                                 ;Сумиране на стълбовете в масива b
            За i <- 1 до M повтаряй
                bj<- bj + ai,j
        4. За i <-1 до N повтаряй     ;Двоен цикъл - обхождане на a по редове
            За j <- 1 до M повтаряй
                Изведи ai,j
            Изведи нов ред
        5. За j <- 1 до M повтаряй
            Изведи bj
    Край

Програма

program tablesum;
    uses WinCrt;
    const max = 100;
    var
        a: array [1 .. max, 1 .. max ] of real;
        b: array [1 .. max ] of real;
        i, j, n, m: integer;
    begin
        repeat     { контролера се n и m да са в границите на масива }
            write( ' N = ' );
            readln( n );
            write( ' M = ' );
   
         readln( m );
         until (n > 0) and (n <= max) and (m > 0) and (m <= max);
         for i := 1 to n do
             for j:= 1 to m do begin
                write( 'a[', i, ',', j, ']=');
                readln( a[i, j] )
            end;
         for j := 1 to m do begin
            b[i] := 0;
             for i := 1 to n do
                b[i] := b[i] + a[i, j]
        end;
         for i := 1 to n do begin
             for j:= 1 to m do
                write( a[i, j]: 8: 2);
            writeln
        end;
         for j:= 1 to 8 * m do
            write( '-' );
        writeln;
         for j:= 1 to m do
            write(b[j]: 8: 2);
    end.

Тримерни масиви. Те се декларират и ползват подобно  на двумерните. При декларирането си имат три диапазона за изменение на индексите си. При ползване към техните елементи се обръщаме с три индекса. Тримерните масиви се обхождат с троен цикъл.


Съдържание


5. Оператори за цикъл. Оператори за цикъл с брояч, с предусловие и с постусловие.


7. Подпрограми. Видове подпрограми в Pascal. Параметри на подпрограмите. Подпрограма процедура. Подпрограма функция. Локални и глобални величини в програмите. Предварително деклариране на подпрограма. Ползване на готови библиотеки от подпрограми. Рекурсия.