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

Екі өлшемді массивтер

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

Мысалы, int a[3][4];// 3 жол 4 бағаннан тұратын бүтін санды массив сипатталған

Массив үзіліссіз облыста жол бойында сақталады.

Бірінші a[0] массиві өзінің элементтерімен, сосын екінші массив өзінің элементтерімен т.с.с тізбектеліп орналасады.

Бірінші оның баған нөмері өзгереді, яғни оның оң жағындағы индексі өзгереді.

Оның элементтеріне нөмері арқылы қатынайды және a[i][j] конструкциясы арқылы жасалады.

Матрица элементтерін инициализациялайды

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

Осы жазу математикадағы

матрицаға сәйкес келеді.

Егер фигуралы жақша ішіндегі сандар артық болса, онда қате туралы хабарлама шығады, ал ондағы сандар кем болса, онда жетпеген элементтің орнына 0 қойылады. Жалпы барлық элементттерін бірден бермесе де болады.

int a[3][4]={{1,2},{4,5},{7,8}}; түріндегі жазуға болады, ал жазылмаған элементтер орнына 0 қойылады.

матрицасы сәйкес келеді.

5-дәріс. Функция. Функцияны сипаттау мен анықтау

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

[класс] типі аты (параметрлер тізімі)

{ функция денесі}

Анықтаудың құрамдас бөліктерін жеке қарастырайық:

Міндетті емес класс модификаторы extern және static арқылы функцияның әрекет ету облысын беруге болады.

extern- ауқымды әрекет, программаның барлық модульдерінде анықталады(көрсетілмеседе)

static-функция анықталған модуль ішінде ғана көріеді.

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

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

#include <iostream.h>

#include <conio.h>

#pragma hdrstop

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

#pragma argsused

int f(int a1,int b1); // функцияны сипаттау

int main()

{

int a=10,b=20,c=35,max;

max=f(a,b); // функцияны шақыру

max=f(max,c); // функцияны шақыру

cout<<" max="<<max; // алған нәтижені экранға шығару

getch();

return 0;

}

int f(int a1,int b1) //функцияны анықтау

{ int m;

if (a1>=b1) m=a1; else m=b1;

return (m); }

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

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

#include <iostream.h>

#include <conio.h>

#pragma hdrstop

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

#pragma argsused

void f(int a){

int m=0;

cout<<" m n p\n";

while (a--){

static int n =0;

int p=0;

cout<<n++<<" "<<m++<<" "<<p++<<"\n";

}

}

int main()

{ f(3);

f(2);

getch();

return 0;

}

n статистикалық айнымалы деректер сегментінде орналасады және бірінші функцияның шақырылуында тек бір рет қана инициализацияланады. m автоматты айнымалы функцияға енгізілген сайын иницализацияланады. Ал, р автоматты айнымалы цикл блогына енген сайын иницализацияланады

Функциядағы static модификаторын алып тастасақ, төмендегідей жауап аламыз.

Функцияның қайтаратын мәні.

Шақырылған функция мәні return [ өрнек]; механизмі арқылы қайтарылады. Функцияда бірнеше return жазылуы мүмкін. Таңдаған алгоритмге байланысты.

void деп сипатталған функцияда return жазбасада болады.

Төменде бірнеше варианттар көрсетілген:

int f1() {return 1;} // дұрыс

void f2(){return 2;} // дұрыс емес, f2 функциясы мән қайтармайды

double f3() {return 1;} // дұрыс, бүтін 1 саны double типіне түрленеді.

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

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

Функцияға параметрді берудің екі тәсілі бар.

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

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

#include <iostream.h>

#include <conio.h>

void f(int i, int*j,int& k);

int main(){

int i=1,j=2,k=3;

cout<<" i j k\n";

cout<<i<<" "<<j<<" "<<k<<"\n";

f(i,&j,k);

cout<<i<<" "<<j<<" "<<k<<"\n";

getch();

return 0;

}

void f(int i, int*j,int& k)

{i++;(*j)++;k++;

}

Бірінші параметр i мәні бойынша беріледі. Функциядағы өзгеріс оның бастапқы мәніне әсер етпейді. Екінші параметр адресі бойынша берілді. Үшінші параметр адреске сілтеме арқылы беріліп тұр.

6-дәріс Көрсеткіштер

