У вас вопросы?
У нас ответы:) SamZan.net

~ор~ал~ан блокты~ басы throw 1~рнек; -- б~л оператор ерекше жа~дайды оны ~~деушіге ла~тырады

Работа добавлена на сайт samzan.net:

Поможем написать учебную работу

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

Предоплата всего

от 25%

Подписываем

договор

Выберите тип работы:

Скидка 25% при заказе до 26.12.2024

А(5,5) матрицаны енгізу - шығаруды  көрсеткішпен орындау

М(7,5) матрицаның жолдарындағы элементтерінің қосындысын табуды көрсеткішпен орындау

try ... сatch  операторы

Ерекше жағдайларды өңдеуде программисттің дербес өңдеушілерді қолдануы үшін  try ... сatch  операторы пайдаланылады.

Жалпы жазылуы:

try 

  { //  «қорғалған блоктың»  басы 

      throw  1-өрнек;    // бұл оператор ерекше жағдайды оны өңдеушіге лақтырады.

      throw  2-өрнек;

       ...

      throw  n-өрнек;

   } //  «қорғалған блоктың»  соңы

catch(1-өрнектің типіне сәйкес айнымалының типі)

   {

      1-өрнекке сәйкес ЕЖ өңдеушінің коды

   }

catch(2-өрнектің типіне сәйкес айнымалының типі)

  {

      2-өрнекке сәйкес ЕЖ өңдеушінің коды

   }

catch(n-өрнектің типіне сәйкес айнымалының типі)

  {

     n-өрнекке сәйкес ЕЖ өңдеушінің коды

   }

мұндағы,  tryорындап көру, байқап көру»- пробовать, попытаться, деген мағынаны білдіреді) сөзімен басталып,  {…} фигуралы жақшаға алынған  программа мәтінінің фрагменттерін қорғалған блоктар немесе уақытша блоктар деп атайды, яғни ерекше жағдай туғызуы мүмкін программа коды осы қорғалған блокта орналасуы керек.

Келесі throw тастай салу, лақтырып жіберу»- бросать, кидать деген мағынаны білдіреді) операторының қызметі, бұл программистке ерекше жағдайды өзінің қажетіне қарай жасауына, генерациялауға (немесе лақтыруына) мүмкіндік береді, егер throw операторы қолданылмаса программадағы ЕЖ-ды C++-тің атқарушы жүйесі немесе стандарт функциялар генерациялайды. Бұл throw операторынан кейін тұрған өрнектің типі пайда болатын ЕЖ-дың типін анықтайды. throw операторын параметрсіз де қолдануға болады.  ЕЖ пайда болғаннан кейін ол блоктың жұмысы тоқтайды да ЕЖ-дың типіне сәйкес оны өңдеуші код ізделінеді.

Өңдеуші код catch  қызметші сөзінен басталады.  Содан кейін жай жақшаның ішінде ЕЖ типі көрсетіледі, егер жай жақшаның ішінде көп нүкте (...)  тұрса,  онда ол ол кез-келген ЕЖ –ды өңдей алады, мысалы:

catch(int i)

    {  

                   //  int типті ЕЖ өңдеуші код

    }

catch(char* str)

   {  

             // char*  типті ЕЖ өңдеуші код 

   }

catch (...)

  {  

                 //кез-келген типті ЕЖ өңдеуші код 

   }

try…_ finally   операторы

 try …_finally операторының (немесе қорғалған блогының) программадағы жазылуы:

                       try

                          {

                                          //қорғалған блок

                         }

                         _finally

                         {

                                    // ерекше жағдайлар туса да  орындалатын код

                         }

try…_finally   операторының try ... сatch  операторынан айырмашылығы,  finally бөліміндегі код,  ерекше жағдайлар туса да орындала беретіндігімен ерекшеленеді.

12.1- жаттығу.  Консолдық қосымшада қарапайым ерекше жағдайды  өңдеуді орындап көру.

Жаттығуды орындау:

Программалық код келесі түрде болады:

#include <vcl.h>

#include <iostream.h>

#include <condefs.h>

#pragma hdrstop

//---------------------------------------------------------------------------

#pragma argsused

int main()

{

    double d = 1.0;

for (int i=0; i<4; i++)

{

try

{

cout << «\n»<< "try-block  bastaldi..." <<«\n»;

switch (i)

{

case 0:

throw " goldi laktiru "; // char* типті  жолды лақтыру

case 1:

throw 5; // int.-бүтінді лақтыру.

default:

throw d; //  double –ді лақтыру.

}

// Келесі оператор ЕЖ байланысты орындалмай

cout<< "Byl try-block-ka bailanisti orindalmaidi" << «\n»;

} //  try-блоктың соңы

catch(int i)

{ // int типті ЕЖ өңдеуші код

cout << "Int laktirildi /thrown /: " << 1 << «\n»;

}

catch(char* str)

{ //char*  типті ЕЖ өңдеуші код

cout << "string-gol laktirildi: " << str << «\n»;

}

catch (...) { //Кез-келген ЕЖ өңдеуші код

cout << "kalgan type laktirildi."<< "Program will.terminate." << «\n»;

cin.ignore () ;

return -1; // Программадан шығу

}

cout<< "sikldin soni"<< «\n»;

} // циклдың соңы

cout << "progr soni" << «\n»; // Бұл операторлар орындалмайды себебі, үшінші catch (...) //программаны аяқтап тастайды 

return 0;

}

Бұл  мысалда цикл төрт рет орындалуы керек. Цикл ішінде і- цикл параметрінің мәндеріне сәйкес int, char* және  double типті ЕЖ шақыратын қорғалған блок орналасқан. і=0 болғанда  throw операторы char* типті жолды лақтырады, ал оны char* типті  екінші тұрған өңдеуші ұстап алады да, соған сәйкес жазуды шығарады, себебі кодта содан басқа ештеңе жазылмаған, тура сол сияқты і=1 болғанда  қорғалған блоктағы throw операторы int  типті  ЕЖ  лақтырады, оны бірінші тұрған catch(int i) өңдейді. і=2 болғанда   double  типті ЕЖ пайда болады, ал оған сәйкес catch  қарастырылмған, бірақ оны кез-келген жағдай үшін орындалатын үшінші catch (...) ұстайды және ондағы кодтағы cin.ignore () және return -1;  командалары программадан шығуды немесе   аяқтауды орындайды , яғни   цикл төртінші рет і=3 үшін орындалып үлгермейді.

Ағын кластары

 

 Жалпы, С++ программалаудың енгізу-алу жүйесі, <iostream>  тақырыбымен берілген  файлда анықталған  күрделі  кластар иерархиясының негізінде жүзеге асырылады.  Программа жазу барысында автоматты түрде құрылатын стандарт ағындардан басқа, файлдармен жұмыс жасау үшін айқын түрде  құрылатын ағындар да жиі қолданылады. Көптеген есептерді шығаруда бұл ағындарды  белгілі бір кластардың объектілері ретінде қарастырады. Программалаудағы енгізу-алуды жүзеге асыруда жиі  қолданылатын кластар, негізінен <iostream>  файлында сипатталған ios және streambuf класынан таратылады. Бұл ios класы жоғары деңгейдегі енгізу-алу операцияларын қамтамасыз ететін, форматтауды және енгізуші-алушы ағындарымен байланысты қателер мен статустық деректерді беруді жүзеге асыра алатын қасиеттер мен әдістерді қамтиды, ал streambuf класы ағындарды буферизациялауды және сыртқы құрылғылармен байланысты қамтамасыз етеді.

Төменде программалауда жиі қолданылатын ағын кластары көрсетілген:

  1.  ағындардың түпкі класы - ios  ;
  2.  енгізуші ағынның класы- istream;
  3.  алушы немесе шығарушы ағынның класы- ostream;
  4.  екі  бағыттағы ағын класы - iostream;
  5.  енгізуші  файлдық ағынның класы- ifstream;
  6.   алушы немесе шығарушы  файлдық ағынның класы - ofstream;
  7.  екі бағыттағы файлдық ағынның класы - fstream.

Бұл кластардың барлығына ортақ негізгі жарияланулар ios класында беріледі, сондықтан программаға <iostream>  тақырыбымен берілген  файлға сәйкес тақырыптық файл  iostream.h қосылып жазылады. Сол сияқты, ifstream, ofstream және fstream файлдық ағын кластарын пайдалану үшін программаға fstream.h  тақырыптық файлын кірістіреді.

Программалауда, жоғарыда айтылғандардан басқа жедел жадымен дерек алмасу үшін құрылатын istringstream — енгізуші жолдық ағын, ostringstream — алушы жолдық ағын және stringstream — екі бағыттағы жолдық ағын кластары қолданылады. Бұл кластарды пайдалану үшін программаға <sstream>  файлына сәйкес тақырыптық файл sstream.һ қосылуы керек.  

Бинарлық ағаш түріндегі құрылымдар

Граф-ағаш. Граф – бұл төбелердің және оларды өзара жалғастыратын немесе қосатын тікелей байланыстардың жиынтығы. Граф өзара байланысқан төбелердің қосары, мысалы (А,С), (А,В), (В,Е) және т.б. арқылы анықталады. Мысалы: бинарлық ағаш-графтың қарапайым түрі болып табылады.  Бұл мысалдағы A, B, C, D, E – графтың төбелері, ал ( A-B), (A-C), (B-D) және ( B-E) сәйкесінше төбелерді қосатын байланыстар болып табылады. Бұл арнайы құрылымдағы деректерді пайдалану сызықтық емес түрде жүреді деп айтуға болады және графты сызықтық емес құрылым деп атайды. Графтағы төбелердің қосары берілген болса, онда ол төбелердің бірінен екіншісіне баратын тікелей жол да берілген болып есептеледі. Бұл жол (немесе байланыс) бір бағытта тура болуы мүмкін бұл кезде оны доға деп атайды, яғни графтың доғасы деп аталады. Егер байланыс екі бағытта да мүмкін болса, онда мұндай байланысты қабырға, яғни жолды графтың қабырғасы деп атайды. Граф бір ғана төбеден де тұруы мүмкін. Бұл жағдайда ол төбенің өз-өзімен байланысын тұзақ, яғни графтың тұзағы деп атайды. Қабырғалар және тұзақ арқылы байланысқан төбелер сыбайлас деп аталады. Егер бір төбе басқа бірнеше төбелермен байланысқан болса бұл төбелерде өзара сыбайлас төбелер болып табылады. Егер графтағы барлық байланыстар (жолдар) қабырға түрінде анықталған болса, онда мұндай графты бағдарланбаған граф деп атайды, ал егер графтың байланыстарының барлығы доғалар түрінде болса, онда мұндай графты бағдарланған граф деп атайды. Мысалы, әуе жолдарының картасы бағдарланбаған графтың, ал алгоритмдердің блок- схемасы бағдарланған графтың мысалы бола алады. Бір төбе мен екінші төбені байланыстыратын қабырғалар мен доғалардың тізбегі маршрут – деп аталады. Сыбайлас екі төбе үшін маршрут қабырға немесе доға болып табылады. Егер графтың қандайда болмасын төбесі үшін басқа төбелер арқылы болса да әйтеуір сол төбенің өзіне қайтып әкелетін маршрут болса онда бұл маршрутты цикл деп атайды. Егер графтың ез келген екі төбесін байланыстыратын маршрут бар болса, онда мұндай графты байланысқан, керісінше жағдайда байланыспаған граф деп атайды.

Графтар үшін төрт амал қарастырылған:

1. Деректі енгізу, яғни графқа дерекі бар төбе қосу;

2. Граф төбелеріндегі орналасқан деректерді іздестіру;

3. Деректі графтан алып тастау, яғни графтың сол дерек тұрған төбесін жою;

4. Байланыстарға сәйкес граф төбелерін айналып өту;

Графтың қарапайым мысалы ағаш – құрылым болып табылады. Графтар теориясында ағаш деп – тұзақ және цикл түріндегі байланыстары жоқ болатын бағдарланбаған, байланысқан графты айтады, яғни ағаштың төбелері бір-бірімен қабырғалар арқылы байланысады. Ағаштың тармақтарын бұтақтар деп атайды да, бұтақтардың ұшындағы байланыспаған төбелерді жапырақтар деп атайды. Белгілі бір төбеден басталатын ағашты түбір ағаш деп, ал төбенің

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

Граф-ағаш екі түрлі жолмен құрылады:

Граф-ағаштың барлық төбелеріндегі және жапырақтарындағы барлық деректер бір мағынаны білдіреді (семантика);

Граф-ағаштың төбелеріндегі деректер бір мағынаны, ал жапырақтарындағы деректер басқа мағынаны білдіреді.

Егер ағаштың әрбір түйіндеріндегі немесе элементіндегі ұрпақтарымен байланыстыратын қабырғалар саны екеуден аспаса мұндай ағашты бинарлық ағаш деп атайды. Бинарлық ағаштарға графтардағы сияқты төрт амал қолданылады:

1. Деректі енгізу;

2. Деректі іздеу;

