q = p;
p -ni siyahının 3-cь obyektinin ьzərinə sьrьşdьrək.
p = p->novb_el;
Siyahının ikinci obyektinin novb_el həddini 4 -cь obyektə mənimsədək:
q->novb_el = p->novb_el;
3-cь obyektin siyahı ilə əlaqəsini ləğv edirik :
p->novb_el = NULL;
Əgər bizə 3-cь obyekt artıq lazım deyilsə onu yaddaşdan silirik:
delete p;
Indi is g lin bьtьn bu dedikl rimizi icra ed n konkret proqram ə ə ə ə nьmunəsi daxil edək.
Proqram 3.
// prg_9_3.cpp
#include
#include
struct syh_el{
int x;
struct syh_el *novb_el;
};
syh_el *siyahi_yarat(struct syh_el *syh, int elem_say);
syh_el *siyahi_sil(struct syh_el *syh, int elem);
void siyahini_cap_et(struct syh_el *);
int main(int argc, char *argv[])
{
// istifade edeceyimiz deyishenleri elan edirik
syh_el *menim_syh;
// siyahinin bosh oldugunu bildirmek ucun
menim_syh = NULL;
int say,elem;
std::cout<<"Siyahinin elementlerinin sayini daxil edin \n";
std::cin>>say;
menim_syh = siyahi_yarat(menim_syh,say);
siyahini_cap_et(menim_syh);
std::cout<<"Siayhidan silmek istediyiniz elementin indeksini daxil edin\n";
std::cin>>elem;
menim_syh = siyahi_sil(menim_syh, elem);
siyahini_cap_et(menim_syh);
return 0;
} //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
syh_el *siyahi_yarat( syh_el *syh, int elem_say)
{ syh_el *
p, *
q;
p=syh;
q=syh;
int i,dey;
for (i=1; i<=elem_say; ++i)
{ std::cout<<"siyahinin "<
ci elementini daxil edin \
n";
std::cin>>dey;
p = new syh_el;
p->x = dey;
p->novb_el = NULL;
if (syh==NULL){
//siyahi boshdur, ilk element
syh=p;
q = p;
p = NULL; }
else {
//siyahida element var
q->novb_el = p;
q = p;
}}
return syh;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void siyahini_cap_et( syh_el *syh)
{ syh_el *
p;
int dey;
p = syh;
if (syh == NULL ) {
std::cout<<"Siyahi boshdur \n";
return;
}
std::cout<<"Siyahinin elementleri \n";
while(p!=NULL){
dey = p->x;
std::cout<
p = p->novb_el; // novbeti elemente kec
}
std::cout<<"\n";
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
syh_el *siyahi_sil(syh_el *syh, int elem)
{ syh_el *
p, *
q;
p=syh;
int i,dey;
if (syh==NULL)
return NULL; // siyahi boshdur
if (elem==1){
// silmek istediyimiz element ilk elementdir
syh = p->novb_el;
p->novb_el = NULL;
delete p;
return syh;
}
for (i=1; i
if (p==NULL) break;
else
p = p->novb_el;
if (p==NULL){
std::cout<<"Siyahida "<
return syh;
}
q=p;
p = p->novb_el;
if (p->novb_el==NULL)
{ // silmek istediyimiz element sonuncu elementdir
q->novb_el=NULL;
delete p;
p=NULL;
q=NULL;
return syh;
}
// silmek istediyimiz element araliq elementdir
q->novb_el = p->novb_el;
p->novb_el = NULL;
delete p;
q=NULL;
return syh;
}
Nəticə:
C:\cpp\prog2\Debug>prog2.exe
Siyahinin elementlerinin sayini daxil edin
7
siyahinin 1 -ci elementini daxil edin
23
siyahinin 2 -ci elementini daxil edin
45
siyahinin 3 -ci elementini daxil edin
123
siyahinin 4 -ci elementini daxil edin
567
siyahinin 5 -ci elementini daxil edin
78
siyahinin 6 -ci elementini daxil edin
345
siyahinin 7 -ci elementini daxil edin
99
Siyahinin elementleri
23 45 123 567 78 345 99
Siayhidan silmek istediyiniz elementin indeksini daxil edin
3
Siyahinin elementleri
23 45 567 78 345 99
C:\cpp\prog2\Debug>
C:\cpp\prog2\Debug>
Зalışmalar
1. Yuxarıda verilmiş proqram 2 nьmun sini el d yişin ki, siyahının obyektl ə ə ə əri цzьndə int tipli
x həddindən əlavə char tipli ad[20] həddi də saxlasın. Mьvafiq olaraq siyahi yaratma və
cap_et funksiyalarinda lazımi dəyişikliyi edin. Proqramı kompilyasiya və icra edin, siyahı
yaradin , onun elementlərini зap edin.
2. Yuxarıdakı proqrama axtarış funksiyası əlavə edin. Proqram istifadəзidən int tipli ədəd
istəyir və siyahıda x -i bu ədədə bərabər olan obyektin ad[20] -həddini зap edir.
3. İki siyahını birləşdirən funksiya tərtib edin. Funksiya parametr olaraq iki siyahı qəbul edir,
daha sonra bu siyahılardan birincini ikinci ilə birləşdirir.
4.Nьmunə Proqram 3 -də daxil edilmiş silmə funksiyasın elə dəyişdirin ki, siyahının verilmiş
indeksli obyektindən başlayaraq verilmiş sayda obyekti siyahıdan silsin.
$10 Siniflər.
Paraqraf $8 -də biz stuct tiplər ilə tanış olduq. Qeyd elədik ki, stuct tiplər proqramзı
tərəfindən yaradılan yeni tiplərdir və bu tiplərdən biz digər standart tiplərdən olduğu
dəyişənlər elan edə bilərik. C++ dilinin adı зəkiləndə yada dьşən ilk anlayış bizim yeni daxil
edəcəyimiz sinif anlayışıdır. Burada qeyri-adi, yeni heз bir şey yoxdur. Sadəcə olaraq
siniflərə strukt tiplərin biraz fərqli və inkişafetmiş nцvь kimi baxmaq olar. Belə ki, strukt tipinin
elementlərini tərtib edərkən biz standart tiplərdən və əvvəl yaratdığımız strukt tiplərdən
istifadə edirdik. Bu qayda siniflər ьзьn də keзərlidir. Lakin siniflərin strukt tiplərdən
fundamental ьstьnlьyь ondadır ki, biz siniflərin tərkibinə nəinki hər hansısa tipdən olan
dəyişən hətta funksiyaları da daxil edə bilərik. ( C dilində sinif təyin olunmur, amma strukt
daxilində funksiya elan etməyə imkan var) Siniflərdən istfadə etməklə tərtib olunmuş sadə
nьmunə proqram fikirlərimizə daha da aydınlıq gətirər.
Proqram nьmunəsi:
// prg_10_1.cpp
#include
// sade_sinif tipini elan edirik
class sade_sinif{
public:
int x;
int y;
int cem(void);
};
// sade_sinif -in cem funksiyasinin metn kodu
int sade_sinif::cem(void)
{ return x+y;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int main(){
//yeni tertib etdiyimiz sinif tipinden dey1 adli deyishen elan edirik
// sinif tipinden olan deyishen numunelerine "obyekt" deyilir.
sade_sinif dey1;
//dey1 obyektinin heddlerine qiymetler menimsedirik
dey1.x = 5;
dey1.y = 10;
//dey1 obyektinin cem funksiyasina muraciet edirik
std::cout<<"dey1 obyektinin x ve y heddlerinin cemi = "
<
return 0;
}
Proqramın izahı:
Gəlin yuxarıda daxil etdiyimiz proqramı analaiz edək, daha sonra siniflərlə bağlı digər
proqram nьmunələrinə baxarıq. Yeni sinif tipi yaradarkən class sцzьndən istfadə edirik. Daha
sonra isə yeni yaratmaq istədiyimiz sinif tipinin adını yazırıq.
Aşağıdakı kimi:
class sinif_adı
Sinifi adi d yiş nl ri adlandırdığımız kimi adlandıra bil rik. Daha ə ə ə ə sonra isə { mцtərəzəsini
yerləşdiririk. Nьmunə proqramda bu class sade_sinif{ sətrinə uyğun gəlir. { mцtərəzəsindən
sonra sinifi təşkil edən elementlər: dəyişənlər və funksiyalar yerləşdirilir. sinifin sonun
bildirmək ьзьn } mцtərəzəsindən və sintaksis tələbi olan ; -dən istifadə olunur.
Baxdığımız sinifdə biz int tipli x və y dəyişənləri, int tipli nəticə qaytaran cem funksiyası elan
etmişik.
class sade_sinif{
public:
int x;
int y;
int cem(void);
};
public ifadəsinin mənasını irəlidə daxil edəcəyik.
Beləliklə biz artıq sade_sinif adlı yeni class tipi elan etmişik. Yeni sinif tipi yaradarkən yerinə
yetirməli olduğumuz ikinci iş sinifi funksiya həddlərinin mətn kodunu tərtib etməkdir. Sinifin
funksiya həddlərinin mətn kodu adi funksiyaların mətn kodu kimi tərtib olunur, sadəcə
funksiyanın hansı sinifə məxsus olduğunu bildirmək ьзьn funksiyanın adının əvvəlinə
sinif_adI:: ifadəsi yazırıq.
Nьmunə proqramında bu int sade_sinif::cem(void){ sətrinə uyğun gəlir. Daha sonra isə adi
qaydada olduğu kimi funksiyanın mətn kodunu tərtib edirik. Bizim daxil etdiyimiz funksiyanın
mətn kodu bir sətirdən ibarətdir return x+y; .
x və y dəyişənləri cem funksiyasına nə parametr kimi цtьrьlьb, nə də onun daxilində dəyişən
kimi elan olunublar. Bəs cem funksiyası x və y dəyişənlərini necə tanıdı və onların
qiymətlərini haradan gцtьrdь?
Burada siniflərin aşağıdakı xassəsindən istifadə olunur:
Sinifin funksiya həddləri onun dəyişən həddlərinə birbaşa mьraciət edə bilər . cem funksiyası
daxilində istifadə olunan x və y dəyişənləri məhs sinifə məxsusdur. Sinifin elementlərini daxil
etdikdən və funksiya həddlərinin mətn kodunu tərtib etdikdən sonra biz artıq yeni
yaratdığımız sinif tipindən dəyişənlər elan edə bilərik, adi tilplərdən olduğu kimi.
Nьmunə proqramın main funksiyasında biz sade_sinif tipinidən dey1 adlı dəyişən elan edirik,
aşağıdakı kimi:
sade_sinif dey1;
Struct tipində olduğu kimi class tipində də həddlərə mьraciət etmək ьзьn nцqtə (.)
operatorundan istifadə olunur. Misal ьзьn kvadrat sinifinin tərəf həddinə mьraciət etmək
ьзьn kvadrat.tərəf yazırıq. Proqramda biz dey1 obyektinin x və y həddlərinə mьvafiq olaraq 5
və 10 qiymətləri mənimsətmişik, aşağıdakı kimi:
dey1.x = 5;
dey1.y = 10;
Daha sonra isə dey1 obyektinin cem funksiya həddinə mьraciət olunur hansı ki, цz
nцvbəsində dey1 obyektinin x və y həddlərinin cəmini nətcə olaraq qaytarır. Bu baxdığımız
sadə nьmunədə biz yeni sinif tipi elan etməyi, onun funksiya həddlərinin mətn kodunu tərtib
etməyi və eləcə də sinifin dəyişən və funksiya həddlərinə mьraciət etməni цrgəndik. Bu
siniflər barəsində bilməli olduğumuz zəruri anlayışlar idi. İndi isə siniflərlə bağlı digər
anlayışları və istifadə qaydalarını daxil edək.
10.1 aзıq və gizli həddlər
Sinif tipinin strukt tipindən digər fərqi də odur ki, sinif tipinin həddləri aзqı və gizli ola bilər.
Sinifin aзıq həddlərinə proqramın istənilən funsiyasından mьraciət etmək olar, gizli həddlərə
isə yalnız və yalnız sinifin цz funksiyaları mьraciət edə bilər. Sinifin hər-hansı həddini aзıq
elan etmək ьзьn public: ifadəsindən istifadə edirlər.
Bu zaman sinif daxilində public: ifadəsindən sonra yerləşdirilmiş həddlər aзıq olurlar. Sinifin
həddlərini gizli elan etmək ьзьn private: ifadəsindən istfadə olunur. Sinifin elanı daxilində aзqı
və gizli həddlərin hansı ardıcıllıqla yerləşdirilməsi ilə bağlı heз bir məhdudiyyət yoxdur. Gəlin
daxil etdiyimiz bu yeni anlayışlara aid proqram nьmunəsi ilə tanış olaq.
Proqram nьmunəsi
// prg_10_2.cpp
#include
// duzbucaqli tipini elan edirik
class duzbucaqli
{ public:
void terefler(int,int);
int sahe(void);
private:
int en;
int uzunluq;
};
// duzbucaqli -nin terefler funksiyasinin metn kodu
//klasin en ve uzunluq gizli heddlerini qiymetlendiririk
void duzbucaqli::terefler(int x,int y)
{ en =
x;
uzunluq = y;
}
// duzbucaqli -nin sahe funksiyasinin metn kodu
int duzbucaqli::sahe(void)
{ return en*uzunluq;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int main()
{
duzbucaqli duzb1;
//duz1 -in en ve uzunluguna qiymetler menimsedek
duzb1.terefler(5,8);
//duzb1 -in sahesini cap edek
std::cout<<"duzbucaqlinin sahesi = "<
return 0;
}
Nəticə:
C:\cpp\prog2\Debug>
C:\cpp\prog2\Debug>./prog2.exe
duzbucaqlinin sahesi = 40
C:\cpp\prog2\Debug>
C:\cpp\prog2\Debug>
10.2 Konstruktor və Destruktor
Yuxarıda baxdığımız sinif2.cpp proqramında biz duzbucaqli sinfindən duzb1 obyekti yaradırıq.
Daha sonra bu obyektin en və uzunlug -nu mənimsətmək ьзьn terefler funksiya həddini
зağırırıq.
Obyekt yцnьmlь proqramlaşdırmada bir зox hallarda obyektin həddlərinin qiymətlərini obyekt
yaradılarkən mənimsətmək tələb olunur. Bunun ьзьn kanstruktor adlandırılan funksiyadan
istifadə olunur, hansı ki, obyekt yaradılarkən avtomatik зağırılır. Obyekt yaradılarkən
deyəndə verilmiş sinif tipindən hər- hansı dəyişənin elan olunması nəzərdə tutulur. Misal
ьзьn yuxarıdakı nьmunə proqramda duzbucaqli duzb1; sətrində duzb1 obyekti yaradılır və əgər
biz duzbucaqli sinifi ьзьn kanstruktor təyin etsəydik onda o avtomatik зağrılardı.
10.3 Kanstruktorun təyin olunması
Hər hansı sinifin kanstruktorunu təyin etmək ьзьn bu sinif daxilində həmin sinifin adı ilə ьstьstə
dьşən funksiya təyin etmək lazımdır. Bu funksiyaya sinifin qurucusu - kanstruktoru
deyilir. Qurucu funksiyasının məqsədi sinifin həddlərinin ilkin qiymətlərini mənimsətməkdir.
Gəlin yuxarıda daxil etdiyimiz sinif2.cpp proqramının sinifdən istfadə etməklə variantını daxil
edək.
Proqram nьmunəsi
// prg_10_3.cpp
#include
// duzbucaqli tipini elan edirik
class duzbucaqli
{ public:
duzbucaqli();
void terefler(int,int);
int sahe(void);
private:
int en;
int uzunluq;
};
//qurucu - kanstruktor
duzbucaqli::duzbucaqli()
{ en =
10;
uzunluq = 15;
}
// duzbucaqli -nin terefler funksiyasinin metn kodu
//sinifin en ve uzunluq gizli heddlerini qiymetlendiririk
void duzbucaqli::terefler(int x,int y)
{ en =
x;
uzunluq = y;
}
// duzbucaqli -nin sahe funksiyasinin metn kodu
int duzbucaqli::sahe(void)
{ return en*uzunluq;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int main(){
duzbucaqli duzb1;
//qurucu avtomatik cagrilir ve heddlere qiymetler menimsedir
//bunu sahe funksiyasini cagirmaqla yoxlaya bilerik
std::cout<<"duzbucaqlinin sahesi = "<
//duzb1 -in tereflerine ayri qiymetler menimsedek
duzb1.terefler(5,8);
std::cout<<"duzbucaqlinin sahesi = "<
return 0;
}
Nəticə:
C:\cpp\prog2\Debug>
C:\cpp\prog2\Debug>./prog2.exe
duzbucaqlinin sahesi = 150
duzbucaqlinin sahesi = 40
C:\cpp\prog2\Debug>
C:\cpp\prog2\Debug>
10.4 Destruktorun təyin olunması
Destruktor funksiyası kanstruktorun əksinə olaraq obyekt yaddaşdan silindiyi zaman зağırılır.
Bu funksiya da sinifin adı ilə eyni adlandırılır, yalnız adın əvvəlinə ~ işarəsi artırılır.
Destruktorlar əsasən dinamik yaradılan obyektlər (ьnvan tipli sinif dıyişənləri) yaddaşdan
silinərkən avtomatik зağırlır, lakin əgər biz obyekti цzьmьz istədiyimiz vaxt məhv etmək
istəsək onda onun destruktorunu зağırırıq.
10.5 Obyektlərin dinamik yaradılması və silinməsi
Nцvbə зatdı ьnvan dəyişənləri barəsində цrgəndiyimiz biliklərin siniflərə tətbiqinə. $4 -də
qeyd eləmişdik ki, statik dəyişənlər elan olunan zaman onlara yaddaşda yer ayrılır və bu yeri
sonradan həmin dəyişəndən azad edib başqa məqsədlər ьзьn istifadə etmək mьmkьn deyil.
Bu səbəbdən də iri həcmli dəyişənlərdən istifadə olunan zaman adi dəyişənlərdən istifadə
etmək proqramın məhsuldarlığın aşağı salır, dinamik dəyişənlər isə əksinə. Yuxarıda
baxdığımız nьmunə proqramda biz duzbucaqli sinfindən adi dəyişən elan etmişdik.
Gəlin indi həmin proqramı unvan tipli dəyişəndən (dinamik) istifadə edilən halına baxaq.
Proqrama baxmazdan цncə onu da qeyd edək ki, (bax $8.1) dinamik obyektin funksiya və
dəyişən həddlərinə mьraciət etmək ьзьn . yox -> operatorundan istifadə olunur.
Proqram nьmunəsi
// prg_10_4.cpp
#include
// duzbucaqli tipini elan edirik
class duzbucaqli
{ public:
duzbucaqli();
void terefler(int,int);
int sahe(void);
private:
int en;
int uzunluq;
};
//kanstruktor
duzbucaqli::duzbucaqli()
{ en =
10;
uzunluq = 15;
} // duzbucaqli -
nin terefler funksiyasinin metn kodu
//klasin en ve uzunluq gizli heddlerini qiymetlendiririk
void duzbucaqli::terefler(int x,int y)
{ en =
x;
uzunluq = y;
} // duzbucaqli -
nin sahe funksiyasinin metn kodu
int duzbucaqli::sahe(void)
{ return en*uzunluq;
} //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int main()
{
duzbucaqli *duzb1;
//heleki yaddashda duzb1 ucun hec bir yer ayrilmiyib
//duzb1 -i yaradaq
duzb1 = new duzbucaqli;
//kanstruktor avtomatik cagrilir
std::cout<<"duzbucaqlinin sahesi = "<sahe()<<"\n";
//duzb1 -in tereflerine ayri qiymetler menimsedek
duzb1->terefler(5,8);
std::cout<<"duzbucaqlinin sahesi = "<sahe()<<"\n";
return 0;
}
Nəticə:
C:\cpp\prog2\Debug>
C:\cpp\prog2\Debug>./prog2.exe
duzbucaqlinin sahesi = 150
duzbucaqlinin sahesi = 40
C:\cpp\prog2\Debug>
C:\cpp\prog2\Debug>
$11 Makroslar və başlıq fayllar.
Biz indiyə kimi proqramlarada
#include, #include
kimi sətirlərdən istifadə etdik və qeyd etdik ki proqramın mətninə bu sətirlərin əlavə olunması
bizə std::cout, std::cin, new , delete, strcpy ... kimi funksiyalardan istifadə etməyə imkan verir.
Hər-hansı bir funksiyadan proqramda istifadə edə bilmək ьзьn proqrama bu funksiyanın elanı
(adı və parametrlərinin qeyd edildiyi sətir) və mətni (funksiyanın kod hissəsi) verilməlidir. Biz
цz funksiyalarımızı tərtib edərkən həm elanı, həm də mətni eyni faylda yerləşdirirdik.
Kompilyator imkan veriri ki, biz ayrı-ayrı fayllarda elan olunmuş funksiya və dəyişənlərə цz
proqramımızdan mьraciət edə bilək.
Bunun ьзьn #include direktivindən istifadə edirlər.
#include və ya #include"fayl.h" kimi.
Bir qayda olaraq proqrama #include vastəsilə əlavə olunan faylların sonu .h ilə bitir. Sadə
proqram nьmunəsinə baxmağımız kifayətdir. İndiyə kimi baxdığımız nьmunələrdə bьtьn
proqram kodunu bir fayla yerləşdirirdik.
İndi isə bizə iki və daha зox fayl lazım olacaq:
Dəyişənlərin, funksiyaların elan olunduğu başlıq fayllar və bu dəyişən və funksiyalara
mьraciət edən proqram kodu faylları.
Proqram 1.
menim_faylim.h faylının mətni
// prg_11_1.cpp
/*bashliq fayli menim_faylim.h */
#ifndef MENIM_FAYLIM_H
#define MENIM_FAYLIM_H
int yeni_deyishen;
#endif
proqram kodu prog2.cpp faylının mətni
#include
#include "menim_faylim.h"
int main()
{
yeni_deyishen = 5;
std::cout<<" yeni deyishen "
<
}
Proqramı yerinə yetirək.
C:\cpp\prog2\Debug>
C:\cpp\prog2\Debug>prog2.exe
yeni deyishen 5
C:\cpp\prog2\Debug>
C:\cpp\prog2\Debug>
menim_faylim.h faylındakı
#ifndef
#define
#endif
makrosları menim_faylim.h faylının bizim proqramam sonsuz lav olunmasının ə ə qarşısını alır.
menim_faylim.h başlıq faylında biz int tipli yeni_deyishen dəyişəni elan edirik. Daha sonra
prog2.cpp faylında yeni_deyishen dəyişəninə mьraciət edirik.
Əgər diqqət yetirdinizsə biz iostream faylını < və > vastəsilə, menim_faylim.h faylını isə " və "
simvolları vastəsilə proqrama əlavə etdik. Bu kompilyatora menim_faylim.h başlıq faylının
standart deyil,bizim tərəfimizdən yaradıldığını bildirir və kompilyator bu faylı bizim proqram
yerləşən qovluqda axtarır.
MAKROSLAR
C++ dilində istifadə olunan digər əhəmiyyətli vasitələrdən biri də makroslardır. Makroslar 2
cьr olur: şərt makrosları və təyin makrosları.
Təyin makrosalrı
Təyin makrosalrı #define direktivindən istifadə olunaraq yaradılır. Təyin makrosları hər hansı
bir ifadənin başqa ifadə ilə əvəz edilməsinə xidmət edir. Misal ьзьn əgər biz proqramın hərhansı
yerində #define MAX_QIYMET 1024 sətrini yerləşdiririksə onda kompilyator proqramda
MAX_QIYMET ifadəsinə rast gəldiyi bьtьn yerlərdə onu 1024 ilə əvəz edəcək.
Sadə proqrama baxaq:
Dostları ilə paylaş: |