Программаның орындалу барысында компилятор int i=10; деген операторды өңдеу кезінде оған int типіне сәйкес келетін жады бөледі, сонымен бірге көрсетілген 10 санын сонда жазады. Программаның ішінде і айнымалысына аты арқылы қатынауды компилятор жады облысының адресімен алмастырады.

Программалаушы жады облысының адресін сақтайтын өзінің айнымаларын анықтауына болады. Ондай айнымалыларды көрсеткіштер деп атайды. Көрсеткіштер жады облысының адресін сақтауға арналған. С++ -те үш түрлі көрсеткіш түрі бар:

  1. функцияға көрсеткіш

  2. объектіге көрсеткіш

  3. void көрсеткіштері.

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

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

Функция көрсеткішінің типі функция қайтаратын мән типі және көрсетілген аргумент типінен тұрады:

тип (* аты) ( аргументтер типі тізімі):

int (* fun)(double, double);

екі double типті аргументі бар int типті fun функциясы сипатталған.

2. Объектіге көрсеткіш – қандай да бір тип деректер сақтайтын жады облысының адресін сақтайды:

тип * аты;

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

int *a, b,*c;

Void көрсеткіші. Объектінің нақты типі анықталмаған жағдайда, оның адресін сақтауға

Void көрсеткішіне кез келген типтің көрсеткішін меншіктеуге, салыстыруға болады, бірақ, оны амалдарды орындау барысында нақты типке түрлендіру керек.

Типтерді сипаттау:

int i; // бүтін айнымалы

const int ci=1; // бүтін тұрақты

int * pi; // бүтін айнымалыға көрсеткіш

const int *pci; // бүтін тұрақтыға көрсеткіш

int * const cp=&I; // бүтін айнымалыға тұрақты көрсеткіш

const int * const cpc= &ci; // бүтін тұрақтыға тұрақты көрсеткіш

Көрсеткіштерді инициализациялау

Көрсеткіштер динамикалық жадымен жұмыс істеуге қолданылады.

Динамикалық жады программаның орындалуы барысында керегіне қарай бөлуге болатын бос жады облысы. Динамикалық жадының берілген бөлігімен

Int**a int*a[nstr] int a [nstr] [nstb]

0 1 nstb-1

Nstb

1.10-сурет.Екі өлшемді массивке жады бөлу

Жадыны динамикалық бөлу

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

Адрестердің жоғарғы облысы

Стек

Куча

Ауқымды айнымалылар

Программа коды

Аррестердің төменгі облысы

# include <iostream.h>

# include <conio.h>

#pragma hdrstop

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

#pragma argsused

int main(int argc, char* argv[])

{

int *p;

p=new int ; // int типке жады бөледі

*p=20;

cout << *p;

delete p;

getch();

return 0;

}

немесе

int *p;

p=new int (99); // жадыға санды орналастыру арқыл инциализациялау

Массивке жады бөлу

int main(int argc, char* argv[])

{

double *p;

int i;

p=new double [10]; // 10 элементтен тұратын массивке жады бөлу

for (i=1; i<10;i++)

p[i]=100.00+i;

for (i=1; i<10;i++)

cout << p[i] <<" ";

delete []p; жадыны толық босату.

getch();

return 0;

}

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

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

Сызықтық тізімдер: бір байланыты және екі байланыты тізімдер. Олардың ақпараттық бөлімі және көрсеткіштерден тұрады.

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

Динарлы тармақ-Атадан баланың тармақталуы принципімен жасалған динамикалық структуа.

Бүтін сандардан тұратын сызықтық тізімнің сипатталуы

struct Node{

int d;

Node *p;

};

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

Берілетін аралықта өзгеретін аргумент үшін Ch x функция мәнін( гиперболалық косинус ) таблица түрінде шығаратын программаны жазу . Функция мәнін Тейлор қатарына дәлдігімен жіктеу арқылы анықтайды.

Екінші семинарда біз осыған ұқсас есептерді қарастырғанбыз ( 2.4 және 2.5 есептірін қараңыз), сондықтан қатар қосындысын анықтау нәтижесі сізге таныс .Программаның жұмыс істеу алгоритмі жоғарыда да көрсетілген: әрбір аргумент мәні үшін функцияның мәні есептелініп, экранға шығарылады. Біздің бұл қатар қосындысын есептеу функциямызда аргументтің мәні мен дәлдігін алу қажет.Аргументтің мәні, дәлдігімен қатар шығарылатын мәні double типті болсын. Олай болса,функцияның басы былай беріледі:

