1. Borland C++ Builder 6 ning strukturalashgan toifalari.
2. Massivlar. Bir va ko’p o’lchovli massivlar, konsol rejimida massivlarni ishlatgan holda dastur tuzish.
3. Dinamik massivlar bilan ishlash.
4. C++ da funktsiya va protseduralar. funktsiya va protseduralar.
5. C++ da protseduralar yordamida dasturlash xususiyatlari.
6. Malumotlarning faylli toifasi, ularning turlari, ularga murojaat qilish.
7. Matnli fayllar bilan ishlash.
8. Fayllar ustida turli amallar.
Strukturali tiplar, struct goods { char* name; long price; float percent; int vol, goods food, percon; goods *point_to; struct complex. massivlar. bir va ko’p o’lchovli massivlar, dinamik massivlar, []; malloc() ; calloc().aralasha toifa, yozuv, yozuv elementlari, birlashtirish operatorlari. getc( ), double atof() (const char* ptr); ptr. to’plam, to’plam toifasi, rekursiv funksiyalar. funktsiya, protseduralar, oddiy rekursiya, vositali rekursiya, malumotlarning faylli toifasi, FILE * fopen V"g", "a", "w+", "r+", "a+",SEEK SET, SEEK_CIJR, SEEKEND
1. Borland C++ Builder 6 ning strukturalashgan toifalari.
Strukturali tiplar va strukturalar. Strukturali tip. Struktura bu turli tipdagi ma’lumotlarning birlashtirilgan tipdir. Struktura har xil tipdagi elementlar-komponentalardan iborat bo’ladi.. Strukturalar quyidagicha ta’riflanishi mumkin:
Struct struturali_tip_nomi {Elementlar_ta’riflari} Misol uchun ombordagi mollarni tasvirlovchi strukturani ko’ramiz. Bu struktura quyidagi komponentalarga ega bo’lishi mumkin:
- Mol nomi (char*)
- Sotib olish narxi (long)
- Ustiga qo’yilgan narx, foizda (float)
- Mol soni (int)
- Mol kelib tushgan sana (char[9])
Bu struktura dasturda quyidagicha ta’riflanadi: struct goods { char* name; long price; float percent; int vol; char date[9]; } Konkret strukturalar va strukturaga ko’rsatkichlar bu tip yordamida quyidagicha ta’riflanishi mumkin: goods food, percon; goods *point_to;
Misol uchun: struct complex { double real; double imag; } Bu misolda kompleks sonni tasvirlovchi strukturali tip complex kiritilgan bo’lib, kompleks son haqiqiy qismini tasvirlovchi real va mavxum qismini tasvirlovchi imag komponentalaridan iboratdir. Konkret strukturalar bu holda quyidagicha tasvirlanadi: Complex sigma,alfa; Quyidagi misolda kasr sonni tasvirlovchi numerator –sur’at va denominator-maxraj komponentalaridan iborat struktura ta’rifi keltirilgan. struct fraction; { int numerator; int denominator; } Bu holda konkret strukturalar quyidagicha tasvirlanishi mumkin: fraction beta; Konkret strukturalarni tasvirlash. Strukturalar ta’riflanganda konkret strukturalar ro’yxatini kiritish mumkin: Struct struturali_tip_nomi {Elementlar_ta’riflari} Konkret_strukturalar_ro’yxati. Misol: Struct student { char name[15];
char surname[20]; int year; } student_1, student_2, student_3; Bu holda student strukturali tip bilan birga uchta konkret struktura kiritiladi. Bu strukturalar student ismi (name[15]), familiyasi (surname[20]), tugilgan yilidan (year) iborat. Strukturali tip ta’riflanganda tip nomi ko’rsatilmay, konkret strukturalar ro’yxati ko’rsatilishi mumkin:
Struct {Elementlar_ta’riflari} Konkret_strukturalar_ro’yxati. Quyidagi ta’rif yerdamida uchta konkret struktura kiritiladi, lekin strukturali tip kiritilmaydi. struct { char processor [10]; int frequency; int memory; int disk; } IBM_486, IBM_386, Compaq; Strukturalar uchun xotiradan joy ajratish. Strukturali tip kiritilishi bu tip uchun xotiradan joy ajratilishiga olib kelmaydi. Har bir konkret struktura (ob’ekt) ta’riflanganda, shu ob’ekt uchun elementlar tiplariga qarab xotiradan joy ajratiladi. Xotiradan joy zich ajratilganda struktura uchun ajratilgan joy hajmi har bir element uchun zarur bo’lgan xotira hajmlari yigindisiga teng bo’ladi. SHu bilan birga xotiradan joy zich ajratilmasligi ham mumkin ya’ni elementlar orasida bo’sh joylar ham kolishi mumkin. Bu bo’sh joy keyingi elementni xotira qismlarining qabul qilingan chegaralari bo’yicha tekislash uchun koldiriladi. Misol uchun butun tipdagi elementlar juft adreslardan boshlansa, bu elementlarga murojaat tezroq amalga oshiriladi. Konkret strukturalarni joylashuviga ba’zi kompilyatorlarda #pragma preprotsessor direktivasi yordamida ta’sir o’tkazish mumkin. Bu direktivadan quyidagi shaklda: Pragma pack(n) Bu yerda n qiymati 1,2 yoki 4 ga teng bolishi mumkin. Pack(1) – elementlarni bayt chegaralari bo’yicha tekislash; Pack(2) – elementlarni so’zlar chegaralariga qarab tekislash; Pack(4) – elementlarni ikkilangan muzlar chegaralariga qarab tekislash. Struktura uchun ajratilgan joy hajmini quyidagi amallar yordamida aniqlash mumkin: Sizeof (strukturali_tip_nomi); Sizeof (struktura_nomi); Sizeof struktura_nomi. Oxirgi holda struktura nomi ifoda deb qaraladi. Ifodaning tipi aniqlanib, hajmi xisoblanadi.
Misol uchun: Sizeof (struct goods) Sizeof (tea) Sizeof coat Strukturalarga murojaat. Konkret strukturalar ta’riflanganda massivlar kabi initsializatsiya qilinishi mumkin. Masalan complex sigma ={1.3;12.6}; goods coats={“pidjak‟,40000,7.5,220,”12.01.97”); Bir xil tipdagi strukturalarga kiymat berish amalini qo’llash mumkin: Complex alfa; alfa=sigma; Lekin strukturalar uchun solishtirish amallari aniqlanmagan. Strukturalar elementlariga quyidagicha murojaat qilish mumkin: Struktura nomi.element_nomi. „Nuqta amali‟ struktura elementiga murojaat qilish amali deyiladi. Bu amal qavs amallari bilan birga eng yuqori ustivorlikka egadir. Misol: Complex alfa={1.2,-4.5},betta={5.6,-7.8),sigma; Sigma.real=alfa.real+betta.real; Sigma.imag=alfa.imag+betta.imag; Konkret strukturalar elementlari dasturda alohida kiritilishi va chiqarilishi zarurdir. Quyidagi misolda ikki kompleks son kiymatlari kiritilib, yigindisi xosil qilinadi: #include
typedef struct { double real; double imag; } complex; void main() { complex x,y,z; Cout<<’\n’; Cin>>x.real; Cout<<’\n’;Cin>>x.imag; Cout<<’\n’;Cin>>y.real; Cout<<’\n’;Cin>>y.imag; z.real=x.real+y.real; z.imag=x.imag+y.imag; Cout<<’\
C++ dasturlash tizimida massivlardan foydalangan holda dasturlash.
Kompyuter xotirasida ketma-ket (regulyar) joylashgan bir xil turdagi qiymatlarga massiv deyiladi. Katta hajmdagi cheklangan va tartiblangan qiymatlarni qayta ishlash bilan bog‘liq masalalarni yechishda massivlardan foydalanishga zarurat tug’iladi. Massivlarni matematikadagi sonlar vektoriga o’xshatish mumkin, chunki vektor ham o‘zining individual nomiga ega va u chekli miqdordagi bir turdagi qiymatlardan, ya’ni sonlardan iborat. Demak, massiv – bu chekli miqdordagi bir turdagi qiymatlar (massiv elementlari)ning tartiblangan majmuasidir. Ya’ni massivdagi barcha elementlar bir xil turga tegishli bo‘lishi lozim.
Bunday tur massiv elementining turi yoki massiv uchun tayanch tur deb ataladi. Dasturda ishlatiladigan har bir massiv o‘zining individual nomiga ega bo‘lishi kerak. Bu nom massiv o‘zgaruvchisi deyiladi. Massivning har bir elementi massiv nomi, hamda kvadrat qavsga olingan va element selektori deb nomlanuvchi indeksni ko‘rsatish orqali oshkor ravishda belgilanadi. Unga murojaat sintaksisi quyidagicha: []; Bu ko‘rinishga xususiy o‘zgaruvchi deyiladi, chunki uning qiymati massivning alohida elementidir. Umuman olganda indeks sifatida ifoda ishlatilishi mumkin. Ifoda qiymati massiv elementi nomerini aniqlaydi. Ifoda sifatida o‘zgaruvchi ham olinishi mumkin, bunda o‘zgaruvchining qiymati o‘zgarishi bilan murojaat qilinayotgan massiv elementini aniqlovchi indeks ham o‘zgaradi. Shunday qilib, dasturdagi bitta indeksli o‘zgaruvchi orqali massivning barcha elementlarini aniqlash mumkin. Haqiqiy turdagi (float, double) qiymatlar to‘plami cheksiz bo‘lganligi sababli ular massiv indeksi sifatida ishlatilmaydi. Bu bo’limda bir o’lchovli statik va dinamik massivlar bilan tanishamiz. C++ tilida massiv indeksi doimo 0(nol) dan boshlanadi, uning eng katta qiymati massiv e’lonidagi uzunlikdan bittaga kam bo‘ladi. Massiv quyidagicha e’lon qilinadi: [] ={}; Bu yerda - butun son ko’rinishidagi o‘zgarmas ifoda. Bir o’lchovli massivlarni e’lon qilishga doir misollar: int a[5]={4,-5,2,10,3}; float n[4]; Massiv statik yoki dinamik turda bo‘lishi mumkin. Statik massivning uzunligi oldindan ma’lum bo‘ladi va uning elementlari xotirada aniq bir adresdan boshlab ketma-ket joylashadi. Dinamik massivning uzunligi dastur bajarilishi jarayonida aniqlanadi va uning elementlari dinamik xotirada ayni paytda bo‘sh bo‘lgan adreslarga joylashadi. Masalan, int a[5]; ko‘rinishida e’lon qilingan bir o‘lchovli massiv elementlari xotirada quyidagicha joylashadi:

Massivning i-elementiga a[i] yoki *(a+i) – vositali murojaat qilish mumkin. Massiv uzunligi sizeof(a) amali orqali aniqlanadi. Massiv e’lonida uning elementlariga boshlang‘ich qiymatlar berish (initsializatsiyalash) mumkin va uning bir nechta variantlari mavjud. 1) O’lchami ko‘rsatilgan massiv elementlarini to‘liq initsializatsiyalash: int b[5]={8,5,-11,41,39}; Bunda 5 ta elementdan iborat bo‘lgan b nomli bir o‘lchovli massiv e’lon qilingan va uning barcha elementlariga boshlang‘ich qiymatlar berilgan. Bu e’lon quyidagi e’lon bilan ekvivalent: int b[5]; b[0]=8; b[1]=5; b[2]=-11; b[3]=41; b[4]=39; 2) O‘lchami ko‘rsatilgan massiv elementlarini to‘liqmas initsializatsiyalash: int b[5]={-11,5,29}; Bu yerda faqat massiv boshidagi uchta elementga boshlang‘ich qiymatlar berilgan. Shuni aytib o‘tish kerakki, massivni initsializatsiyalashda uning boshidagi ementlariga boshlang’ich qiymatlar bermasdan turib, oxiridagi elementlariga boshlang‘ich qiymatlar berish mumkin emas. Agarda massiv elementlariga boshlang‘ich qiymat berilmasa, unda kelishuv bo‘yicha static va
extern modifikatori bilan e’lon qilingan massiv uchun elementlarning boshlang’ich qiymati 0(nol) soniga teng bo’ladi. Automatik massiv elementlarining boshlang‘ich qiymatlari esa noma’lum hisoblanadi. 3) O‘lchami ko‘rsatilmagan massiv elementlarini to‘liq initsializatsiyalash: int d[]={-15,7,15,24}; Bu misolda massivning barcha elementlariga qiymatlar berilgan hisoblanadi, massiv uzunligi esa kompilyator tomonidan boshlang‘ich qiymatlar soniga qarab aniqlanadi. Shuni ta’kidlash kerakki, massivning uzunligi berilmasa, unga boshlang’ich qiymatlar berilishi shart. Bir o’lchovli statik massivlarni e’lon qilish: char s[5]={’d’,‘a’,‘b’,’c’,’e’}; //belgilar massivi int n[5] ={1,26,34,14}; // butun sonlar massivi char str[]=”defa”; /*satr uzunligi 5 ga teng, chunki, uning oxiriga ‘\0’ belgisi qo‘shiladi.*/ char str[]={‘d’,‘e’,‘f’,’a’}; /*yuqoridagi satrning boshqacha yozilishi.*/ Statik massivlarning kamchiliklari shundaki, ularning o‘lchami oldindan ma’lum bo‘lishi kerak, bundan tashqari bu o‘lcham berilganlarga ajratilgan xotira segmentining o‘lchami bilan chegaralangan. Ikkinchi tomondan, yetarlicha katta o‘lchamdagi massiv e’lon qilib, masala yechilishida ajratilgan xotira to‘liq ishlatilmasligi mumkin. Bu kamchiliklar dinamik massivlardan foydalanish orqali bartaraf etiladi, chunki ular dastur ishlashi jarayonida kerakli o‘lchamdagi massivlarni yaratish va ularga zarurat qolmaganda yo‘qotish imkoniyatini beradi. Dinamik massivlarga xotiradan joy ajratish uchun malloc(), calloc() funksiyalaridan yoki new operatoridan foydalaniladi. Dinamik massivga ajratilgan xotirani bo‘shatish uchun free() funksiyasi yoki delete operatori ishlatiladi. Yuqorida qayd qilingan funksiyalar alloc.h kutubxonasida joylashgan. malloc() funksiyasining sintaksisi void * malloc(size_t ulcham) ; ko‘rinishida bo‘lib, u xotiraning uyum qismidan ‘ulcham’ bayt o‘lchamidagi uzluksiz sohani ajratadi. Agar xotira ajratish muvaffaqiyatli bo‘lsa, malloc() funksiyasi shu soha boshlanishining adresini qaytaradi. Talab qilingan xotirani ajratish muvaffaqiyatsiz bo‘lsa, funksiya NULL qiymatini qaytaradi. Sintaksisdan ko‘rinib turibdiki, funksiya void turidagi qiymat qaytaradi. Amalda esa aniq bir turdagi massiv ob’ekti uchun xotiradan joy ajratish zarur bo‘ladi. Shu bois void turini aniq bir turga keltirish texnologiyasidan foydalaniladi. Masalan, butun turdagi uzunligi 3 ga teng massivga joy ajratishni quyidagicha amalga oshirish mumkin: int * d_mas=(int*)malloc(3*sizeof(int)); malloc() funksiyasidan farqli ravishda calloc() funksiyasi massiv uchun joy ajratishdan tashqari massiv elementlarini 0(nol) qiymati bilan initsializatsiyalaydi. Bu funksiya sintaksisi quyidagi: void * calloc (size_t miqdor, size_t ulcham) ; ko’rinishda bo‘lib, ‘miqdor’ parametri ajratilgan sohada nechta element borligini, ‘ulcham’ esa element o‘lchamini bildiradi. free() dinamik xotirani bo‘shatish funksiyasi bo’lib, ko’rsatilgan dinamik massiv egallab turgan xotira qismini bo’shatadi: void free (void * blok); free() funksiyasi parametrining void turida bo‘lishi, ixtiyoriy turdagi xotira bo‘lagini o‘chirish imkonini beradi. Quyidagi dasturda 10 ta elementga ega dinamik massivni yaratish, unga dastlabki 10 ta toq sonni qiymatlash va massiv elementlari qiymatini chop etish hamda shu massivni xotiradan o‘chirish jarayonlari amalga oshirilgan. #include #include int main() {
int * d_mas; if ((d_mas=(int*)malloc(10*sizeof(int)))==NULL) { cout<<”Xotira yetarli emas!!!”; return 1; } // ajratilgan xotira sohasini to‘ldirish for(int i=0; i<10; i++) * (d_mas+i)=2*i+1; // dinamik massiv elementlarini chop etish for(int i=0; i<10; i++) cout<<*(d_mas+i)<<”end1”; // ajratilgan xotira qismini bo’shatish free (d_mas); return 0; } Endi new va delete operatorlari bilan tanishamiz. new operatori yordamida massivga xotiradan joy ajratish uchun massiv turidan keyin kvadrat qavs ichida massiv elementlari soni ko‘rsatiladi. Masalan, butun turdagi 10 ta sondan iborat massivga joy ajratish quyidagi d_mas=new int[10]; ko’rinishda bo’ladi. Bu usulda massivga ajratilgan xotirani bo‘shatish uchun delete [] d_mas; buyrug’ini berish kerak bo‘ladi. Massivlar bilan ishlashda quyidagilarni hisobga olish zarur: - massiv elementlariga qiymat kiritish siklllar yordamida amalga oshirilishi maqsadga muvofiq; - statik massivlar bilan ishlashda kiritiladigan ma'lumotlar soni, massiv elementlari sonidan oshmasligi kerak; - massiv elementlaridagi barcha ma'lumotlarni chiqarish uchun ham siklllardan foydalanish maqsadga muvofiq; Quyida keltiriladigan masalada bu tasdiqlar o'z aksini topgan. Shuni alohida ta'kidlash lozimki, for takrorlanish operatorini algoritmda tasvirlash uchun qo'llanmada ikki xil shakldan foydalanilgan, chunki C++ tilida for operatori murakkab konstruksiyali bo'lib, uning parametrlariga tur nuqtai-nazaridan cheklovlar qoýilmaydi. Qo'llanmaning 3-bobida takrorlanish operatorini tasvirlash uchun «romb» shaklidan foydalanilgan. Quyida keltirilgan masalaning algoritmida esa takrorlanish operatorini tasvirlash uchun «oltiburchak» shaklidan foydalanilgan. Chunki bu masalada barcha takrorlanish qadamlari 1 ga teng.
Yuqoridagilardan xulosa qiladigan bo'lsak, takrorlanishlar qadami 1 ga teng bo'lgan hol uchun algoritmlarni tasvirlashda «oltiburchak» shaklidan, qolgan hollarda esa «romb» shaklidan foydalanish maqsadga muvofiq bo'ladi.
C++ tilida massiv elementlarining turiga cheklovlar qo‘yilmaydi, lekin bu turlar chekli o‘lchamdagi ob'ektlarning turi bo‘lishi kerak. Chunki kompilyator massivning xotiradan qancha joy (bayt) egallashini bilishi zarur. Xususan, massiv komponentasi massiv bo‘lishi ham mumkin, ya’ni «vektorlar-vektori» natijada matritsa deb nomlanuvchi ikki o‘lchovli massivni hosil qiladi. Agar matritsaning elementi ham vektor bo‘lsa, uch o‘lchamli massiv hosil bo‘ladi. Shu yo‘l bilan ixtiyoriy o‘lchamdagi massivni hosil qilish mumkin. Ikki o‘lchovli statik massivning sintaksisi quyidagi ko‘rinishda bo‘ladi: [][]; Masalan, 5x15 o‘lchamli haqiqiy sonlar qabul qiluvchi statik massivning e’loni quyidagicha bo’ladi: float s_mas[5][15]; E’lon qilingan s_mas massiv o’zgaruvchisi 5 ta satr va 15 ta ustundan tashkil topgan matritsaga o’xshaydi, ya’ni uning 75 ta elementi mavjud.
Endi adres nuqtai–nazaridan ko‘p o‘lchovli massiv elementlariga murojaat qilishni
ko‘raylik. Quyidagi e’lonlar berilgan bo‘lsin:
int a[4][5];
float b[3][2][4];
Birinchi e’londa ikki o‘lchovli massiv, ya’ni 4 ta satr va 5 ta ustundan iborat matritsaga
o’xshash massiv e’lon qilingan, ikkinchisida esa uch o‘lchovli, ya’ni 3 ta satr, 2 ta ustun va 4 ta
qavatdan iborat massiv e’lon qilingan.
Massiv elementlariga murojaat qilish uchun massiv nomidan keyin kvadrat qavsda har bir
o‘lcham uchun indeks yozilishi kerak, masalan, a[i][j] ko’rinishidagi asosiy murojaatdan tashqari,
vositali murojaat qilish *(*(a+i)+j) yoki *(a[i]+j) va b[i][j][k] ko’rinishidagi asosiy murojaatdan
tashqari, vositali murojaat qilish *(*(*(b+i)+j)+k) yoki *(*(b[i]+j)+k) yoki *(b[i][j]+k) ham
mumkin.
Ko‘p o‘lchovli massivlarni initsializatsiyalash quyidagi misollar yordamida ko’rsatiladi:
int s_mas[3][4]={0,4,1,-5,2,-22,15,-46,18,98,12,-3};
int b[4][3]={{5,1,24},{1,34,-12},{76,-2,7},{7,-25,7}};
Birinchi e’londa boshlang‘ich qiymatlar ketma-ket yozilgan, ikkinchi e’londa esa qiymatlar
guruhlashgan.
Endi ikki o‘lchovli dinamik massivlar tashkil qilishni qarab chiqamiz. Bunday massivlarni
tashkil etishning sintaksisi quyidagi:
**;
ko’rinishda bo’lgan «ko‘rsatkichga ko‘rsatkich» ishlatiladi.
Dastlab massiv satrlari soniga qarab ko‘rsatkichlar massiviga dinamik xotiradan joy
ajratiladi:
d_mas=new int *[n]; // bu yerda n massiv satrlari soni
Keyin, dinamik massivning har bir satri uchun takrorlash operatoridan foydalanib xotiradan
joy ajratish va ularning boshlang‘ich adreslarini d_mas massiv elementlariga joylashtirish zarur
bo‘ladi:
for(int i=0;iShuni ta’kidlash kerakki, dinamik massivning har bir satri xotiraning turli joylarida
joylashishi mumkin.
Ikki o‘lchovli dinamik massivni o‘chirish uchun esa oldin massivning har bir elementi
(satri), so‘ngra massivning o‘zi o’chiriladi:
for (i=0;i Masala. O’lchamlari n×m bo’lgan (n>0,m>0) ikkita A va B matritsalar berilgan, ulardan
foydalanib C matritsa tuzilsin: )
,
,
,
max(
, i j
B
i j
A
i j
С = (C matritsaning har bir elementi A va B
matritsalardagi mos elementlarning kattasi hisoblanadi).
Qo’yilgan masala uchun algoritm va dastur tuzilsin.
Dasturlash tillarida funksiya – masala yechishdagi kalit elementlardan biridir. Dasturda ishlatiladigan har qanday funksiya e’lon qilinishi kerak. Odatda funksiyalar e’loni sarlavha fayllarda e’lon qilinadi va #include direktivasi yordamida dastur matniga qo‘shiladi. Funksiya e’lonini funksiya prototipi tavsiflaydi. Funksiya prototipi quyidagi ko‘rinishda bo‘ladi: (); bu yerda −funksiya ishlashi natijasida qaytariladigan qiymatning turidir. Agar qaytariladigan qiymat turi ko‘rsatilmagan bo‘lsa, kelishuv bo‘yicha funksiya qaytaradigan qiymat turi int deb hisoblanadi, −vergul bilan ajratilgan funksiya parametrlarining turi va nomlari ro‘yxati. Parametr nomini yozmasa ham bo‘ladi. Ro‘yxat bo‘sh bo‘lishi ham mumkin. Funksiya prototiplariga misollar: int almashtir(int,int); double minimum(double a, double b);
Boshl.Boshl. Boshl.
n,m n,m
TamomTamom
yo’q yo’q yo’q
yo’q yo’q yo’q
i:=0..n i:=0..n i:=0..ni:=0..n-1
ha
yo’q yo’q yo’q
j:= 0.. m-1
ha
yo’q yo’q yo’q
ha
ha
yo’q yo’q yo’q
j:=0..:=0.. :=0..m-1
i:=0..n i:=0..n i:=0..ni:=0..n-1
ha
199
void fakt();
void bosmalash(void);
Agar dastur matnida funksiya aniqlanishi, uni chaqiradigan funksiyalar matnidan oldin
yozilgan bo‘lsa, bunday funksiya prototipi tushirib qoldirilishi ham mumkin. Ammo bu holat yaxshi
usul hisoblanmaydi, ayniqsa o‘zaro bir-biriga murojaat qiluvchi funksiyalarni e’lon qilishda
muammolar yuzaga keladi.
Funksiya matni−funksiya sarlavhasi va figurali qavsga (‘{‘,’}’) olingan, amaliy mazmunga
ega tanadan iborat bo‘ladi. Agar funksiyaning turi void turidan farqli bo‘lsa, uning tanasida albatta
mos turdagi parametrga ega return operatori bo‘lishi shart. Funksiya tanasida bittadan ortiq return
operatori bo‘lishi ham mumkin. Ularning ixtiyoriy birortasi bajarilganda funksiyadan chiqib ketish
amalga oshadi. Agar funksiyaning qiymati dasturda ishlatilmaydigan bo‘lsa, funksiyadan chiqish
uchun parametrsiz return operatori ishlatiladi yoki umuman return ishlatilmasligi ham mumkin.
Oxirgi holatda funksiyadan chiqish, funksiyani yakunlovchi figurali qavsga yetib kelinganda
amalga oshadi.
Funksiya dasturning biror modulida faqat bir marta aniqlanishi kerak, uning e’loni esa
funksiyani ishlatadigan modullarda bir necha marta yozilishi mumkin. Funksiya aniqlanishida
sarlavhadagi barcha parametrlar nomlari yozilishi shart.
Funksiya dasturga ma’lum bir ishni amalga oshirish uchun chaqiriladi. Funksiyaga murojaat
qilinganda, u o’ziga yuklangan masalani yechadi va o’z ishini tugatib, kutilgan qiymatni natija
sifatida qaytaradi.
Funksiyani chaqirish uchun uning nomi va undan keyin qavs ichida argumentlar ro‘yxati
beriladi:
(,,...,);
bu yerda har bir , funksiya tanasiga uzatiladigan va keyinchalik hisoblash jarayonida
ishlatiladigan o‘zgaruvchi, ifoda yoki o’zgarmasdir. Argumentlar ro‘yxati bo‘sh bo‘lishi ham
mumkin.
Funksiyalar o‘z tanasida boshqa funksiyalarni, hatto o‘zini ham chaqira oladi. O‘z tanasida
o‘zini chaqiradigan funksiyalarga rekursiv funksiyalar deyiladi.
Funksiya prototipida yoki aniqlanish sarlavhasida ko‘rsatilgan parametrlar formal
parametrlar deyiladi, funksiya chaqirilishida ko’rsatilgan argumentlarga faktik parametrlar
deyiladi.
C++ tilidagi har bir dasturda albatta main()−bosh funksiya bo‘lishi shart. Aynan shu
funksiya yuklagich tomonidan chaqirilishi bilanoq dasturning bajarilishi boshlanadi.
Aksariyat hollarda main() funksiyasining parametrlar ro‘yxati bo‘sh bo‘ladi. Agar dastur
ishga tushirilayotganda, uning buyruq satrida ma’lum bir parametrlarni uzatish zarur bo‘lsa, main()
funksiyasining sintaksisi o‘zgaradi:
int main(int argc, char* argv[]);
Bu yerda argc – uzatiladigan parametrlar soni, argv[]- bir-biridan punktuatsiya belgilari
(yoki probel) bilan ajratilgan parametrlar ro‘yxatini o‘z ichiga olgan massivga ko‘rsatkich.
Quyida dasturchi tomonidan tuzilishi mumkin bo’lgan bir qator funksiyalar va ularning
tuzilishi bilan tanishamiz.
Funksiyalarning dasturda tasvirlanishini namoyish etish maqsadida son kvadratini hisoblash
masalasi uchun dasturchi funksiyasini tuzamiz.
Buning uchun funksiya prototipini funksiya.h sarlavha fayliga joylashtiramiz:
long son_kv(int);
Asosiy dasturga ushbu sarlavha faylini qo‘shish orqali son_kv() funksiya e’loni dastur
matniga kiritiladi:
#include
#include “funksiya.h”
int main()
{
int butun_o’zgaruvchi=6;
cout<return 0; } long son_kv(int x) { return x*x; } Xuddi shu masalani sarlavha faylidan foydalanmagan holda, funksiya e’lonini dastur matniga yozish orqali ham hal etish mumkin: #include long son_kv(int); int main() { int butun_o’zgaruvchi=6; cout< sarlavha faylida joylashgan. #include #include void chop_etish (double son, double aniqlik=1, bool b=true); int main() { double pi1=-3.141592654; chop_etish(pi1,4,false); chop_etish(pi1,2); chop_etish(pi1); return 0; } void chop_etish(double son, double aniqlik=1, bool b=true) { if(!b) son=fabs(son);
son=(int)(son*pow(10,aniqlik)); son=son/pow(10,aniqlik); cout< int max(int, int); char max(char,char); float max (float,float); int max (int,int,int); void main() { int a,b,k; char c,d; float x,y; cin>>a>>b>>k>>c>>d>>x>>y; cout<j) ?i:j;} char max(char s1, char s2) {return (s1>s2) ?s1:s2;} float max (float x,float y) {return (x>y)?x:y;} int max (int i, int j, int k) {return (i>j) ?(i>k?i:k;) (j>k)?j:k);}
Agar funksiya chaqirilishida argument turi uning prototipidagi xuddi shu o‘rindagi parametr turiga mos kelmasa, kompilyator uni parametr turiga keltirilishga harakat qiladi. Masalan, bool va char turlarini int turiga, float turini double turiga va int turini double turiga o‘tkazishga. Qayta yuklanuvchi funksiyalardan foydalanishda quyidagi qoidalarga rioya qilish kerak: -qayta yuklanuvchi funksiyalar bitta ko‘rinish sohasida bo‘lishi kerak; -qayta yuklanuvchi funksiyalarda kelishuv bo‘yicha parametrlar ishlatilsa, bunday parametrlar barcha qayta yuklanuvchi funksiyalarda ham ishlatilishi va ular bir xil qiymatga ega bo‘lishi shart; -agar funksiyalar parametrlarining turi faqat “const” va ‘&’ belgilari bilan farq qiladigan bo‘lsa, bu funksiyalar qayta yuklanmaydi. Ko’pgina masalalarni yechishda funksiyaning formal parametrlaridan qiymat qaytaruvchi sifatida foydalanishga to’g’ri keladi, ya’ni funksiyaning formal parametri bir vaqtning o’zida qiymat qabul qiluvchi va qaytaruvchi bo’lishi talab etiladi. Buning uchun ko’rsatkichlar va murojaatlardan foydalaniladi. Faktik parametr adres bilan uzatilganda unga mos keluvchi formal parametrni ikki xil usul bilan yozish mumkin: ko‘rsatkich yoki murojaat orqali. Ko‘rsatkich orqali yozilganda formal parametr turidan keyin ‘*’ belgisi yoziladi, mos argumentda esa o‘zgaruvchining adresi (& amal orqali) yoki massiv nomi, yoki funksiya nomi bo‘lishi mumkin. Murojaat orqali parametr uzatishda formal parametrda turidan keyin ‘&’ belgisi yoziladi va funksiya chaqirilishida mos argument sifatida o‘zgaruvchi nomi keladi. Misol: #include void f(int,int*,int&) void main() { int i=1, j=2, k=3; cout< =
−
=
1, 0;
*( 1)!, 0;
!
agar n
n n agar n
n .
Ko’rinib turibdiki, navbatdagi qiymatni hisoblash uchun funksiyaning oldingi qiymati
ma’lum bo‘lishi kerak. C++ tilida rekursiya matematikadagi rekursiyaga o‘xshash. Buni yuqoridagi
misol uchun tuzilgan funksiyada ko‘rish mumkin:
long fac(int n)
{
if(!n) return 1;
else return n*fac(n-1);
}
Agar faktorial funksiyasiga n>0 qiymat berilsa, quyidagi holat ro’y beradi: shart
operatorining else tarmog’idagi qiymati (n ning qiymati) stekda eslab qolinadi. Noma’lumlarni
hisoblash uchun shu funksiyaning o’zi oldingi qiymat (n-1 ning qiymati) bilan chaqiriladi. O‘z
navbatida, bu qiymat ham eslab qolinadi (stekka joylanadi) va yana funksiya chaqiriladi va hokazo.
Funksiya n=0 qiymat bilan chaqirilganda if operatorining sharti rost bo‘ladi va «return 1;» amali
bajarilib, ayni shu chaqirish bo‘yicha 1 qiymati qaytariladi. Shundan keyin «teskari» jarayon
boshlanadi − stekda saqlangan qiymatlar ketma-ket olinadi va ko‘paytiriladi: oxirgi qiymat
aniqlangandan keyin (1), u o’zidan oldingi stekda saqlangan qiymatga, ya’ni 1 qiymatiga
ko‘paytirib fac(1) qiymati hisoblanadi, bu qiymat 2 qiymatiga ko‘paytirish bilan fac(2) hisoblanadi
va hokazo.
Rekursiv funksiyalarning to‘g‘ri ishlashi uchun rekursiv chaqirishlarning to‘xtash sharti
bo‘lishi kerak. Aks holda rekursiya to‘xtamasligi va o‘z navbatida funksiya ishi cheksiz davom
etadi. Faktorialni hisoblashda rekursiv tushishlarning to‘xtash sharti funksiya parametri n=0
bo‘lishidir (shart operatorining rost tarmog’i).
Har bir rekursiv murojaat qo‘shimcha xotira talab qiladi–funksiyalarning lokal
o‘zgaruvchilari uchun har bir murojaatda stekdan yangidan joy ajratiladi. Masalan, rekursiv
funksiyaga 100 marta murojaat qilinsa, jami 100 ta lokal ob’yektlarning majmuasi uchun stekdan
joy ajratiladi. Ayrim hollarda, juda ko‘p rekursiya bo‘lganda, stek o‘lchami cheklanganligi sababli u
to‘lib qolishi mumkin va bu holatda dastur o‘z ishini «Stek to‘lib ketdi» xabari bilan to‘xtatadi.
Lekin shunday masalalar borki, ularni yechishda rekursiya juda samarali, hattoki, yagona usuldir.
Xususan, grammatik tahlil masalalarida rekursiyadan foydalanish, qulay usullardan biri
hisoblanadi.
C++ dasturlash tizimida ma’lumotlarning faylli toifasi. C++ dasturlash tizimida
ma’lumotlarning murojaat toifasi
Programma ishlashi natijasida olingan ma'lumotlami, saqlab qo'yish uchun, CD, DVD disklar,
qattiq disklar va boshqa har xil tashqi qurilmalardan foydalaniladi. Ma'lumotlami saqlab qo'yish
uchun tashqi qurilmalardan foydalanish qulay va ishonchlidir.
Ma'lumotlarni saqlab qo'yish uchun, tashqi xotiraning nomlangan qismiga favl deyiladi.
Bunday fayllar fizik fayllar deyiladi.
Mantiqiv fayllar. Fizik fayllar bilan ishlash uchun, programmalashtirish tillarida maxsus
strukturalashgan, toifalangan fayllar kiritilgan. Bunday fayllar mantiqiy (logicheskiy) fayllar
deyiladi. Mantiqiy fayllar, hech qanday fizik xotirani band qilmasdan ma'lumotlaming mantiqiy
modelini o'zida saqlaydi.
Fizik va mantiqiv favllar bir - biri bilan fopen funksiyasi orqali bog’lanadi.
Fayl bir nechta elementdan tashkil topgan bo'lganligi uchun, faqat fayl ko'rsatkichi ko'rsatayotgan elementga murojaat qilish mumkin.
Fayldan o'qish yoki yozish mumkin bo'lgan o'rimi ko'rsatuvhi elementga fayl ko'rsatkichi deyiladi. Fayldan nia'lumot o'qiganda yoki yozganda fayl ko'rsatkichi avtomat ravishda o'qilgan yoki yozilgan bayt miqdoricha siljiydi. Fayl ko'rsatkichini magnitafon galovkasiga o'xshatish mumkin.
Binar fayl - har xil ob'ektlami ifodalovchi baytlar ketma - ketligidir. Ob'ektlar faylda qanday ketma - ketlikda joylashganini programmaning o'zi aniqlashi lozim.
Fayllar bilan ishlovchi funksiyalardan foydalanish uchun sarlavha faylini programmaga qo'sliish kerak bo'ladi. Fayldan ma'luniotlami o'qish yoki yozish uchun ochish fopen funksiyasi orqali amalga oshiriladi.
FILE * fopen (const char * filename, const char * mode);
filename - o'zgaruvchisi char toifasidagi satr bo'lib, faylning to'liq nomini ko'rsatishi lozim
(filename = "D:\Qudrat_c++\Namuna\file\file.txt"). Agar faylning faqat nomi ko'rsatilgan bo'lsa, fayl joriy katalogdan qidiriladi (filename = "file.txt").
mode - o'zgaruvchisi ham char toifasidagi satr bo'lib, faylni qaysi holatda ochish lozimligini bildiradi.