3. Деректі жою;

4. Ағашты айналу.

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

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

– Берілген деректі ағаштан іздеу: Бұл амалдың операндасы – берілген деректің мәні; Амалдың нәтижесі – true немесе false болады, яғни, true болады, егер дерекке сәйкес түйін немесе жапырақ табылса, false болады, егер ондай дерек табылмаса;

– Ағаштан деректі жою: Деректі жою үшін әуелі оны іздейді, егер ондай дерек табылмаса онда амал орындалмайды, ал дерек табылған жағдайда сол «түйін» немесе «жапырақ» қалған түйіндермен байланысын, ұрпақтармен байланысын қоса алғанда жойылады;

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

 Бір өлшемді массивтің жұп элементтерін табуда көрсеткішьерді пайдалану

int ar[] = {1, 8, 2, -1, -3, 12};

int* p = ar;

int s=0;

cout<<"jup elemennter=";

for (int i=0; i<=5; i++)       

{

if(*p%2==0)

 cout<<" "<<*p;

p++;

}

getch();

Бір өлшемді массивті сұрыптауда көрсеткіштерді пайдалану

int i,j, buf1, buf2;

int a[8]={10,6,8,9,1,2,4,7};

int *p;

for(i=0;i<7;i++)

{

 for(j=0;j<7-i;j++)

 {

   if(*(a+j)>*(a+j+1))

   {

     p=a+j;

     buf1=*p++;

     buf2=*p;

     *p--=buf1;

     *p=buf2;

   }

 }

}

for(i=0;i<8;i++)

cout<<" "<<a[i];

getch();

 

Бір өлшемді массив элементтерін кері ретпен шығаруда көрсеткіштерді пайдалану 

(a[6]={4,6,1,9,3,7} массиві берілген)

#include<iostream.h>

#include<conio.h>

int main()

{

int a[6]={4,6,1,9,3,7};//массивті жариялау және инициализациялау

int *k_masBasi=a;//массивтің алғашқы элементінің көрсеткіші

int *k_masSoni=&a[5];//массивтің соңғы элементінің көрсеткіші

while(k_masSoni>=k_masBasi)//әзірге соңғы адрес алдыңғыдан үлкен

{cout<<” ”<<*k_masSoni;//ендеше сол адрестегі мәнді алу

k_masSoni--;//алдыңғы адреске түсу

}

getch();

7 3 9 1 6 4

}

Жауабы:

Бір өлшемді массив элементтерінің қосындысын табуда көрсеткішті пайдалану

 int ar[] = {1, 3, 2, -1, -3, 13};

int* p = ar;

int s=0;

for (int i=1; i<=6; i++)

{

s=s+*p;

p++;

}

cout<<"\ns="<<s;

 getch();

Графиктік объектілерді тұрғызу.

Кластары

TBitMap, биттік матрица түрінде сақталатын кескін объектілері үшін анықталған;

TIcon, пиктограммалар түрінде сақталатын кескін объектілері үшін анықталған;

TMetafile, кескінді салу әдістері сақталатын объектілер үшін анықталған.

Бұл кластардың барлығы үшін түпкі класс ТGraphic класы болып табылады. TРicture класы – өзінде, жоғарыда көрсетілген үш кластың барлық мүмкіндіктерін қамти алады. Сондықтан TPicture класының, графиктік объектілері үшін

төмендегідей,

TPicture->TІcon;

TРicture->TМetafile;

ТРicture->TBitMap ;

қасиеттерді шақырып пайдалануға

болады.

Қасиеттері

Picture(TPicture) - бұл қасиет файлдағы кескінді Image терезесіне жүктейді. Image терезесінде суретті көруге ғана емес, сақтауға да болады.

AvtoSize (bool) - Егер бұл қасиет true мәнге ие болса, онда іmage компонентінің өлшемдері ол көрсететін кескін өлшеміне қарай келтіріледі.

Stretch (bool) - Егер бұл қасиет true мәнге ие болса, керісінше, кескін немесе сурет өлшемдері іmage компонентінің өлшемдеріне келтіріледі. Бұл қасиет пиктограммаларға әсер етпейді, себебі пиктограммалардың

өлшемдері өзгермейді.

Center (bool) - Егер бұл қасиет true мәнге ие болса, онда бұл кескін іmage компонентінің ортасында орналасады.

Transparent (bool) - Егер бұл қасиет true мәнге ие болса, онда кескін көрінбей тұрады, (түссіз болып кетеді), бұл әсіресе бір кескіннің үстіне екіншісін беттестіргенде жиі қолданылады. Бұл қасиет тек биттік матрицаларға ғана жүреді.

                      Динамикалық жады. new және delete амалдары

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

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

Динамикалық жады – программаның орындалуы кезінде жедел жадыдан берілетін, бірақ, программада әдейі қарастырылмаған болса, өздігінен пайдаланылмайтын бос тұратын жады бөлігі.(программистер арасында кейде «куча»--«HEAP» деп айтылады)

Динамикалық  жадыны пайдалану үшін тек қана көрсеткіштер түрінде жарияланатын динамикалық айнымалылар қолданылады.

Динамикалық айнымалылар, жарияланғаннан бастап  программа аяқталғанға дейін немесе  динамикалық жады әдейі босатылғанға дейін уақытта бар болып, программа жұмысына қатыса алады. С++ программалау тілінде динамикалық айнымалылармен жұмыс жасау үшін, негізінен new – жадыдан орын алу, delete – жадыдан алынған орынды босатып беру амалдары  қолданылады. Программалауда, динамикалық жадымен жұмыс жасау үшін С тілінен қабылданған <malloc.h> файлындағы функцияларды да қолдануға болады, бірақ new – delete амалдарының артықшылығы, оларды объектілер үшін де қолдана береді.

Программадағы деректер үшін динамикалық жадыдан алдын ала орындар алынады, ол үшін нақты көрсетілген типтерге new амалын қолданады, ол алынған орындағы алғашқы ұяшықтың адресі көрсеткіш түрінде анықталған динамикалық айнымалыға беріледі, мысалы:

int* n = new int; // динамикалық жадыдан int типті шама үшін орын алады және оның адресін n-ға береді

int* m = new int (10); //динамикалық жадыдан int типті шама үшін орын алады,

                   //ол орынға 10 деген мәнді жазып иницализациялайды және оның адресін m-ға береді

int* mas = new int [10];  //динамикалық  жадыдан int типті он шамаға немесе массив

                //элементтеріне орын алу, алғашқы ұяшық адресін массив аты болатын mas-ға беру

int* nC = (int *)malloc(sizeof(int));  // malloc функциясын пайдаланып динамикалық

                           // жадыдан int типті шама үшін орын алады және оның адресін nС-ға  береді.

Динамикалық жадыдан new амалының көмегімен алынған орынды босатып беру үшін delete амалы, ал malloc() функциясымен алынған орынды босату үшін free() функциясы қолданылады, мысалы:

delete n;       //динамикалық жадыдан int типті шама үшін алынған орынды босату

delete m;    //динамикалық жадыдан int типті шама үшін алынған орынды босату

delete [ ] mas;// int типті массивтің  он элементіне алынған барлық орынды босату

free (nC);           // malloc   функциясымен алынған орынды босату

Динамикалық массивтер.

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

Программа a[n] және  b[n] динамикалық массивтерді   динамикалық жадыға орналастыруда және оларға берілген орындарды босатуда new -delete  амалдарын қолдануды көрсетеді.

#include <iostream.h>

#include <conio.h>

int main()

{

   int n;

   cin>>n; //массивтердің өлшемін енгізу

   int* a = new int[n];    // a[n] массив элементтері үшін жадыдан орын алу

  cout<<"\n a massivi elementterinin   ";

   cout<<"\n ADRESTERI :     MANDERI : ";

   cout<<"\n ___________________________" ;

  for(int i=0; i<n;i++)

  {

   a[i]=random(7); // a[n] массивін құру

  cout<<"\n  "<<&a[i]<<"           "<<a[i];   // a[n] массиві элементтері орналасқан

                  //жады ұяшықтарының адрестерін және элементтердің мәндерін шығару

  }

 delete a; // a[n] массив элементтері үшін жадыдан алынған орынды босату

      //бұл амалды тоқтату үшін оның алдына екі слэш // таңбасы қойылса болды

  cout<<"\n\n  " ;

  cout<<"\n b massivi elementterinin   ";

   cout<<"\n ADRESTERI :     MANDERI : ";

   cout<<"\n ___________________________";

  int* b = new int[n];  // b[n] массив элементтері үшін жадыдан орын алу

     for(int i=0; i<n; i++)

  {

  b[i]=random(17); // b[n] массивін құру

 cout<<"\n  "<<&b[i]<<"       "<<b[i];   // b[n] массиві элементтері орналасқан

                 //жады ұяшықтарының адрестерін және элементтердің мәндерін шығару

  }

  getch();

}

Динамикалық матрица

Программа матрицаны немесе екі өлшемді динамикалық массивті matrix класы түрінде анықтауды және осы класс үшін қайыра жүктелген «меншіктеу» (=), «қосу» (+) және «көбейту» (*) амалдарының қызметтерін көрсете алады:

#include <iostream.h>

#include <conio.h>

class matrix   // matrix  класты жариялау басталды

{

    private:

    unsigned int  GOL;           //матрицаның жолдарының саны

    unsigned   int  BAGAN;   //матрицаның бағандарының  саны

    float **elemMat;          //матрица  элементіне көрсеткіш 

   public:

 matrix( unsigned int gol, unsigned int bagan);       //матрицаны құрушы  

                                                                     //конструктор-әдістің прототипін жариялау

 matrix engizu();          // құрылған матрицаны толтыратын немесе

                                            // элементтерінің мәнін енгізетін әдістің прототипі  

 void koru ();            // матрицаны баспаға шығарып көрсететін әдіс прототипі

          matrix operator =(matrix &M);   // matrix класы үшін   меншіктеу (=)  амалын

                                                                             // қайыра жүктейтін әдістің  прототипі

         matrix operator +(matrix &M);   // matrix класы үшін   қосу  (+)  амалын

                                                                             // қайыра жүктейтін әдістің  прототипі

         matrix operator *(matrix &M); // matrix класы үшін   көбейту  (*)  амалын

                                                                             // қайыра жүктейтін әдістің  прототипі

};  // matrix класын  жариялау аяқталды

//-----------------------------------------------------------------------------------------

matrix:: matrix( unsigned int gol, unsigned int bagan) //матрицаны құрушы  

                                                                     //конструктор-әдістің өзін  жариялау

{

 unsigned int i;

GOL=gol; BAGAN= bagan;

elemMat = new float* [GOL];  // матрица элементтері үшін жадыдан GOL орын алу

for(i=0;i<GOL;i++)

   elemMat[i]= new float [BAGAN];          // матрица элементтері үшін жадыдан

                                                                     // GOL* BAGAN орын алу

}

matrix matrix:: engizu()   // құрылған матрицаны толтыратын немесе элементтерінің мәнін енгізетін әдістің өзін жариялау 

{

 unsigned int i,j;

for(i=0; i<GOL; i++)

 for(j=0; j<BAGAN; j++)

elemMat[i][j]=random(100)%13-3;       // матрица элементтерінің мәндерін

                                                                          //кездейсоқ сандар генераторы анықтайды

 return * this;

}

//------------------------------------------------------------------------------------------------

 void matrix:: koru()    // кездейсоқ сандар генераторы анықтаған матрица

// элементтерінің мәндерін баспаға шығарып көрсететін әдістің өзін жариялау

{

 unsigned int i,j;

 cout<<"\n matrixti koru :" ;

 for (i=0; i<GOL; i++)

    {

                cout<<"\n";

 for (j=0; j<BAGAN; j++)

     cout<<"\t"<< elemMat[i][j];

     }

}

//-----------------------------------------------------------------------------------------------

matrix  matrix:: operator = (matrix &M)  // matrix класы үшін   меншіктеу (=)  амалын

                                                                     // қайыра жүктейтін әдістің  өзін жариялау

   {

     unsigned int i,j;

     GOL=M.GOL;  BAGAN=M.BAGAN;

     for (i=0; i<GOL; i++)

     for (j=0; j<BAGAN; j++)

     elemMat[i][j]=M.elemMat[i][j];

     return * this;

}

//-------------------------------------------------------------------------------------------------

matrix  matrix:: operator + (matrix &M)  // matrix класы үшін   қосу  (+)  амалын  қайыра жүктейтін әдістің  өзін жариялау

{

      unsigned int i,j;

if((GOL!=M.GOL)||(BAGAN!=M.BAGAN))         //қосу амалы орындалатын   

                                                                    //матрицалардың өлшемдерін тексеру

    {

 cout<<"\n matrixterdin olshemderi saikes emes!!!";

 getch();

 exit(-1);   //программаның орындалуы аяқталды

    }

  matrix S(GOL,BAGAN);       // matrix типті S қосынды матрицаны жариялау

    for(i=0; i<GOL; i++)

    for(j=0; j<BAGAN; j++)

S.elemMat[i][j]=elemMat[i][j]+M.elemMat[i][j];

    return S ;

}