double cosh (double х , double eps );

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

Программа мәтінін қарастырайық:

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

#include<stdio.h>

#include<math.h>

#include<сonio.h>

#pragma hdrstop

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

#pragma argsused

double cosh(double x, double eps); // функция басы

int main(int argc, char* argv[])

{

double Xn,Xk,dX,eps;

printf("Enter Xn,Xk,dX,eps \n");

scanf("%1f%f1%1f%f1",&Xn,&Xk,&dX,&eps);

printf("------------------------\n");

printf("| X | Y |\n");

printf("------------------------\n");

for (double x=Xn; x<=Xk; x+=dX)

printf("|%9.21f |%14.6g |\n",x,cosh(x,eps));

printf("------------------------\n");

getch ( );

return 0;

}

double cosh(double x,double eps){

const int MaxIter=500; //итерациялардың максималды саны

double ch=1,y=ch; //қатардың бірінші мүшесі және бастапқы қосынды мәні for (int n=0; fabs(ch)>eps;n++){

ch*=x*x/((2*n+1)*(2*n+2)); // қатар мүшесі

y+=ch; //қатар мүшесінің қосындыға қосылуы

if (n>MaxIter) {puts("Қатар жинақталмайды! \n");return 0;}

return y;

}

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

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

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

Өзгелерден тиімдірек әдіс –қосынды есептеудің сәтті аяқталуын сыртқа білдіру. Мұндай әрекет көбіне стандартты функцияларда қолданылады. Егер қате бір ғана рет шығатын болса, онда параметрге bool типін тағайындауға болады. Параметр шақырылатын программаға жіберіледі және сонда анализ жүргізіледі. Біздің есебіміз үшін бұл шешім былайша көрсетіледі:

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

#include<stdio.h>

#include<math.h>

#include<conio.h>

#pragma hdrstop

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

#pragma argsused

double cosh(double x, double eps, int &err);

int main(int argc, char* argv[])

{

double Xn,Xk,dX,eps,y;

int err;

printf("Enter Xn,Xk,dX,eps \n");

scanf("%1f%f1%1f%f1",&Xn,&Xk,&dX,&eps);

printf("------------------------\n");

printf("| X | Y |\n");

printf("------------------------\n");

for (double x=Xn; x<=Xk; x+=dX) {

y=cosh(x,eps,err);

if (err) printf("|%9.21f | Қатар жинақталмайды! |\n",x);

else printf("|%9.21f |%14.6g |\n",x,y);

}

printf("------------------------\n");

return 0;

}

double cosh(double x,double eps, int &err){

err=0;

const int MaxIter=500;

double ch=1,y=ch;

for (int n=0; fabs(ch)>eps;n++){

ch*=x*x/((2*n+1)*(2*n+2));

y+=ch;

if (n>MaxIter) {err=1;return 0;}

}

getch ( );

return y;

}

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

Бұл әдістің жеткіліксіз жағы функция параметрлер санының көбеюінде.Біз сіздің err параметрінің алдында тұрған & белгісіне көңіл аударғаныңызға үміттенеміз.Ол сілтеме арқылы берілетін параметр. Мұндай әдіс мәндердің функциядан шақырылатын программаға берілуіне мүмкіндік береді. Қазір функцияға берілетін параметрлердің механизмін қарастыруға болатын уақыттың дәл өзі.Ол өте қарапайым болып келеді. Функция параметрлерінің тізіміндегі double х функция шақырылған кезде оған сәйкес келетін аргумент мәні берілуі тиіс екендігін білдіреді. Ол үшін стекке оның функция жұмыс істейтін көшірмесі алынады. Әрине, бұл көшірменің өзгерісі параметрдің сақталатын жады ұяшығына ешқандай ықпалын тигізе алмайды.Сондықтан бұл параметрдің орнына шақыру кезінде мысалға төмендегідей де өрнекті беруге болады :

у= cosh ( x +0.2, eps |100, err );

Өрнек есептелінеді де оның нәтижесі стекте арнайы бөлінген орынға жазылады.

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

//Функция басы(прототип):

double cosh ( double х , double eps , jot err );

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

у= cosh ( x , eps ,& err );

// функция ішінде err параметріне қатынау:

*еrr =0;

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

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

// функция басы :

Double cosh ( const double & х , const double & int eps . & err );

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

у= cosh ( eps x , err ):

// eps және х-ке қатынау функция ішінде өзгермейді

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