Faylni ochishda xatolik sodir bo'lsa, fopen funksiyasi NULL qiymat qaytaradi. Ochilgan faylni vopish uchun fclose funksiyasi ishlatiladi.
int fclose ( FILE * stream);
Faylni yopishda xato sodir bo'lmasa, fclose funksiyasi nol qiymat qaytaradi. Xato sodir bo'lsa, EOF - fayl oxiri qaytariladi.
Faylga ma'lumot yozish va o'qish
size t fread (void * ptr, sizet size, sizet n, FILE * stream);
fread funksiyasi, fayldan ptr ko'rsatkichi adresiga size hajmdagi ma'himotdan n tani o'qishni amalga oshiradi. Agar o'qish muvoffaqiyatli amalga oshsa fread funksiyasi o'qilgan bloklar soni n ni qaytaradi. Aksholda nol qaytariladi
size t fwrite ( const void * ptr, size t size, size t n, FILE * stream);
fwrite funksiyasi, faylga ptr ko'rsatkichi adresidan boshlab size hajmdagi ma'lumotdan n tani yozishni amalga oshiradi.
1 - Misol. fread va fwrite funksiyalarining qo'llanilishi
finclude finclude using namespace std;
int main()
{
int n = 5; double d = 10.77;
char s [20] = "dastur.uz";
FILE *f;
// binar faylni yozish uchun ochamiz f = fopen("my_file.dat", "wb");
fwrite(&n, sizeof(int), 1, f); // n sonini faylga yozish fwrite(&d, sizeof(double), 1, f); // d sonini faylga yozish // satrni faylga yozish
fwrite (s, sizeof (char) , strlen(s) + 1, f) ; fclose(f); // faylni yopish
n = 0; d = 0;
// binar faylni o'qish uchun ochamiz f = fopen("my_file.dat", "rb");
fread(&n, sizeof (int) , 1, f) ; // n sonini fayldan o'qish fread(&d, sizeof (double) , 1, f) ; // d sonini fayldan o'qish // satrni fayldan o'qish
fread (s, sizeof (char), strlen(s) + 1, f) ; fclose(f); // faylni yopish
cout « n « endl; cout « d « endl;
cout << s << endl return 0;
yuqoridagi misolda satrni yozish va o'qish uchun quyidagicha kod ishlatildi:
fwrite(s, sizeof (char), strlen(s) + 1, f) ; fread (s, sizeof (char), strlen(s) + 1, f);
Buning kamchiligi s satridagi har bir belgi alohida - alohida faylga yozildi va o'qildi. Bu masalani quyidagicha hal qilish mumkin edi:
fwrite(s, sizeof (s), 1, f) ; fread (s, sizeof (s), 1, f) ;
Lekin bu usulning ham kamchiligi bor. Ya'ni s satri belgilari soni massiv o'lchamidan kam bo'lgan holda, keraksiz ma'lumotlami saqlash va o'qish sodir bo'ladi.
Fayl ko'rsatkichi bilan ishlovchi funksiyalar
Fayldan ma'lumot o'qiganda yoki yozganda fayl ko'rsatkichi avtomat ravishda o'qilgan yoki yozilgan bayt miqdoricha siljiydi. Fayl ko'rsatkichining kelgan joyini aniqlash uchun ftell funksiyasi ishlariladi.
long int ftell ( FILE * stream);
Fayl ko'rsatkichini siljitish uchun fseek funksiyasi ishlatiladi.
int fseek (FILE * stream, long int offset, int whence);
Bu fimksiya offset da ko'ratilgan bayt miqdoricha siljishni amalga oshiradi. Whence o'zgaruvchisi quyidagi qiymatlami qabul qilishi mumkin:
Agar whence = 1 bo'lsa (SEEK CUR), offset musbat (o'ngga siljish) yoki manfiy (chapga siljish) bo'lishi mumkin.
Fayl ko'rsatkichini faylning boshiga o'matish uchun rewind funksiyasi ishlatiladi.
void rewind ( FILE * stream );
Bu amalni fayl ko'rsatkichini siljitish orqali ham amalga oshirish mumkin.
fseek (f, 0, SEEKSET);
Agar faylda faqat butun sonlar yozilgan bo'lsa, uning k - elementiga murojaat quyidagicha bo'ladi.
fseek (f, sizeof (int) * (k - 1), SEEK_SET); fread (&n, sizeof(int), 1, f) ;
Fayl oxirini aniqlash uchun feof funksiyasi ishlatiladi.
int feof (FILE * stream );
feof funksiyasi fayl ko'rsatkichi fayl oxirida bo'lsa, noldan farqli qiymat qaytaradi. Boshqa hollarda nol qaytaradi.
2 - misol. n natural soni berilgan. Elementlari n ta butun sondan iborat bo'lgan faylni hosil qiluvchi va ekranga chiqaruvchi programma tuzilsin.
finclude finclude using namespace std;
int main ()
{
int n, k;
FILE *f;
f = fopen("binar", "wb+");
// binar faylni yozish va o'qish uchun ochish if (f == NULL)
{
cout << "Faylni hosil qilishda xato bo'ldi"; return 1;
}
cout << "n="; cin >> n; for (int i = 0; i < n; i++)
{
cin » k;
fwrite (&k, sizeof (k) , 1, f) ;
}
// fayl ko'rsatkichini fayl boshiga qo'yish rewind(f);
while (fread(&k, sizeof (k) , 1, f) )
{
//fayl boshidan fayl ko'rsatkichi turgan o'ringacha bo'lgan baytlar int bayt = ftell(f);
cout << k «" ftell (f)=" « bayt << endl;
}
fclose (f); return 0;
3 - misol. n natural soni berilgan. Elementlari n ta butun sondan iborat bo'lgan faylni hosil qiluvchi va juft elementlarini 2 marta orttiruvchi programma tuzilsin.
finclude finclude using namespace std;
int main()
{
int n, k;
FILE *f;
// binar faylni yozish va o'qish uchun ochish f = fopen("binar", "wb+");
if (f == NULL)
{
cout « "Faylni hosil qilishda xato bo'ldi";
return 1;
}
cout << "n="; cin >> n; for (int i = 0; i < n; i++)
{
cin » k;
fwrite (&k, sizeof (k) , 1, f) ;
}
// fayl ko'rsatkichini fayl boshiga qo'yish rewind (f);
while (!feof(f)) // fayl oxiri uchramasa bajar {
fread(&k, sizeof (k), 1, f) ; if (k % 2 == 0 )
{
k *= 2;
// fayl ko'rsatkichini sizeof (int) bayt chapga surish fseek(f, -sizeof(int), SEEK_CUR); fwrite(&k, sizeof(int), 1, f) ;
// fayl ko'rsatkichini o'rnatish fseek(f, ftell(f), SEEK SET) ;
}
}
cout << "fayl elementlari\n"; rewind(f);
while (fread(&k, sizeof (k) , 1, f) ) cout << k << endl;
fclose(f); return 0;
3 - misolni quyidagicha yechish ham mumkin.
linclude linclude using namespace std;
int main()
{
int n, k;
FILE *f;
f = fopen("binar", "wb+"); cout << "n="; cin >> n; for (int i = 0; i < n; i++)
{
cin » k;
fwrite (&k, sizeof (k) , 1, f) ;
}
// fayl ko'rsatkichini fayl boshiga qo'yish rewind (f); while (!feof(f))
{
// fayl ko 'rsatkichi o 'mini eslab qolish int pos = ftell(f); fread(&k, sizeof (k), 1, f) ; if (k % 2 == 0 )
{
k *= 2;
// fayl ko'rsatkichini oldingi holatiga o 'rnatish fseek (f, pos, SEEK_SET) ; fwrite (&k, sizeof(int), 1, f) ;
// fayl ko'rsatkichi o'mini sizeof (int) da surish pos += sizeof(int); fseek (f, pos, SEEK_SET) ;
}
}
cout << "fayl elementlari\n"; rewind(f);
// fayl elementlarini chiqarish while (fread(&k, sizeof (k) , 1, f) )
cout << k << endl
fclose(f) ; return 0;
Nazorat savollari:
1. Borland C++ Builder 6 ning strukturalashgan toifalariqanday e’lon qilinadi
2. Ko’rsatkichlar haqida tushuncha bering
3. Lokal o’zgaruvchilar haqida tushuncha bering
4. Statik o’zgaruvchilar haqida tushuncha bering
5. Dinamik o’zgaruvchilar haqida tushuncha bering
6. Massiv nima?
7. Bir va ko’p o’lchovli massivlar qanday farqlanadi?
8. Dinamik massivlar haqida tushuncha bering
9. C++ da funktsiya qanday e’lon qilinadi?
10. C++ da protseduralar qanday e’lon qilinadi?
11. Malumotlarning faylli toifasirning qanday turlari bor?