matrix matrix::operator *(matrix &M)  // matrix класы үшін   көбейту   (*)  амалын

                                                               // қайыра жүктейтін әдістің  өзін жариялау

 {

 unsigned int i,j,k;

 if((BAGAN!=M.GOL))         //көбейту орындалатын матрицалардың бағандары

                                                     //мен жолдарының саны бірдей  болуын тексеру 

     {

 cout<<"\n matrixterdin bagandari men goldarinin sani birdei emes!!!";

 getch();

 exit(-1);

      }

matrix P(GOL,M.BAGAN);  // matrix типті Р көбейтінді  матрицаны жариялау

for(j=0; j<M.BAGAN; j++)

for(i=0; i<GOL; i++)

    for(k=0; k<M.GOL; k++)

P.elemMat[i][j]=P.elemMat[i][j]+elemMat[i][k]*M.elemMat[k][j];

 return P ;

}

//-----------------------------------------------------------------------------------------------

int main()                                                                   //негізгі программа басталды

    {

  matrix A(4,4), B(4,4); // matrix типті A  және B объектілерін жариялау

 A.engizu(); cout<<" \n A "; A.koru();  // A  объектісі үшін әдістерді шақыру

 B.engizu(); cout<<" \n B " ;  B.koru(); // В  объектісі үшін әдістерді шақыру

 cout<<" \n A + B ";(A+B).koru(); // A+B қосу амалын орындап,  нәтижені көру

 cout<<" \n A * B ";(A*B).koru(); // A*B көбейту  амалын орындап,  нәтижені көру

 matrix C(3,2), D(3,3);   // matrix типті С  және D объектілерін жариялау

 C.engizu(); cout<<" \n C "; C.koru(); //С  объектісі үшін әдістерді шақыру

 D.engizu(); cout<<" \n D " ;  D.koru(); // D  объектісі үшін әдістерді шақыру

 cout<<" \n C + D ";(C+D).koru(); // С+D қосу амалын орындап,  нәтижені көру

 cout<<" \n C * D ";(C*D).koru(); // C*D көбейту  амалын орындап,  нәтижені көру

 getch();

  }

Программа орындалуының нәтижесі келесі түрде болады:

D   matrixti koru :

       3       5       3 A    matrixti koru :                               

       7       1       5       2

       9       2       1       5

       5       6       6       2

       -3      3       1       -2

 B   matrixti koru :

       -3      4       3       3

       6       -3      -2      8

       1       9       -1      4

       4       9       -2      0

 A + B   matrixti koru :

       4       5       8       5

       15      -1      -1      13

       6       15      5       6

       1       12      -1      -2

A * B    matrixti koru :

       -2      88      10      49

       6       84      12      47

       35      74      -7      87

       20      -30     -12     19

 C   matrixti koru :

       5       -1

       1       5

       2       7

       4       8       7

       2       2       9

 C + D   matrixterdin olshemderi saikes emes!!!

Бұл программадағы, matrix:: matrix( unsigned int gol, unsigned int bagan);

конструктор-әдістің қызметі  gol Х bagan өлшемді болашақ матрицаның элемент

тері үшін жадыдан орын алу болып табылады. Сондықтан,  негізгі программада

ғы     matrix типті   A(4,4);   немесе  C(3,2), объектілерінің  жарияланулары орындал

ғанда, сәйкесінше 16 немесе 6 элемент үшін,  new амалының көмегімен жадыдан

орын алынады. Бұл алынған орындарға немесе ұяшықтарға матрица элементтерінің мәндерін жіберетін  matrix engizu()   әдісіндегі келесі команда,

elemMat[i][j]=random(100)%13-3;

болып табылады.  

Бұл программадағы matrix класы үшін қайыра жүктелген «меншіктеу» (=), « қосу» (+) және  «көбейту» (*)   амалдарының барлығы да бинарлық амалдар, сондықтан да осы аталған  амалдарға сәйкес қайыра жүктелген амал-функциялардың үшеуінде де ,

                                   matrix matrix::operator *(matrix &M)

matrix  matrix:: operator + (matrix &M)

matrix  matrix:: operator = (matrix &M)

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

matrix S(GOL,BAGAN);

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

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

Динамикалық кезек

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

Динамикалық   стек

Келесі  программа элементтерді динамикалық   стекке орналастыруды және одан шығарып алуды демонстрациялайды:

#include <iostream.h>

#include <conio.h>

 struct elem                      // stak-тізімнің  элементін жариялау

     {

int d;                    

elem* adrK;            

 elem *adrA;

      };

elem* elem_1(int d);    // stak-тізімге бірінші элементті орналастыру

void kosuS(elem **tizSoni,int d);   //stak-тізімге  элемент енгізу

void aluS(elem** tizSoni) //stak-тізімнен  элементті шығарып алу

 int main()                      //негізгі программа басталды

{

int ganaEl;

cout<<"\n  birinshi elementtin mani:  " ;

cin>> ganaEl;     //stak-тізімге баратын бірінші элементтің мәнін енгізу

elem *tizBasi=elem_1(ganaEl); //stak-тізімге бірінші элементті орналастыру

elem *tizSoni=tizBasi; //тізімнің соңы үшін жарияланған көрсеткішке

      //тізімнің  басының  адресі беріледі, яғни тізім бір ғана элементтен тұрады

 while  (ganaEl != 13)  //тізім соңының белгісін  13 саны білдіріп тұр

           {  

               //stak-тізімге қалған элементтерді  енгізу басталды

              cout<<"\n kelesi elementtin mani: " ;

              cin>> ganaEl; // келесі элементтерінің мәндерін енгізу

   kosuS(&tizSoni,ganaEl); //stak-тізімге элемент енгізетін функцияны шақыру

          }  

elem *buf=tizBasi;   // buf –қа  stak- тізімнің  басының  адресін беру

cout<<"\n ELEMENTTER STAK- TIZIMGE ORNALASTI  :  \n";

while (buf)            // stak- тізімге енген  элементтерді көру

           {

cout<<"\t"<<buf->d;       

buf=buf->adrK;               

            }

   cout<<"\n ELEMENTTER STAK- TIZIMNEN  SHIGARILDI  :  \n ";

  buf=tizSoni; //buf –қа  stak- тізімнің соңының  адресін беру 

  aluS(&buf); // stak- тізімнен  элементтерді шығаратын функцияны шақыру

  getch();

}

//---------------------------------------------------------------------------

elem* elem_1(int d)      //stak-тізімге бірінші элементті орналастыру функциясы            

   {

elem* buf=new elem;  

buf->d=d;                     

buf->adrK=0;              

 return buf;

    }

//---------------------------------------------------------------------------

void kosuS (elem** tizSoni,int d)     //stak-тізімге элемент енгізетін функция       

         {

 elem *buf=new elem;   

 buf->d=d;                     

buf->adrK=0;                

buf->adrA=* tizSoni;   

(*tizSoni)->adrK=buf;   

           * tizSoni=buf;                 

    }

//---------------------------------------------------------------------------

void aluS (elem** tizSoni)      // stak- тізімнен  элементтерді шығаратын функция      

        {  

            elem* buf=*tizSoni;

 while (buf)  

         {             cout<<"\t"<<buf->d;

            buf=buf->adrA;          }

* tizSoni=buf;

        }

Программа орындалғанда келесі нәтижелерд көрсете алады:

birinshi elementtin mani:  1

kelesi elementtin mani: 2

kelesi elementtin mani: 3

kelesi elementtin mani: 4

kelesi elementtin mani: 5

kelesi elementtin mani: 13

ELEMENTTER STAK- TIZIMGE ORNALASTI  :

       1       2       3       4       5       13

ELEMENTTER STAK- TIZIMNEN  SHIGARILDI  :

       13      5       4       3       2       1

  ДИНАМИКАЛЫҚ ТІЗІМ

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

 Бір бағыттағы жай тізім элементінің анықталуында көрсеткіш түріндегі адрестік өріс біреу ғана болады және ол келесі элементтің адресін көрсететін болады  (5.3.1- сурет).

Екі бағыттағы тізімнің әрбір элементінде адрестік өріс екеу болады, оның біреуі- сол элементтің алдындағы элементтің адресін, ал екіншісі - одан кейін тұрған элементтің адресін сақтап тұрады  (5.3.2- сурет)..

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

Программалауда тізімнің жұмысын ұйымдастыруды екі кезеңге бөледі : тізімді құру және тізімді өңдеу. Тізімді құру келесі алгоритм бойынша жүргізіледі:

Динамикалық құрылымдар, түрлері

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

Программаның орындалуы кезеңінде динамикалық құрылымдардың өлшемдерін өзгертіп пайдалана беруге  болады, яғни программист қажет болған кезде көрсеткіштің көмегімен динамикалық жадыдан қатар-қатар орналасқан ұяшықтардан тұратын элементтерді немесе блоктарды ала береді, ал бұл блоктар қажет болмай қалғанда оларды қайтадан босатып береді. Осыған байланысты динамикалық құрылымдардың өлшемдері үнемі өзгеріп қозғалыста болатындықтан да оларды динамикалық деп атайды.  

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

Программалау тілдерінде динамикалық құрылымдардың блоктарын түйіндер, элементтер немесе компоненттер деп түрлі- түрлі атай береді. Динамикалық құрылымның элементі (немесе түйіні, компоненті) кем дегенде екі өрісі бар болатын құрылыммен (struct)  анықталады. Өрістердің біреуінде стандарт типтер, қолданушы құратын типтер түріндегі немесе т.б. деректер сақталады, ал екінші өріс міндетті түрде көрсеткіш болады және ол көрсеткіште келесі элементтің адресі сақталады, егер келесі элемент жоқ болса нульдік адрес NULL  сақталатын болады. Динамикалық құрылымның элементін программада құрылым түрінде сипаттау келесі түрде болуы мүмкін:

struct elem                       //динамикалық құрылымның элементін жариялау

{

int d;                           //деректер сақталатын өріс

 elem* adrK;              //келесі элементтің адресі сақталатын көрсеткіш

                                      // немесе адрес-өріс

elem* adrА;            //алдыңғы элементтің адресі сақталатын көрсеткіш

                               // немесе адрес-өріс

};

мұнда, өрістердің саны екеуден артық болса бола береді, бірақ одан кем болмауы керек.  Мысалы, деректер сақталатын өрістер бірнешеу болуы мүмкін, олардың типтері де әртүрлі бола береді, сол сияқты адрес-өрістер де бірнешеу бола алады, мысалы, олардың  біреуі алдыңғы элементтің, ал екіншісі кейін тұрған элементтің адресін көрсетіп тұрады.

Сонымен динамикалық құрылымдарды ұйымдастыруда белгілі бір тәсілдер қолданылатын болды, сол тәсілдерге байланысты оларды келесі топтарға бөледі:

  1.  тізім (список);
  2.  стек (стек);
  3.  кезек (очередь);
  4.  бинарлық ағаштар (бинарные деревья).

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

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

Екілік файлға мәлімет жазу

Келесі программа құрылымдық массивті екілік файлға жазуды орындайды:

#include <iostream.h>

#include <conio.h>

#include <fstream.h>

struct adam

{ string fam; //фамилия

int stag; //еңбек өтілі

float zarpl; //жалақысы

};

int main()

{

adam gruppa[3]; //құрылымдық массивті жариялау

ofstream FileGazu(«777.dat»); // алушы файлдық ағын объектісін

// жариялау және оны екілік файлмен байланыстыру

for(int i=0;i<3;i++)

{c

in>>gruppa[i].fam>> gruppa[i].stag>> gruppa[i].zarpl; //деректерді енгізу

FileGazu.write((char*)& gruppa[i], sizeof (adam)); // екілік файлға жазу

}

FileGazu.close();

}

Бұл программа орындалуының нәтижесінде пайда болған терезеге келесі деректер енгізіледі:

Asnova

20

100000

Mukasheva

25

75000

Muratova

15

50000

Бұл терезедегі енгізілген деректер 777.dat екілік файлға жазылып сақталып қалады.

Екілік файлдан мәліметті оқу.

Келесі программа екілік файлдағы деректі құрылымдық массив түрінде оқуды демонстрациялайды:

#include <iostream.h>

#include <conio.h>

#include <fstream.h>

struct adam

{

char fam[30]; //фамилия

int stag; //еңбек өтілі

float zarpl; //жалақысы

};

int main()

{

adam gruppa[3]; //құрылымдық массивті

жариялау

cout <<»\n\n FILE- dan oku bastaldi : \n»;

ifstream FileOku(«777.dat»); // енгізуші файлдық ағын объектісін

/ ж/ ариялау және оны екілік файлмен байланыстыру

for(int i=0;i<3;i++)

{ FileOku.read((char*)& gruppa[i], sizeof (adam)); //ағыннан деректі алу

cout<<»\n»;

cout<<gruppa[i].fam<<» «;

cout<<gruppa[i].stag<<» «;

cout<<gruppa[i].zarpl;

}

FileOku.close();

getch();

}

Программа орындалуының нәтижесі

келесі түрде болады:

FILE- dan oku bastaldi :

Asnova 20 100000

Mukaseva 25 75000

Muratova 15 50000

 Көрсеткіш, қызметі мен жариялануы.

Программалауда қолданылатын кез-келген дерек, мейлі ол программаның коды немесе жарияланған айнымалы, немесе тұрақты  немесе  т.б. болсын, бәрібір ол  компьютер жадысында белгілі бір адрес бойынша  ұзындығы байтпен өлшенетін орын алатыны белгілі. Егер компьютер жадысы шартты түрде көптеген кішкентай ұяшықтардан немесе сол ұяшықтардан тұратын кішкентай жәшіктерден тұрады деп есептелсе, онда осы ұяшықтың адресі оның жадыдағы тұрған орнын білдіретін болады (3.5- сурет).  Программада қандай да болмасын белгілі бір типке жататын айнымалы немесе т.б. жарияланған кезде,  оның  типіне сәйкес байт-ұзындықтағы орынды немесе жәшікті жадыдан алады, мысалы,  int  aInt;  түрінде жарияланған бүтін типті aInt айнымалысы үшін қатар орналасқан адрестері 1245064, 1245063, 1245062, 1245061 болатын ұяшықтар алынады, егер ол айнымалының  мәні  берілсе, онда сол мән жаңағы ұяшықтардан құралған жәшікке барып түсті деп есептеуге болады, ал айнымалының идентификаторы (aInt) сол ұяшықтардан құралған жәшіктің  сыртындағы этикеткасы секілді қызмет атқарады. Демек, қолданушы программамен жұмыс жасағанда айнымалының нағыз адресімен емес, тек оның этикеткасымен ғана жұмыс жасайтын болып тұр, себебі, бұл адрестермен жұмыс жасағаннан әлдеқайда жеңіл, яғни бұл жерде адрестермен жасалатын жұмысты компилятор өзі атқарып тұр, сондықтан бұл қолданушыға байқалмайды.

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

тип *көрсеткіш;          

немесе

тип *көрсеткіш=  көрсеткіш_айнымалы;      

немесе

тип айнымалы=мәні;

тип *көрсеткіш=& айнымалы;

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

Бір типке жататын бірнеше көрсеткіштерді жариялағанда «*»  белгісі олардың әрқайсысының алдына қойылады.

Мысалы,

  int  aInt=777; //aInt   айнымалыны жариялау

 int  * kInt=&aInt;    //aInt   айнымалының адресі сақталатын kInt   көрсеткішті жариялау

 Int  ** kkInt=&kInt;  // kInt   көрсеткіштің адресі сқталатын kkInt   көрсеткішті жариялау

 Int  *** kkkInt=&kkInt;   // kkInt    көрсеткіштің адресі сқталатын kkkInt   көрсеткішті жариялау

              char  *kChar_a, *kChar_b, *kChar_c;   //бірнеше көрсеткішті қатар жариялау

мысалы, мұндағы, int  aInt;  түрінде жарияланған бүтін типті aInt айнымалысы үшін жадыдан бөлінген орын немесе жәшіктің адресі 1245064 болсын, сонда kInt  көрсеткішке арналған жәшікте осы айнымалының адресі сақталатын болады (3.5 –сурет), ал «көрсеткішке көрсеткіш» немесе « **» түрінде жарияланған kkInt  жәшіктің ішінде  kInt  көрсеткіш адресі орналасады.

Көрсеткіш. Адресті алу амалы.

Көрсеткіштің программадағы жариялануының бірнеше түрі бар:

тип *көрсеткіш;

немесе

тип *көрсеткіш= көрсеткіш_айнымалы;

немесе

тип айнымалы=мәні;

тип *көрсеткіш=& айнымалы;

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

int aInt=777; //aInt айнымалыны жариялау

int * kInt=&aInt; //aInt айнымалының адресі сақталатын kInt көрсеткішті жариялау

Int ** kkInt=&kInt; // kInt көрсеткіштің адресі сқталатын kkInt көрсеткішті жариялау

Int *** kkkInt=&kkInt; // kkInt көрсеткіштің адресі сқталатын kkkInt көрсеткішті жариялау

char *kChar_a, *kChar_b, *kChar_c; //бірнеше көрсеткішті қатар жариялау

 

 

Көрсеткіш. Адресі бойынша мәнді алу амалы.

С++ программалау тілінде айнымалылардың, объектілердің немесе т.б. деректердің жадыдағы орындарының адрестерімен тікелей жұмыс жасау үшін көрсеткіш деп аталатын арнаулы айнымалылар қолданылады. Көрсеткіш өз алдына жеке тип болып есептелмейді, ол тек типі анықталып, жарияланған айнымалының жадыдан алған орнын немесе адресін көрсету үшін ғана қолданылатын ерекше айнымалы болып табылады. Бір типке жататын бірнеше көрсеткіштерді жариялағанда «*» белгісі олардың әрқайсысының алдына қойылады.

Мысалы,

int aInt=777; //aInt айнымалыны жариялау

int * kInt=&aInt; //aInt айнымалының адресі сақталатын kInt көрсеткішті жариялау

Int ** kkInt=&kInt; // kInt көрсеткіштің адресі сқталатын  kkInt көрсеткішті жариялау

Int *** kkkInt=&kkInt; // kkInt көрсеткіштің адресі сқталатын // kkkInt көрсеткішті жариялау

char *kChar_a, *kChar_b, *kChar_c; //бірнеше көрсеткішті қатар жариялау

Көрсеткіштерге қолданылатын амалдар. Меншіктеу, ++, --, типтерді келтіру амалдары.

Көрсеткіштерге қолданылатын амалдар:

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

мысалы:

int *k_nol=NULL; немесе int *k_nol=0;  – типтерді келтіру амалы (void типіне қолданылмайды), мысалыunsigned long L=0x12345678L;

char *k_Char=(char *)&L; // long типін char* типке келтіру

int *k_Int=(int *)&L; // long типін int * типке келтіру

char *k_adr=(char *) 0xB8000000; // көрсеткішке жадыдағы  жәшіктің адресін анық түрде меншіктеу, мұнда оналтылық түрдегі 0xB8000000-  тұрақты char типке келтіріледі.

– инкремент (++) және декремент (--) амалдары, int *k_Int ++; немесе int *k_Int -- ; жазуға болады;

– жадыдағы жәшіктің адресін алу (& ) амалы, программада жарияланған атауы бар, уақытша жадыда орналасқан шамалар үшін ғана қолданылатын унарлық амал,  

мысалы:

int a=45; // бүтін типті а айнымалыны жариялау

int *k_a=&a; // жадыдағы а айнымалысы орналасқан жәшіктің адресін *k_a көрсеткішке алып беру

бұл амалды скаляр өрнектер үшін, атауы жоқ тұрақтылар үшін қолдануға болмайды.

Қателер және ерекше жағдайлар 

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

  1.  синтаксистік қателерге  программа мәтінін теру кезінде операторлардың қате жазылуы, операторларды айыру белгілерінің қойылмауы, программа соңының көрсетілмеуі және т.б.  жатады. Әдеттте синтаксистік қателерді анықтау компилятордың қызметіне жатады, яғни программа синтаксистік қатесі жөнделмейінше компиляциядан өтпейді.
  2.  логикалық қателер, есеп алгоритмінің дұрыс құрылмауынан болады. Логикалық қатесі бар программалар түсініксіз жұмыс жасайды, мысалы, цикл алгоритмінде циклдан шығу шарты   дұрыс құрылмаған болса, онда программа ешбір тоқтамастан қайталанып, нәтиже бермей жұмыс жасауы мүмкін, сол сияқты, есептеу алгоритмдерінде көбейтіндінің бастапқы мәнін нольге тең деп алғанда нәтижеде үнемі ноль шығуы мүмкін  және т.б. . Мұндай қателерді программаны тестілеу, яғни әртүрлі мәндер үшін орындап көру арқылы табады.

динамикалық қателер бұл- программаның орындалуы кезінде  пайда, болып оның орындалу тәртібінің бұзылуына немесе нәтижесіз тоқтап қалуына әкеліп соқтыратын қателер. Динамикалық қателерді немесе «орындау уақыты кезіндегі қателер» («ошибка времени выполнения», Runtime errors) деп те атайды. Динамикалық қателерге, мысалы, есептеу кезінде бөлшек бөлімінің нольге тең болуы, түбір астында теріс сан кездесіп қалуы, жады ресурстарының жетпей қалуы, программада көрсетілген маршрут бойынша файлдың табылмай қалуы, принтерде қағаздың бітіп қалуы  және т.б. көптеген нәрселер жатады. Міне,  қосымшалардағы осындай динамикалық қателерге байланысты болатын жағдайларды «ерекше жағдайлар»деп атап, және олармен жұмыс жасау үшін программалау тілдерінде «ерекше жағдайларды өңдеу» түсінігі енгізілген.

Массивтердің көрсеткіштермен байланысы. 

С++ программалау тілінде массивтер үшін көрсеткіштерді пайдаланудың өте үлкен маңызы бар. Бұл жалпы массивтің жадыдағы орналасуына байланысты болып келеді. Массив элементтері, жадыда, бірінен кейін бірі қатар орналасқан ұяшықтарда немесе жәшіктерде сақталады.

С++-те массивтің аты, оның алғашқы элементінің (мысалы, a[0]-дің) адресін сақтап тұратын көрсеткіштің қызметін атқарады, сондықтан, егер, программада келесі түрде жазылса,

int a[5]= {5,1,7,9,3}; //массивті жариялау

int *k_mas=a; // k_mas көрсеткішке массивтің атын меншіктеу

онда, бұл жазу int *k_mas=&a[0]; дегенмен пара-пар болып шығады, сондықтан программалауда int *k_mas=&a[0]; деп жазудың орнына int*k_mas=a; деп жаза береді. Массивтің келесі a[1] элементінің адресін алу үшін көрсеткіштерге қолданылатын декремент амалын k_mas++; немесе «қосу» амалын k_mas=+1; деп пайдалануға болады, ал бірден a[2] – үшінші элементтің адресін алу керек болса, онда k_ mas=+2; деп жазуға болады. Ал, сол адресі көрсетілген жәшіктегі массив элементінің мәнін алу керек болса, онда сәйкес көрсеткішке, «*» – адрес бойынша мәнді алу амалын қолданады, мысалы, келесі программа фрагменті орындалғанда:

int a[5]= {5,1,7,9,3}; //массивті жариялау

int *k_mas=a; // k_mas көрсеткішке массивтің атын меншіктеу

cout<<»\ *(k_mas+2)=»<< *(k_mas+2); // k_mas+2 көрсеткішіне «*»-

//амалын қолданып сол адрес бойынша мәнді алу

a массивтің үшінші жәшікте орналасқан, үшінші элементінің (a[2]-нің) мәні *(k_mas+2)= 7 шығатын болады.

Келесі программа int a[5]= {5,1,7,9,3}; түрінде жарияланған массив элементтері орналасқан жады жәшіктерінің адресін шығарып береді:

#include <iostream.h>

#include <conio.h>

int main()

{

int a[5]= {5,1,7,9,3}; //массивті жариялау және иницализациялау

int *k_masBasi=a; //массивтің алғашқы

элементінің көрсеткіші

int *k_masSoni=&a[4]; //массивтің соңғы элементінің көрсеткіші

int i=0; //массивтің алғашқы элементінің реттік номері

while (k_masBasi<=k_masSoni) //әзірге алдыңғы адрес, соңғыдан кіші

{cout<<»\n\na[«<<i<<»] adresi-> «<< k_masBasi; //ендеше сол k_masBasi          көрсеткіштегі адрестікөрсету

k_masBasi++; // келесі адреске көшу

i++; // массивтің келесі элементінің реттік номерін алу

}

getch();

}

Мәтіндік файлға жазу

 Программа,  саны алдын –ала белгісіз , string  түрінде анықталған  фамилияларды мәтіндік файлға жазуды көрсетеді.

#include <iostream.h>

#include <conio.h>

#include <fstream.h>

int main()

{

string fam;

ofstream FileGazu("spisok.txt");             //файлды программамен байланыстыру

cout<<"File-ga gazu bastaldi: \n ";

 while (fam!="!")              //әзірге енгізілген фамилия ! болмаса цикл қайталанады

{

cin>>fam;

FileGazu <<fam<<"\n"; // fam-дағы мәнді  алушы  файлдық ағынға қосу

  }

       FileGazu.close();

       cout<<"File-ga gazu toktaldi \n ";

        getch();

         }

Бұл программаның орындалуы нәтижесінде , ағымдағы бумада,  

File-ga gazu bastaldi:

Asanov

Saparova

Bulatov

Kim

Petrov

Ospanov

!

File-ga gazu toktaldi

spisok.txt  мәтіндік файлы құрылып, оған жоғарыдағы терезедегі енгізілген фамилиялар жазылады.

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

2-мысал Программа алушы немесе шығарушы файлдық ағынды пайдаланып мәтіндік файлға дерек жазуды көрсете алады.

#include <iostream.h>

#include <conio.h>

#include <fstream.h>

int main()

  {

ofstream  file_object1 ("111.txt");        // алушы  файлдық ағын объектісін жариялау 

                                                                               // және программаны файлмен байланыст

   file_object1<<" Menin atim Koga!";  // алушы файлдық ағынға деректі қосу

   file_object1.close();   //  файлды жабу

Menin atim Koga!

 }

Бұл программа орындалғанда шығатын нәтиже жоба сақталған ағымдағы бумада 111.txt файлы құрылады және бұл файлға " Menin atim Koga!" деген мәтін жазылып қалады.

Мәтіндік файлдан оқу

 Программа енгізуші файлдық ағынды пайдаланып мәтіндік файлдан деректі оқуды көрсете алады.

#include <iostream.h>

#include <conio.h>

#include <fstream.h>

int main()

{ char X[20];

ifstream file_object2 ("111.txt");      // енгізшіу файлдық ағын объектісін жариялау 

                                                               // және  программаны файлмен байланыстыру

file_object2.getline(X, sizeof(X));     //енгізуші файлдық ағыннан деректі алып,

                                                                        //  Х-қа беру

cout<<X;

file_object2.close(); //файлды жабу

getch();

}

Бұл программа орындалуының нәтижесі келесі түрде болады:

Программада, файлдағы жолды тұтасымен  бірден оқып шығу үшін getline( ); функциясы шақырылды, егер оның орнына   file_object2>>X;  ағыннан алу амалын қолданса, онда ол бірінші бос орынға дейінгі сөзді , яғни «Menin»  деген мәтінді ғана шығарған болар еді.

Мәтіндік файлды ашу режимдері

Жадыдағы берілу тәсіліне байланысты файлдарды екіге бөліп қарастырады:

  1.  мәтіндік файлдар. Мәтіндік файлдар бұл «бос орын», «жаңа жол», табуляция символдарымен  ажыратылған символдар тізбегінен тұратын мәтін түрінде берілетін файл.
  2.  бинарлық немесе екілік файлдар. Мұнда файлға жазылатын немесе файлдан оқылатын дерек байттардың порциясы түрінде берілетін болады.

Ашу режимі не сәйкес параметр мәні

Орындайтын қызметі

ios::app

файлды дерек қосу үшін ашу және файлдық көрсеткішті файлдың соңына апару

ios::ate

файлдық көрсеткішті файлдың соңына апару

ios::binary

Файлды екілік (бинарлық) режимде ашу

ios::in

файлды  дерек енгізу үшін ашу

ios::nocreate

файл табылмаған жағдайда, файлды жаңадан құрмай қатені хабарлау

ios::noreplace

файл табылған жағдайда, файлды  ашу операциясын үзіп ,қатені хабарлау

ios::out

файлды шығару үшін ашу

ios::trunc

Файлдағы деректі  жою

 С++ программалау тілінде жалпы файлды ашу кезінде open(); функциясын қолдану қарастырылған, жазылуы:

ifstream file_object;   //файлдық объектіні жариялау

file_object. open  файлдыңАты «, ашу режимі); //файлды ашу

Бірақ ofstream, ifstream және fstream кластарында файлды ашуды автоматты түрде орындайтын конструкторлар болғандықтан программисттер open(); функциясын қолданбай-ақ, файлдарды жоғарыда келтірілген әдіспен аша береді. Файлды жабу үшін close (); функциясын қолданады. Бұл close(); функциясының параметрлері болмайды және ол ешқандай мән қайтармайды.

Параметрлерінің саны әр түрлі функцияны қайыра жүктеу

Программада атаулары бірдей, бірақ параметрлерінің  саны әртүрлі функцияларды қайыра

жүктеуді көрсетіледі.

# include <iostream.h>

# include <conio.h>

void perchar ( ); // параметрі жоқ функция прототипі

void perchar (char); // бір ғана параметрі бар функция прототипі

void perchar (char, int); // екі параметрі бар функция прототипі

int main()

{

cout <<»\n\n»;

perchar ( ); // параметрі жоқ функцияны шақыру

cout <<»\n\n»;

perchar ( ‘=’ ); // бір ғана параметрі бар функцияны шақыру

cout <<»\n\n»;

perchar (‘+’, 30); // екі параметрі бар функцияны шақыру

getch();

}

void perchar ( ) // параметрі жоқ функцияны жариялау

{ for (int j=0; j<45; j++)

cout << ‘*’; // функция «*» символын 45 рет басып шығарады

}

void perchar (char ch) // бір параметрі бар функцияны жариялау

{ for (int j=0; j<45; j++)

cout<<ch; //функция ch параметрімен

берілген символды 45 рет шығарады

}

void perchar (char ch, int n) // екі параметрі бар функцияны жариялау

{ for (int j=0; j<n; j++)

cout<<ch; //функция ch параметрімен

берілген символды n рет шығарады

}

Программа нәтижесінде экранға келесі ақпарат шығарылады:

*****************************

==========================

++++++++++++++++++++++++++

Бұл программада, perchar ( );,perchar (char); және perchar (char, int); деп аталатын үш функцияның қызметікөрсетілді. Бұл функциялардың барлығының атаулары бірдей екені көрініп тұр, сондай-ақ, олардың әрқайсысы өз жариялануына сәйкес әртүрлі қызметтер орындауы керек. Бірақ осыған қарамастан аттары бірдей бұл үш функция бір-бірінен өзгеше үш түрлі нәтиже көрсетіп тұр, себебі бұл функциялардың параметрлерінің сандары және типтері әртүрлі болғандықтан ғана компилятор оларды ажырата алып тұр, яғни жарияланған әрбір функция өзіне тиесілі қызметті орындап тұр.

 Программа бір атаумен берілген, бірақ параметрлерінің типтері әртүрлі, саны бірдей  бірнеше функцияларды  қайыра жүктеуді  көрсетеді.

#include <iostream.h>

# include <conio.h>

struct tortburish  // tortburish құрылымдық типті жариялау

  { float a; //төртбұрыштың  ені

    float b;  //төртбұрыштың  ұзындығы

  };

          struct ushburish  // ushburish құрылымдық типті жариялау

  {  float a; //үшбұрыштың  табаны

     float h; //үшбұрыштың  биіктігі

  };

         float audan (tortburish);   //төртбұрыш ауданын табатын

                                                             // функция прототипі

        float audan (ushburish);    //үшбұрыш  ауданын табатын  

                                                                  //функция прототипі

   int main()

{

tortburish   t={1.7,8.3};  // tortburish  типті t айнымалыны жариялау

ushburish    u={1.7, 8.3}; // ushburish типті u айнымалысын  жариялау

cout << " \n\n tortburish audani St="<<audan(t); // параметрі  tortburish  

                                                                                  // типті t айнымалысы болатын

                                                                                //audan(t); функцияны шақыру

cout << " \n\n ushburishtin audani Su="<<audan(u); // параметрі    

                                                       //ushburish    типті u  айнымалысы болатын

                                                     //audan(u ); функцияны шақыру

getch();

}

float audan (tortburish k)  //төртбұрыш ауданын табатын функцияны жариялау

{

  float s=k.a*k.b;

 return (s);

}

float audan (ushburish k)  //үшбұрыш  ауданын табатын функцияны жариялау

{

float s=(k.a*k.h)/2;

return (s);

}

мұнда, функциялардың атаулары да, параметрлерінің саны да бірдей, бірақ ол параметрлердің типтері әртүрлі болып тұр, яғни бір параметрдің типі -   tortburish , ал екінші параметрдің типі – ushburish, болғандықтан компилятор оларды ажыратады және соған  сәйкес функцияны іске қосатын болады.  

 Рекурсивті функциялар

Рекурсивті  функция деп  өзін-өзі шақыра алатын функцияны айтады. Рекурсивті функцияның ең көп тараған классикалық мысалы ретінде факториалды есептеу функциясын  айтуға болады. n санының факториалы деп әдетте 1-ден бастап  n-ды қоса алғандағы барлық бүтін сандардың көбейтіндісін айтады және оны былай жазады:

n!=1 · 2 ·  3 · . . .  · (n-1) ·   n .

немесе мұны келесі түрде де жазуға болады:

n!= n· ((n-1) · (n-2) ·  . . .    ·  3 · 2 · 1 ) = n ·  (n-1)!

демек, n санының факториалын табу үшін n- ды  (n-1) санының факториалына көбейтеді,  сол сияқты (n-1) санының факториалы, оны  (n-2)-нің факториалына көбейткенде шығады.  Ал егерде,  n санының факториалын есептеу алгоритмін  функция түрінде жазатын болса, онда бұл функцияда  тағы да  (n-1) санының факториалын есептейтін тура сондай функцияны шақыруға тура келеді, яғни функция өзін-өзі шақыратын болады. Шақырудың бұл тәсілін рекурсия,  ал шақырылатын функцияны рекурсивті функция деп атайды.

Сақина түріндегі тізім құру

Сақина түрінде ұйымдастырылатын тізім бұл да бір бағыттағы тізім болып есептеледі, бірақ, мұнда тізімнің соңғы элементіндегі адрестік өрісте немесе  көрсеткіште қайтадан тізімнің басындағы элементтің адресі сақталатын болады, сонда тізім тұйықталып, сақина түріндегі тізім болып шығады

Статикалық стек 

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

Стектің элементтері үшін екі-ақ амал анықталған: біреуі стекке элементті енгізу, екіншісі, стектен таңдаған элементті шығарып алу. 

Стектің жұмысы “соңғы келген бірінші болып шығып кетеді  (LIFO- last in — first out)” деген принципке негізделген. Бұл принципті немесе деректердің арнайы құрылымы - стекті L- F құрылым ( Last- First) деп  те атайды.

Келесі  программа бес элементтен тұратын массив элементтерін  стек түрінде орналастырып және оларды стектен шығарып алуды көрсетеді:

#include <conio.h>

#include <iostream.h>

const int teren=5;   //стектің тереңдігі

void stakEng( int* stak , const int teren);  //стекке элементтерді орналастыратын

                                                                            //функция прототипі

    void stakAlu( int* stak , const int teren);    //стектен элементтерді шығаратын  

                                                                         //функция прототипі

  int main()

         {

int s[teren];  //стектің қызметін атқаратын  массивті жариялау

int* ukS=s;  //массивтің бірінші элементіне көрсеткішті жариялау

cout<<"\n stakke elementter engizu :         ";

stakEng(ukS,teren);  //стекке енгізуді орындайтын функцияны шақыру

cout<<"\n stakten elementterdi shigarip alu  :     ";stakAlu( ukS , teren);  //стектен шығарып алуды  орындайтын функцияны шақыру

            getch();

      }

//---------------------------------------------------------------------------

void stakEng( int* stak , const int teren)     //стекке енгізуді орындайтын

                                                                                       // функцияны жариялау

       {  

              int tobe=0;  //стектің төбесінде   стектің бірінші элементінде тұр

              if (tobe==teren-1)  //стектің төбесінде соңғы элемент тұрса, онда    

   cout<<"\n stak toldi";         //әрі қарай орын жоқ стек толып тұр

              else    

     while (tobe<teren)        // әзір стек толмаған болса

             {

               int m;                  // m  стекке енгізілетін элемент

              cin>>m;

              stak[tobe]=m; // m элементті  стекке  орналастыру

              tobe++;          //төбені кейінгі позицияға немесе орынға жылжыту

            }

       }

//-------------------------------

 void stakAlu( int* stak , const int teren)     //стектен шығарып алуды  орындайтын

                                                                                             // функцияны жариялау

        {   

              int  tobe=teren-1;   //стектің төбесінде соңғы элемент тұр                                                                    

              if (tobe==0)            //стектің төбесінде бірінші элемент тұрса, онда әрі қарай

                                                     // ештеңе жоқ,  стек бос

   cout<<"\n stak bos";

else

      while (tobe>=0) //әзір стектің төбесі бос емес болса   

              {

                int m; // m  стектен шығатын  элемент

                m=stak[tobe]; // элементті  стектен шығарып алып m –ға беру

                cout<<"   "<<m;

                tobe--;  //төбені алдыңғы  позицияға немесе орынға жылжыту

              }

        }

Бұл программаның нәтижесі келесі түрде болады:

 stakke elementter engizu :                    1  2  3   4   5

stakten elementterdi shigarip alu  :     5   4  3  2   1

Бұл программадан, стектің тереңдігі массивтің өлшемімен бірдей болатындығын  және оның өзгермейтіндігін (const int teren=5;) байқауға болады.  

Статикалық кезек 

Кезек (очередь) – бұл жұмыс істеу принципі кәдімгі кезек сияқты, бір типке жататын арнайы деректер құрылымы. Бұл құрылым келесі түрде ұйымдастырылады, яғни кезекке элементті кіргізу немесе енгізу оның  соңынан ғана, ал элементті шығарып алу басынан ғана жүргізіледі. Кезектегі деректер оның элементтері деп аталады. Элементтері бірінен кейін бірі тізбектей орналасады.

Кезекпен жұмыс істеу үшін екі амал қарастырылған: элементті кезекке енгізу және таңдаған элементті кезектен шығарып алу.

Егер кезекте бірде- бір дерек жоқ болса, онда мұндай кезекті бос  кезек деп атайды.

Статикалық кезек үшін ондағы деректер санына тең болатын “өлшем” ұғымы анықталған.

Кезек құрылымындағы сақталатын “бірінші келген – бірінші болып  шығып кетеді FIFO (first in — first out) деген принципке байланысты оны F-F құрылымы (First-First) деп атайды.

Статикалық тізімді құру

Сілтемелер (сілтеуіш айнымалылар)

Сілтемелер немесе оларды сілтеуіш айнымалылар деп те атайды, негізінен көрсеткіштердің бір түрі болып табылады. Жазылуы:

тип & сілтеме (айнымалы);

тип & сілтеме = айнымалы;

мұндағы, & (амперсанд) таңбасы бұл жерде сілтеу амалының қызметін атқарады, сілтеме – бұл дұрыс иден-

тификатор.

Мысалы:

int x=10; //х айнымалыны жариялау

int & cx=x; // х айнымалысына сілтеме cx жариялау

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

Мысалы:

int x=10; //х айнымалыны жариялау

int & cx=x; // х айнымалысына сілтеме cx жариялау

int *korsX= &x; // korsX көрсеткішке

х айнымалысының адресін беру

мысал:

#include <iostream.h>

#include <conio.h>

int main()

{ int x=10; //х айнымалыны жариялау

int & cx=x; // х-қа сілтейтін cx сілтеуіш айнымалыны жариялау

cout<<"\n x= "<<x; // х айнымалынының

мәнін көру

cout<<"\n cx="<<cx; // cx сілтеуіш айнымалынының мәнін көру

x=x*2; //х айнымалынының мәнін өзгерту

cout<<"\n\n x=x*2; tan keingi cx="<<cx; //х айнымалынының мәні

//өзгергеннен кейінгі cx сілтеменің мәнін көру

cx=cx+7; //сх сілтемені өзгерту

cout<<"\n\n cx=cx+7;tan keingi cx="<<cx; //сх сілтеме өзгергеннен

//кейінгі оның мәнін көру

cout<<"\n x= "<<x; //сх сілтеме өзгергеннен кейінгі x- тің мәнін көру

getch();

}

Стандарт ағындар

С++-тегі <iostream> тақырыптық файлы қосылған программа орындалған кезде автоматты түрде құрылатын стандарт ағындар болады. Бұл стандарт ағындарды пайдалану үшін программа мәтінініне стандарт ағындар кластарының жарияланулары және алдын ала анықталған cin, cout, cerr, clog объектілерінің сипаттамалары сақталатын <iostream> тақырыптық файлын кірістіреді. Программа орындалған кезде бұл тақырыптық файлға байланысты автоматты түрде төрт түрлі ағындар объектілері құрылады:

– cin, бұл- деректі стандарт құрылғыдан (әдетте, пернетақтадан) енгізуге арналған буферлік ағын объектісі;

– cout, бұл- деректі стандарт құрылғыға (әдетте, мониторға) шығаруға арналған буферлік ағын объектісі;

– cerr, бұл- қате туралы деректі стандарт құрылғыға (әдетте, мониторға) шығаруға арналған буферлік емес ағын объектісі;

– clog, бұл- қате туралы деректі стандарт құрылғыға (әдетте, мониторға) шығаруға арналған буферлік ағын объектісі.

сerr және clog стандарт ағындарының бір-бірінен айырмашылығы, сerr стандарт ағынына жіберілген қате туралы хабарлама, мониторға бірден шығарылады, яғни буферде сақталмайды, ал clog стандарт ағынын пайдаланғанда, қате туралы хабарламалар буфер толғаннан кейін барып шығарылады. Жалпы, буфер (buffer)- бұл, компьютердің сыртқы құрылғылары мен іске қосылып тұрған программаның, бір-біріне жіберетін деректерін уақытша сақтай тұруға арналған жедел жадының бір бөлігі. Егер, ағын буферді пайдаланбаса, онда дерек файлға (немесе құрылғыға) бірден  ығарылады, ал ағын буферді пайдаланатын болса, ол кезде файлға шығару буфер толғаннан кейін ғана орындалады.

Тізімнен  берілген элементті іздеу. 

- берілген деректің тізімде бар-жоғын іздеуді анықтайтын функция келесі түрде болуы мүмкін, мысалы:

elem* izdeu(elem* const tizBasi, int k) //берілген элементті тізімнен  іздейтін функция

{

elem* buf= tizBasi; //тізімнің басының адресін buf-қа беріп алу

while(buf) // әзірге buf- тағы адрес NULL болмаса,

{

if (buf->d==k) //сол адрестегі d-ның мәнін берілген k-мен салыстыру

break; //егер, олар сәйкес болса шығып кету

buf=buf->adrK; //әйтпесе келесі адреске көшіп тексеруді жалғастыру

}

return buf; //функция қайтаратын мәнге buf-тағы адресті беру

}

ТІЗІМНІҢ БАСЫНА ЖАҢА ЭЛЕМЕНТТІ ҚОСУ

Біріншіден, тізім элементінің жалпы құрылымы анықталады, мысалы:

struct elem // тізімнің элеменітін жариялау

{   int d; // деректер сақталған өріс

elem*adrK; //келесі элементтің адресі сақталған көрсеткіш өрісті жариялау

elem*adrA; //алдыңғы элементтің адресі сақталатын көрсеткіш өрісті жариялау

};

Функция түрінде тізімге бірінші элементті құру

elem* elem_1(int d) // тізімнің бірінші элементін құратын функция

{

elem*buf=newelem; // жаңа элемент үшін жадыдан орын алу және оның адресін buf

көрсеткіш түріндегі айнымалыға жіберу

buf->d=d; //сол адрес бойынша d-мәнді жіберу

buf->adrK=0; //келесі адрестің мәні NULL екенін немесе тізімнің аяқталғанын көрсетеді

 returnbuf;

}

Тізімнің ортасына жаңа ортасына жаңа элементті қосу

    elem* ortKosu(elem *const tizBasi, int k, int k1) //жаңа k1 элементті тізімнен    

                                     //ізделетін k элементтен кейін орналастыратын функция 

 {

          elem *berElemIzdeu=izdeu(tizBasi,k);  //берілген  k элементті  тізімнен іздеу

      if (berElemIzdeu!=0)               // k элемент табылса, онда жаңа k1-ді  

орналастыру басталады  

         {        elem* buf = new elem;  //жаңа k1-элементке жадыдан орын алып, адресін  buf-қа беру

buf->d=k1;  //жаңа  адреске  k1дің мәнін жіберу

buf->adrK=berElemIzdeu->adrK;        //жаңа элементтің кейінгі адресіне табылған элементтің кейінгі адресі беріледі   

buf->adrA=berElemIzdeu;               //жаңа элементтің алдыңғы адресіне табылған элементтің  өзінің  адресі беріледі   

berElemIzdeu->adrK=buf;   //табылған  элементтің кейінгі адресіне

жаңа  элементтің адресі беріледі   

                    }

}

Тізімнің элементін анықтау және бірінші элементті құру 

Біріншіден, тізім элементінің жалпы құрылымы анықталады, мысалы:

 struct elem // тізімнің элеменітін жариялау

{   int d; // деректер сақталған өріс

elem*adrK; //келесі элементтің адресі сақталған көрсеткіш өрісті жариялау

elem*adrA; //алдыңғы элементтің адресі сақталатын көрсеткіш өрісті жариялау

};

Функция түрінде тізімге бірінші элементті құру

elem* elem_1(int d) // тізімнің бірінші элементін құратын функция

{

elem*buf=newelem; // жаңа элемент үшін жадыдан орын алу және оның адресін buf көрсеткіш түріндегі айнымалыға жіберу

buf->d=d; //сол адрес бойынша d-мәнді жіберу

buf->adrK=0; //келесі адрестің мәні NULL екенін немесе тізімнің аяқталғанын көрсетеді

 returnbuf;

}

Тізімнің соңына жаңа элементті қосу

Тізімді өңдеу амалдарына функциялар түрінде анықталған келесі амалдарды жатқызуға болады:

- тізімнің соңына жаңа элементті тіркеу, мысалы:

void kosuS(elem** tizSoni,int d) //тізімнің соңына жаңа элементті қосу

{

elem *buf=new elem; //жаңа элемент үшін жадыдан орын алу және оның адресін buf             көрсеткіш түріндегі айнымалыға жіберу

buf->d=d; //сол адрес бойынша жаңа элементтің мәні d-ны жіберу

buf->adrK=0; //келесі адрестің мәні NULL екенін немесе тізімнің аяқталғанын көрсету

buf->adrA=* tizSoni; //жаңа элементке оның алдында тұратын элементтің адресін беру

(*tizSoni)->adrK=buf; //енді, алдыңғы тұрған элемент үшін келесі адрес болып жаңадан қосылған элементтің buf- та сақталған адресі беріледі

* tizSoni=buf; //көрсеткішке соңынан қосылған элементтің адресін беріп оны тізімнің соңына жылжыту

}

Тізімнің элементін жою функциясы

тізімнен элементті алып тастауды орындайтын функцияны келесі түрде құруға болады, мысалы:

bool aluEl(elem** tizBasi, elem** tizSoni,int k) //берілген k элементті тізімнен тауып, оны өшіріп тастайтын функцияны жариялау

{

elem* berElemIzdeu=izdeu (*tizBasi,k); //k үшін орындалатын izdeu функциясының нәтижесін berElemIzdeu –ге беру, егер ол k табылса, онда berElemIzdeu-ге сол элементтің адресі, табылмаса ноль беріледі.

if (berElemIzdeu!=0) // k элементтабылса, онда

{

if (berElemIzdeu == *tizBasi) // k элементтің орнын тексеру, егер ол тізімнің басында тұрса онда

{

*tizBasi = (*tizBasi)->adrK;

(*tizBasi)->adrA=0; //тізімнң басы k-дан кейін тұрған элементке жылжиды

}

else {

if (berElemIzdeu == *tizSoni) // k элементтің орнын тексеру, егер ол тізімнің соңында тұрса онда

{

*tizSoni =(*tizSoni)->adrA;

(*tizSoni)->adrK=0; //тізімнің соңы k-ның алдындағы элементке жылжиды

}

else //егер ол k элемент тізімнің ортасында тұрса онда

{

(berElemIzdeu->adrA)->adrK= berElemIzdeu->adrK;

{

elem* berElemIzdeu=izdeu (*tizBasi,k); //k үшін орындалатын izdeu функциясының нәтижесін berElemIzdeu –ге беру, егер ол k табылса, онда berElemIzdeu-ге сол элементтің адресі, табылмаса ноль беріледі.

if (berElemIzdeu!=0) // k элементтабылса, онда

{

if (berElemIzdeu == *tizBasi) // k элементтің орнын тексеру, егер ол тізімнің басында тұрса онда

{

*tizBasi = (*tizBasi)->adrK;

(*tizBasi)->adrA=0; //тізімнң басы k-дан кейін тұрған элементке жылжиды

}

else {

if (berElemIzdeu == *tizSoni) // k элементтің орнын тексеру, егер ол тізімнің соңында тұрса онда

{

*tizSoni =(*tizSoni)->adrA;

(*tizSoni)->adrK=0; //тізімнің соңы k-ның алдындағы элементке жылжиды

}

else //егер ол k элемент тізімнің ортасында тұрса онда

{

(berElemIzdeu->adrA)->adrK= berElemIzdeu->adrK;

Файлды құру, ашу және жабу.

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

– ofstream file_object («файлдың Аты»);

– мұндағы, ofstream – типі, file_object – объектінің аты, файлдыңАты –дискіде, ағымдағы бумада құрылатын файлдың аты, мысалы:

– ofstream file_object ("FILENAME.ТXT "); // FILENAME.ТXT мәтіндік файлын құру

– ofstream file_object ("FILENAME. DAT "); // FILENAME. DAT бинарлық файлын құру

Программада ofstream типіне жататын объектіні жариялағанда дискіде көрсетілген атпен файл құрылады, егер дискіде дәл сондай атпен құрылған файл бұрыннан бар болса, онда ол жойылып, оның орнына соңғы құрылған жаңа файл баратын болады.

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

– ifstream file_object («файлдың Аты «, ашу режимі);

мұндағы, ifstream –типі, file_ object – объектінің аты, файлдыңАты оқу үшін ашылатын файлдың аты, ашу режиміфайлдың қандай мақсат үшін ашылатынын тағайындайтын параметр.

Дискідегі сақталған файл түрлі мақсаттар үшін ашылуы мүмкін, мысалы ондағы деректерді өзгертпей экранға шығару керек болуы мүмкін немесе ол файлға қосымша тағы да деректер жазу үшін ашу керек болады.

Файлға еркін қатынау  

Файлға деректер жазуды немесе файлдан деректер (байттар) оқуды біріншісінен кейін екіншісіне көшіп, біртіндеп  немесе файлдың кез-келген көрсетілген позициясынан бастап жүргізуге болатыны мәлім (8.2 қараңыз). Файлдағы байттарды біртіндеп пайдалану, бұл- көп қолданылатын, кең тараған әдіс. Осы кезге дейінгі  файлға қатысты  қарастырылған   жаттығулардың  барлығында дерлік,  файлға қатынау біртіндеп жүргізілді. Бірақ программалауда көптеген есептерді шешуде файлға біртіндеп қатынау тиімді болып табылмайды, мысалы, дискідегі бумалардың өзі файл сияқты сақталады, ал бумадағы қажет файлды тауып, оны ашу үшін оған дейінгі файлдардың бәрін біртіндеп қарамайды, бірден сол қажет файлға түсу керек болады. Мұндай есептер өте көп, сондықтан бұл мәселені шешуде  «файлға еркін қатынау» әдісін қолданады.  Бұл әдісті жүзеге асыру үшін С++ программалау тілінде файлмен байланысты get-көрсеткіш және  put-көрсеткіш деп аталатын екі көрсеткіш анықталған. Бұл көрсеткіштердің қызметі файлға жазу немесе файлдан оқудың қай жерден  (позициядан)  басталатынын көрсету болып табылады. Осы аталған екі көрсеткіштер негізінде құрылған, файлға еркін қатынауда көп қолданылатын функцияларға seekg()  және  seekp()  функциялары жатады. Функциялардың программадағы жазылулары келесі түрде болады:

seekg(off_type байтНомері, seekdir көрсеткішАғымдағыМәні);

seekp (off_type байтНомері, seekdir көрсеткішАғымдағыМәні);

 мұндағы, байтНомері –байттың файлдағы позициясын көрсетеді, оның типі off_type , ios класында анықталған бүтін санды  мән болып келеді, ал көрсеткішАғымдағыМәні – байтНомерін қай жерден бастап санауды көрсетеді, мысалы файйлдың басынан бастап немесе соңынан санағанда және т.б. деген сияқты. Оның типі seekdir саналатын тип түрінде анықталған, келес мәндерді қабылдай алады: ios::beg - файлдың басы, ios::cur – ағымдағы позиция және ios:: end - файлдың соңы.

Сонымен seekg() функциясы файлдың get-көрсеткішін көрсеткішАғымдағыМәнінде берілген орынға қатысты алғанда байтНомері  позицияға жылжыта алады.

seekр() функциясы файлдың put-көрсеткішін көрсеткішАғымдағыМәнінде берілген орынға қатысты алғанда байтНомері  позицияға жылжыта алады.

Бұл seekg()  және  seekp()  функцияларын бір мәнділік сақталатын екілік файлдар үшін ғана қолданады.

Төменде  seekp()  функциясын қолдануды көрсететін жаттығулар берілген. Бұл жаттығуларды берілу реті бойынша жеке-жеке орындау керек.

8.3.1- жаттығу. Келесі программа  пернетақтадан енгізлген бүтн сандарды massiv.dat екілік файлға жазуды орындайды:

#include <iostream.h>

#include <conio.h>

#include <fstream.h>

int main()

{

int k;                                           

     ofstream FileGazu("massiv.dat");                                                                                   

for(int i=0;i<5;i++)

  {

cin>>k;  

FileGazu.write((char*)& k, sizeof (int));         

 }

     FileGazu.close();  

}

Бұл программа орындалуының нәтижесі , төмендегі консол терезесінде  

1

2

3

4

5

енгізілген  бүтін сандардың  massiv.dat файлына жазылуымен аяқталады.  

Файлды ашу режимдері

Ашу режиміне сәйкес параметр мәні               Орындайтын қызметі

ios::app                                                     файлды дерек қосу үшін ашу және файлдық

                                                                көрсеткішті файлдың соңына апару

ios::ate                                                     файлдық көрсеткішті файлдың соңына апару

ios::binary                                                Файлды екілік (бинарлық) режимде ашу

ios::in                                                      файлды дерек енгізу үшін ашу

ios::nocreate                                              файл табылмаған жағдайда, файлды жаңадан

                                                              құрмай қатені хабарлау

ios::noreplace                                          файл табылған жағдайда, файлды ашу опера-

                                                              циясын үзіп,қатені хабарлау

ios::out                                                  файлды шығару үшін ашу

ios::trunc                                               Файлдағы деректі жою

С++ программалау тілінде жалпы файлды ашу кезінде open(); функциясын қолдану қарастырылған, жазылуы:

ifstream file_object; //файлдық объектіні жариялау

file_object. open («файлдыңАты «, ашу режимі); //файлды ашу

Бірақ ofstream, ifstream және fstream кластарында файлды ашуды автоматты түрде орындайтын конструкторлар болғандықтан программисттер open(); функциясынқолданбай-ақ, файлдарды жоғарыда келтірілген әдіспен аша береді. Файлды жабу үшін close (); функциясын қолданады. Бұл close(); функциясының параметрлері болмайды және ол ешқандай мән қайтармайды.

Функция параметрлерінің мәндер бойынша берілуі

Параметрлердің мәндер бойынша берілуінде функция шақырылуындағы нақты параметрлердің орнында тұрған айнымалылардың көшірмелері жасалады. Функцияны шақыру кезінде стектегі формальды параметрлердің орнына мәндері анықталған айнымалылардың көшірмелері барады, яғни функция нақты параметрлердің көшірмелерімен ғана жұмыс жасай алатын болады, ал нақты параметрлердің орнында тұрған айнымалылардың мәндерін (немесе, оригиналдарын) функция өзгерте алмайды.

4.2-жаттығу. Келесі программа функцияның нақты параметрлері ретінде берілетін x=1 және y='+' айнымалыларының мәндерін функцияның өзгерте алмайтынынын көрсете алады:

#include <iostream.h>

#include <conio.h>

int ozgermeu( int i, char c); //прототипті жариялау

int main()

{

int x=1; // х-айнымалының бастапқы мәні

char y=’+’; // y-айнымалының бастапқы мәні

cout<<»\n bastapki manderi: \n x=»<<x<<»; y=’»<<y<<»’;»;

ozgermeu (x,y); // х, y-айнымалылардың мәндерін өзгертуші функцияны шақыру

cout<<»\n\n funcion- nan keingi mander : \n x=»<<x<<»; y=’»<<y<<»’;»;

getch();

}

int ozgermeu (int i, char c) //функцияны жариялау басталды

{

i++; //і-параметрдің мәнініне 1-ді қосып өзгерту

c=’-’; //-параметрдің мәнініне ‘-’ қойып өзгерту

} //функцияны жариялау аяқталды

Бұл программа орындалғанда келесі нәтиже алынады:

bastapki manderi:

x=1; y=’+’; 

funcion- nan keingi mander:

x=1; y=’+’;

Функция параметрлерінің сілтеме бойынша берілуі

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

бойынша беруде көрсеткіштер мен сілтемелер қолданылады Әдетте, сілтеме айнымалының қосалқы есімі немесе псевдонимі болып табылады. Сілтеме бойынша

мәндерді параметрлерге беру барысында, негізінен ол мәндер сақталып

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

int ozgeru( int *i, char &c); //функцияның прототипі,

мұнда * - көрсеткіш, &с – адреске сілтеме түрінде анықталған параметрлер

Функцияны шақыру барысында формальды көрсеткіш параметрге сәйкес нақты параметрдің алдына & адресті алу амалы қойылады ал сілтеме параметрге сәйкес нақты параметрдің алдына бұл белгі қойылмайды, мысалы: ozgeru(&x,y); // функцияны программада шақыру мұндағы, int *i көрсеткіш түрінде анықталған параметрдің орнына баратын х- нақты параметрдің алдына адресті алу амалының & белгісі қойылды.

Функцияны жариялау. Прототип.

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

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

тип функция_аты (тип параметр1, …, тип параметрN)

{

айнымалыларды_жариялау;

операторлар;

return (қайтаратын мән);

}

мұндағы, тип функция орындалғаннан кейін қайтарылатын мәннің немесе функция нәтижесінің типін көрсетеді, бұл С++-тегі массив пен функциядан басқа кез келген тип бола алады. Егер функция орындалуының нәтижесі белгілі бір типті қайтармайтын болса, онда оның типін void деп анықтайды.

функция_аты – бұл дұрыс идентификатор болып табылады; тип параметр1, …, тип параметрN- бұл функцияның жұмысына қатысатын, яғни функцияға сырттан деректер беру үшін немесе т.б. үшін қолданылатын айнымалы - аргументтер және олардың типтері. Бұл айнымалыларды функцияның параметрлері немесе функцияның аргументтері деп  атайды. Сондай-ақ, функцияны жариялағанда бұл параметрлердің болмауы да мүмкін. Функция параметрлері берілмеген жағдайда функция келесі түрде жазылады:

тип функция_аты ()

{

айнымалыларды_жариялау;

орындалатын_операторлар;

return (қайтаратын мән);

}

Егер функция да параметрлер көрсетілетін болса, онда оны параметрлі функция деп атайды. С++ программалау тіліндегі функцияның жазылуындағы бірінші тұрған,

тип функция_аты ( тип пара-метр1, …, тип параметрN)

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

С++ программалау тілінде функцияны жариялауды оның программадағы шақырылуынан кейін де немесе бұрын да жасай беруге болады. Осыған байланысты функцияның жариялануы екі түрлі жолмен берілуі мүмкін:

– Бірінші жағдайда функцияның прототипін жариялау қарстырылсын. Функция прототипін жариялау – бұл функцияның тақырыбы мен денесін программада функция шақырылғаннан кейін анықтайтын жағдайларда қолданылады, яғни прототипі жарияланған функцияны жариялау програмамманың кез келген жерінде жүргізіле береді, сондай-ақ, ол функцияның жариялануы басқа модульде немесе файлда болуы да мүмкін. Бұл кезеңнің қызметі программадағы функция орындауға жіберілмей тұрып, яғни ол шақырылғанға дейін функция қайтаратын мәнге және оның параметрлеріне жадыдан қажет орын алып қоюды және функция кодының кейін анықталатынын негізгі орындалатын программаға хабарлауды қамтамазыз ету болып табылады.

Функция прототипін жариялаудың синтаксисі:

Мысалы, жай ғана «Мені . атым Қожа» деген мәтінді жаңа жолға шығаратын

функцияның жазылуы:

void gazu () //параметрі жоқ функция

{

cout<<»\n Менің атым Қожа»; // оператор

}

тип функция_аты (тип параметр1, …, тип параметрN);

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

Функция_прототипі; //прототипті көрсету

void main() //негізгі функция

{

функцияны шақыру;

}

функцияны жариялау;

– екінші жағдайда программада функцияның прототипі берілмейтін болады, сондықтан функция бірден толығымен жарияланады, яғни мұнда функцияның прототипі болмайды да, функцияның тақырыбы және денесі толығымен функция шақырылғанға дейін анықталып кетеді. Бұл жағдайдағы қолданушы құратын функция жариялануының, негізгі функция main()-ге қатысты орналасуын келесі түрде береді:

функцияны жариялау;

void main()

{

функцияны шақыру;

}

Функцияны қайыра жүктеу 

Функцияларды қайыра жүктеу бұл қажеттіліктен туындаған нәрсе, мысалы, бастапқы С тілінде  берілген санның модулін табу үшін abs(int x), labs(long x)  және fabs(float x) деп аталатын үш функция қолданылды.  Бұл үш функцияның орындайтын қызметі бірдей, айырмашылық тек қана параметрлерінің типтерін де ғана болып тұр.  Олардың орындайтын амалдары біреу болғанына қарамастан,  олардың әрқайсысына жеке атау (уникальная имя) беріліп тұр, демек программист олардың үшеуін де жатқа білуі керек деген сөз, бұдан басқа мұндай нәрселер өз кезегінде программа құрылымының күрделенуіне және түсініктілігінің төмендеуіне де әкеліп соқтырады. Осындай себептерге байланысты программалау тілдерінде орындайтын әрекеттері бірдей немесе ұқсас болып келетін, тек қана параметрлерінің типтері мен сандары ғана өзгеше болатын функцияларды бір атаумен ғана беретін, «функцияны қайыра жүктеу» механизмі қарастырылған.    Сонымен, қайыра жүктелген функциялар - атаулары бірдей, бірақ параметрлерінің типтері  және сандарына қарай әр түрлі нәтижелер беретін әрекеттерді орындайтын функциялар.

Функцияларды қайыра жүктеу – бұл объектіге бағдарланған программалаудағы  «бір интерфейс- бірнеше әдіс» немесе полиморфизм принципін жүзеге асырудың бір жолы ретінде қарастырылған.

Функцияны шақыру. 

Жарияланған функцияны программада пайдалану үшін, оны аты арқылы шақырады. Жарияланған функцияның программадағы шақырылуын келесі түрде жазады:

функция_аты (парам1, парам2, …, парамN) ;

немесе

функция_аты () ; // параметрсіз функцияның шақырылуы

Жарияланған функцияның тақырыбындағы параметрлерді – шартты түрде алынған «формальды» параметрлер деп, ал шақырылған функциядағы параметрлерді жұмысшы немесе «нақты (фактические)» параметрлер деп қарастырады. Функция шақырылғанда ең алдымен формальды параметрлер мен нақты параметрлердің типтерінің сәйкестігі тексеріледі, егер сәйкес келмесе қате туралы хабарланады. Көпшілік жағдайларда функцияның шақырылуындағы параметрлердің саны және типтері функцияның тақырыбындағы немесе прототипіндегі параметрлер санымен және олардың типтерімен сәйкес бо лып келеді. Бірақ кейбір функцияларда ( мысалы, printf ) параметрлердің саны өзгере береді, типтері де өзгере береді. Мұндай функциялардың жариялануындағы немесе прототиптеріндегі параметрлердің орнына «...» – көп нүкте белгісі қойылады,

мысалы, прототипі:

      void MyFunc(…);

болатын функцияның шақырылуында оның параметрлер саны да, типі де өзгере беруі мүмкін. Функцияны шақыру барысында қайтарылатын тип көрсетілмейді. Мысалы, барлық программаларда дерлік қолданылып жүрген getch(); – бұл да стандарт функциялардың бірінің шақырылуы болып табылады.

Функцияның параметрлері.

Параметрлер механизмін жалпы екі функция арасындағы (жарияланған және шақырылған) дерек алмасу ретінде қараған дұрыс болады. Функцияны программада шақырғанда, алдымен оның шақырылуындағы нақты параметрлердің орнында тұрған өрнектердің мәндері есептеледі, сонан соң барып, жедел жадының стек деп аталатын арнайы бөлімінде функция жариялануындағы формальды параметрлер үшін олардың типтеріне сәйкес орындар бөлінеді, сол орындарға нақты параметрлердегі мәндер жіберіледі. Осыған байланысты, функция параметрлерінің мәндерін беру екі түрлі жолмен жасалады:

– параметрлердің мәндер бойынша берілуі;

– параметрлердің адреске сілтеме бойынша берілуі.

Функция параметрлерінің массивтер түрінде  берілуі 

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

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

Программа  массив-параметрмен жұмыс жасайтын функциялардың қызметін көрсетеді / Массивтің оң элементтерін баспаға шығаратын функция - MasKoru ,  ал жұп элементтерін көрсету  мен олардың қосындысын есептеу - summa  функциясы түрінде анықталған/.

#pragma hdrstop

#include <iostream.h>

#include <conio.h>

#include <math.h>

//---------------------------------------------------------------------------

#pragma argsused

void mas(int *a,const int  n);

  const n=7;

  int main()

  {

  int mymas[n];

     int *p=mymas;

for(int i=0; i<n;i++)

     mymas[i]=random(20)+3;

     cout<<" massiv=";

     mas(p,n);

     getch();

  }

void mas(int *a,const int n)

  { int buf=0;

int i;

for(int i=0;i<n;i++)

    cout<<" "<<a[i];

    cout<<"\n";

for(int i=0;i<n;i++)

    {if(buf<a[i])

buf=a[i];

}

      cout<<"\nmax="<<buf;

  }

Программа нәтижесі келесі түрде болады:

Massiv= 12 7 9 7 15 6 19

 Max=19

 Функцияның көру аймақтары. Жергілікті көру аймағы

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

Жергілікті көру аймағы

Жергілікті көру аймағы блоктың, яғни { }- фигуралы жақшаларға алынған бөліктің көмегімен жасалады (2.6.2- тақырыпты қараңыз).  Ереже бойынша, программада құрылған әрбір осындай блокка сәйкес оның өзінің көру аймағы анықталады. Мұндай блоктардың  ең көп қолданылатын түрі бұл – функциялар екені белгілі. Функцияның денесіндегі немесе оның фигуралы жақшаларға алынған бөлігіндегі коды оның тек қана өзінікі болып саналады, басқа ешбір функцияның ол  кодта анықталған айнымалыларды немесе т.б. деректерді пайдалануға құқығы жоқ.  Бұл ереже, функцияның, программаның басқа бөліктеріне әсер етпеуін және керісінше басқа бөліктердің ол функцияға әсері тимеуін, яғни функция аймағындағы деректердің барынша қорғалғанын білдіреді. Мысалы, goto  операторын пайдаланып, басқа бір функциядағы операторға көшу мүмкін емес, себебі ол функция goto -ны өз аймағына кіргізбейді. Функциялардың көру аймақтары  әртүрлі болғандықтан, бір функция аймағында анықталған код пен деректер, екінші бір функцияның коды мен деректеріне тәуелсіз болады. Осыған байланысты бір программада, бірақ әртүрлі функциялардың аймағында жарияланған аттары бірдей айнымалылар кездесе береді.   

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

Функцияның Кең ауқымды көру аймағы

Программаға бөлінген жады облысының функциялардан тысқары бос қалған жерінің барлығы кең ауқымды көру аймағына беріледі. Функциялардың сыртында, кең ауқымды көру аймағында анықталған айнымалыларды кең ауқымды айнымалылар деп атайды. Кең ауқымды айнымалылар программадағы барлық функцияларда да көрінеді, сонымен қатар, басқа файлдарда да көрінеді. Программалауда егер бір айнымалы бірнеше функциялардың жұмысына қатар қажет болатын болса, онда оны кең ауқымды айнымалы ретінде бір-ақ рет жариялайды.  Әдетте, программада, кең ауқымды айнымалыларды main()- ға дейін, барлық функциялардан бұрын жариялап кетеді. Егер кең ауқымды айнымалылар айқын түрде инициализациаланбаса, онда компилятор оның мәнін « ноль» деп аталады.

Функцияны көру аймақтары. extern спецификаторы

Кейбір жағдайларда, кең ауқымды айнымалы мен негізгі орындалатын программа немесе main() функциясы, екеуі, екі басқа файлда сақталған болуы мүмкін. Мұндай жағдайда, басқа файлдағы кең ауқымды айнымалыны негізгі программаға кірістіру үшін extern спеификаторын қолданады.

f=a*x2+b*x+c; өрнегінің мәнін есептейтін esepteu() функциясын құру керек. Мұнда,бүтін типті кең ауқымды a,b,c,x,f айнымалылары және esepteu() функциясының өзі, main()- нан басқа бөлек файлда жарияланып сақталуы керек. Бұл есепті шешу үшін, жаңадан құрылатын жобада, мысалы, Project1 жобасында негізгі программа мәтіні жазылатын Unit1.cpp файлынан басқа, esepteu() функциясының мәтін

жазылатын тағы да бір Unit2.cpp файлы құрылуы керек. Ол үшін ашық тұрған жобада, File -> New -> Unit командалары орындалады, нәтижесінде Unit2.cpp терезесі пайда болады, осы терезедегі файл мәтінінде, кең ауқымды a,b,c,x,f айнымалылары extern арқылы жарияланып, esepteu() функциясының мәтіні теріледі, бұл Unit2.cpp файлын esepteu деген атпен сақтауға да болады, Unit2.cpp немесе esepteu.cpp файлының мәтіні:

#include "esepteu.h"

extern int a,b,c,x,f; //кең ауқымды айнымалыларды extern арқылы жариялау

esepteu() // функцияның өзін жариялау

{

f=a*x*x+ b*x+c;

return(f);

}

Программаның немесе Unit1.cpp файлында сақталатын main() –нің мәтіні:

#include <iostream.h>

#include <conio.h>

#include "esepteu. срр " // esepteu.срр файлын программаға кірістіру

int a=5,b=7,c=10, x, f; // кең ауқымды a,b,c,x,f айнымалыларын жариялау

int main()

{ cin>>x;

f=esepteu(); // esepteu(); функциясын шақыру

cout<<"\n f="<<f;

getch();

}

Программа орындалуының нәтижесі

төмендегідей болады:

1

f=22

Функцияның көру аймақтары. static спецификаторы қызметі

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

шаблон функциялар

С++ те  функция шаблоны немесе шаблон функциялар деп аталатын механизм қолданылады.  Ол механизм бойынша әртүрлі типтегі деректер үшін қолданылатын алгоритм бірдей, яғни біреу болғандықтан осы  алгоритмге сәйкес функция,  шаблон түрінде бір-ақ рет жазылады. Программист шаблон түрінде жазылатын функция параметрінің типін,  class қызметші сөзін пайдаланып шартты түрде ( немесе  формальды түрде) тағайындайды.  class қызметші сөзімен анықталған тип, программист өзі құрған қолданушының типі болып есептеледі. Шартты түрде анықталған параметрдің орнына компиляциялау кезеңінде нақты параметрлер  жіберіледі де, шаблон- функция сол нақты параметрге сәйкес орындалатын болады.

Функция шаблонының программадағы жазылуы келесі түрде болады:

       template  <class тип1, class тип2, ..., class типN>

                     функция_аты (тип1 параметр1, …, типN  параметрN)

{ айнымалыларды_жариялау;
 операторлар;

  return (қайтаратын мән);

}

мұндағы, template  функция шаблонын жариялаудың басталғанын білдіреді, ал class,  функцияның формальды параметрлерінің типтерін шартты түрде анықтау үшін қолданылады,  тип1, тип2, …, типN-  дұрыс тағайындалған идентификаторлар болып табылады .

Функция шаблондарында   class сөзімен анықталған типтерден басқа жай айнымалыларды да пайдалана беруге рұқсат етіледі , мысалы келесі түрде :

template  <class тип1, class тип2, ..., int  n>                     

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

#include <iostream.h>

#include <conio.h>

template <class type1>  // шартты түрдегі type1 типін жариялау

void TikeSuriptau(type1 *b, int n) //шаблон - функцияны жариялау басталды

{

type1 buf;

for (int i = 0; i<n-1; i++)

{

int imin = i;

for (int j = i + 1; j<n; j++)

if (b[j]<b[imin])

   imin = j ;

buf = b[i];

b[i]=b[imin];

b[imin]=buf;

}

for (int i = 0; i<n; i++)

cout<<" "<<b[i];

}   //шаблон - функцияны жариялау аяқталды

int main()

{

const int n = 7;

int i, b[n]={7,-1,5,9,0,-6,3};

cout<<"\n\n int - massivti suriptau :" ;

TikeSuriptau(b,n); //Шаблон-функцияны b[n] бүтін сандар массиві үшін шақыру

double a[]={0.22, 1.17, -0.08, 0.21, 42.5};

cout<<"\n\n  double - massivti suriptau :" ;

TikeSuriptau(a,5); // Шаблон-функцияны а[] нақты  сандар массиві үшін шақыру

char c[]="suriptau";

cout<<"\n\n  char - massivti suriptau :" ;

          TikeSuriptau(c,strlen(c));       //Шаблон-функцияны c[] символдық

                                                               // массив үшін шақыру

getch();

}

Программа орындалуының нәтижесі келесі түрде болады:

int - massivti suriptau :     -6  -1  0  3  5  7  9

double - massivti suriptau :  -0.08  0.21  0.22  1.17   42.5

char - massivti suriptau :  a  i  p  r  s  t  u  u




1. Тюменнефтегаз дочернее предприятие
2. федерация относится к форме государственного устройства и отражает территориальное деление государства и
3. Тема3 Механизм административноправового регулирования ПЛАН Вопрос 1 Общая характеристика механизм
4. процесс целенаправленного воздействия людей на природу в результате которого создаются потребительские с
5. Экспертиза и управление недвижимостью Допускаю к защите
6. The profession of an interpreter
7. родственных связей 17 век итальянский философ Вико
8. Теория и практика лабораторных общеклинических исследований
9. реферату- ГрибиРозділ- Біологія Гриби Світ грибів цікавий та різноманітний
10. д~ріс Айнымалы ток машиналарыны~ электромеханикалы~ ~асиеттері Айнымалы ток машиналары арасынан ~ндір
11. Поняття позашкільної та позакласної виховної роботи
12. по отношению к учению от ответственного до равнодушного безразличного; 2 по общему развитию от высоко
13. Прогнозирование и планирование экономики для студентов всех специальностей на 2012-2013 учебный год.
14. Общество 11 Общество как сложная динамическая система- 1
15. Медиаисследования печатных СМИ
16. ПОЯСНИТЕЛЬНАЯ ЗАПИСКА К КУРСОВОЙ РАБОТЕ по дисциплине Метрология стандартизация и сертификация 1406
17. Исследование и оценка финансовой деятельности организации (На примере ООО
18. Источники права
19. ТЕМА- ЗМІНИ ЗВУКІВ У МОВНОМУ ПОТОЦІ.html
20. тематического направления в нём 20 юношей и 7 девушек возраста 1516 лет