0% found this document useful (0 votes)
765 views378 pages

Dasturlash Asoslari: M. A. Bobojonova

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
765 views378 pages

Dasturlash Asoslari: M. A. Bobojonova

Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

M. A.

Bobojonova

DASTURLASH ASOSLARI
(Birinchi qism)

Darslik
M. A. Bobojonova

DASTURLASH ASOSLARI 1-QISM


(Darslik)

60610200-Axborot tizimlari va texnologiyalari


(tarmoqlar va sohalar bo‘yicha)

“KAMOLOT” nashriyoti
Buxoro-2023
UO‘K: 004.424
KBK: 32.973
B69

Bobojonova Madina Abduahat qizi, Dasturlash asoslari 1-qism /


[Matn]: Darslik / M.A.Bobojonova - Buxoro : “BUXORO
DETERMINANTI”MCHJning Kamolot nashriyoti, 2023. - 376 b.

Mazkur darslik Oliy ta`lim muassalarining 60610200-Axborot


tizimlari va texnologiyalari (tarmoqlar va sohalar bo‘yicha) ta`lim
yo‘nalishi talabalari uchun “Dasturlash asoslari 1-qism” fanining o‘quv
dasturi asosida ishlab chiqilgan.
C++ dasturlash tili sodda, dasturchilar tomonidan eng ko‘p
qo‘llanilayotgan til sifatida e`tirof etiladi. “Dasturlash asoslari 1-qism”
darsligi oliy o‘quv yurtlaridagi o‘qitish effektivligini oshirishga, C++
tilini kengroq qo‘llashga xizmat qiladi.
Darslikdan barcha Axborot tizimlari va texnologiyalari (tarmoqlar
va sohalar bo‘yicha) ta`lim yo‘nalishi talabalari va professor-
o‘qituvchilar foydalanishi mumkin.

Taqrizchilar:
F.A.Muradov - Raqamli texnologiyalar va sun`iy intellektni
rivojlantirish ilmiy-tadqiqot instituti katta ilmiy xodimi, texnika fanlari
bo‘yicha falsafa doktori;
T.R.Shafiyev - Buxoro davlat universiteti “Axborot tizimlari va
raqamli texnologiyalar” kafedrasi mudiri, PhD, dotsent.

ISBN: 978-9910-734-38-0

Oliy ta’lim, fan va innovatsiyalar vazirligi Buxoro davlat


universitetining 2023 yil “21” oktabrdagi “556”- soni buyrug‘iga
asosan nashr etishga ruxsat berildi. Ro‘yxatga olish raqami 556-2

© “KAMOLOT” nashriyoti
© Bobojonova Madina Abduahat qizi
2
АННОТАЦИЯ

Учебник разработан на основе учебной программы по


дисциплине “Основы программирования часть 1” для студентов
образовательного направления 60610200-Информационные
системы и технологии высших учебных заведений. Язык
программирования C++ считается простым, наиболее часто
используемым программистами. Учебник “Основы програм-
мирования часть 1” служит повышению эффективности препо-
давания в высших учебных заведениях, более широкому
применению языка C++. Учебник может быть использован
студентами и преподавателями всех направлений обучения
информационным системам и технологиям.

ANNOTATION

The textbook is developed on the basis of the curriculum on the


discipline “Fundamentals of programming part 1” for students of the
educational direction 60610200-Information systems and technologies
of higher educational institutions. The C++ programming language is
considered to be the simplest, most commonly used by programmers.
The textbook “Fundamentals of Programming part 1” serves to increase
the effectiveness of teaching in higher educational institutions, wider
use of the C++ language. The textbook can be used by students and
teachers of all areas of training in information systems and
technologies.

3
MUNDARIJA:

1-MAVZU. KIRISH. ALGORITM TUSHUNCHASI VA TASVIRLASH


USULLARI 6
2-MAVZU: C++ DASTURLASH TILINING TUZILISHI 18
3-MAVZU: O‘ZGARUVCHILAR VA IFODALAR 27
4-MAVZU: C++ TILINING AMALLARI. INKREMENT, DECREMENT, SIZEOF, MANTIQIY,
RAZRYADLI, TAQQOSLASH. AMALLARNING USTUNLIKLARI VA BAJARILISH
YO‘NALISHLARI 43
5-MAVZU. C++ KIRITISH VA CHIQARISH OPERATORLARI VA
MANTIQIY(BOOLEAN) BILAN ISHLASH 56
6-MAVZU. C++ TILIDA SHART OPERATORLAR 70
7-MAVZU. C++ DA TAKRORLASH OPERATORLARI 84
8-MAVZU. C++ DA MASSIVLAR 97
9-MAVZU: C++ DA BELGI VA SATRLAR 110
10-MAVZU. C++ DA FUNKSIYALAR 116
11-MAVZU. FUNKSIYANING MASSIVLI PARAMETRLARI. 141
12-MAVZU. REKURSIV VA QAYTA YUKLANUVCHI
FUNKSIYALAR 147
13-MAVZU. C++ DA FAYL TUSHUNCHASI. FAYLDAN O’QISH VA
YOZISH FUNKSIYALARI. FAYLLAR USTIDA AMALLAR. 154
14-MAVZU. STANDART KUTUBXONA FUNKSIYALARI. 162
15-MAVZU. OOP (OBYEKTGA YO’NALTIRILGAN DASTURLASH) HAQIDA
TUSHUNCHA. C++ DA STRUKTURALAR. 176

4
16-MAVZU. SINFLAR VA OBYEKTLAR 193
17-MAVZU. C++ DA MODIFIKATOR BILAN ISHLASH 221

18-MAVZU. STATIK BERILGANLAR, STATIK SINFLAR 228


19-MAVZU. OPERATORLARNI QAYTA ANIQLASH. 239
20-MAVZU. VORISLIK. 255
21-MAVZU. ICHMA-ICH JOYLASHGAN SINFLAR 271
22-MAVZU. POLIMORFIZM 275
23-MAVZU. C++ DA MAVHUM(ABSTRACT) SINFLAR. 295
24-MAVZU. C++ DA TRY, CATCH. 299
NAZORAT UCHUN TEST SAVOLLARI 310

GLOSSARIY 368
XULOSA 372
FOYDALANILGAN ADABIYOTLAR RO‘YXATI 374

5
1-MAVZU. KIRISH. ALGORITM TUSHUNCHASI VA
TASVIRLASH USULLARI
 Algoritm tushunchasi va tasvirlash usullari
 Dasturlash tillari tarixi
 C++ dasturlash tiliga ekskursiya
 C++dasturini ishlab chiqarish bosqichlari qanday?
 C++tilida birinchi dasturni yozish va kompilyatsiya qilish

Kompyuter dasturlash tilida muayyan masalani hal qilish


uchun aniq belgilangan ko'rsatmalar to'plamidir. U bir qator
kirish(lar)ni oladi va kerakli natijani beradi.
Bir necha misollarni ko‘rib chiqamiz.
1-masala: Foydalanuvchi tomonidan kiritilgan ikkita sonni
qo'shing.
1-qadam: Boshlash
2-qadam: num1, num2 va sum o'zgaruvchilarni e'lon qiling.
3-qadam: num1 va num2 qiymatlarini o'qing.
4-qadam: 1 va 2 sonlarni qo'shing va natijani yig'indiga
o‘zlashtiring.
sum←num1+num2
5-qadam: yig`indini konsolga chiqarish.
6-qadam: To'xtating.
2-masala: Uchta sondan eng katta sonni toping.
1-qadam: Boshlash
2-qadam: a,b va c o'zgaruvchilarni e'lon qiling.
3-qadam: a, b va c o'zgaruvchilarni o'qing.
4-qadam: Agar a > b
Agar a > c a ni konsolga chiqarish
Aks holda c ni konsolga chiqarish
Aks holda
Agar b > c b ni konsolga chiqarish
Aks holda
c ni konsolga chiqarish
5-qadam: To'xtating

6
3-masala: Sonning faktorialini toping.
1-qadam: Boshlash
2-qadam: n, faktorial va i o'zgaruvchilarni e'lon qiling.
3-qadam: o'zgaruvchilarni ishga tushiring
faktorial ← 1
i←1
4-qadam: n qiymatini o‘qish
5-qadam: i = n ga qadar amallarni takrorlang
5.1: faktorial ← faktorial*i
5.2: i ← i+1
6-qadam: faktorialni ko'rsating
7-qadam: To'xtating

Algoritmlarni tasvirlashning ham turli usullari mavjud. Quyida


algoritmlarni tasvirlashning keng tarqalgan usullarini ko‘rib chiqamiz:
I. Algoritmni so‘zlar yordamida ifodalanishi
Algoritmning so‘zlar orqali ifodalanish (masalan, choy damlash
yoki yig’indi hisoblash algoritmi) usulida ijrochi uchun ko‘rsatma
gaplar orqali buyruq tarzida beriladi.
Misol tariqasida suv havzasi oldida turgan A litrli va B litrli suv
idishi bor. Ijrochi uchun {A ni to‘ldir; B ni to‘ldir; A dan B ga quy; B
dan A ga quy; A ni bo’shat; B ni bo‘shat} ko’rsatmalar sistemasini olish
mumkin. Bu ijrochiga xos masalaning maqsadi o‘lchab olinishi kerak
bo‘lgan suv miqdorining A yoki B idishlardan birortasida hosil
bo‘lishidir.
4-masala: A=3 va B=5 bo‘lganda suvchi 1 litr suv o‘lchab olishi
uchun algoritm tuzing.
Qadamlar Algoritmdagi ko‘rsatmalar A idishdagi B idishdagi
suv miqdori suv miqdori
1 A ni to‘ldir; 3 litr 0 litr

2 A dan B ga quy; 0 litr 3 litr

3 A ni to‘ldir; 3 litr 3 litr

4 A dan B ga quy. 1 litr 5 litr

7
II. Algoritmni formulalar yordamida ifodalanishi
Algoritmni formuladagi “+”, “”, “·”, “” kabi arifmetik
amallarning hisoblash qoidalariga rioya qilgan holda bajarilishi
formulalar yordamida ifodalanishiga misol bo‘ladi.
𝑎𝑥 2 + 𝑏𝑥 + 𝑐 = 0(𝑎 ≠ 0) ko‘rinishidagi kvadrat tenglamani yechish
algoritmining quyida keltirilgan formula orqali ifodasi bilan tanishsiz:
−𝑏 ± √𝑏 2 − 4𝑎𝑐
𝑥=
2𝑎
III. Algoritmni jadval yordamida ifodalanishi
Algoritmning jadval ko‘rinishda berilishi ham sizga tanish.
Masalan, matematikadagi Pifagorning ko‘paytirish jadvali, lotoreya
yutuqlar jadvali, Mendeleyev kimyoviy elementlar jadvali. Bunday
jadvallardan foydalanish ma’lum bir algoritm qo‘llashni talab etadi.
Biror funksiyaning grafigini chizish uchun ham
funksiyaning argument qiymatlariga mos qiymatlar jadvalini hosil
qilamiz. Bu ham algoritmning jadval ko‘rinishiga misol bo‘ladi.
5-masala: 𝑦 = 𝑥 2 algoritm asosida harakat qilayotgan ijrochi
o‘tadigan nuqtalarni ba’zilari ko‘rsatilgan quyidagi jadval bilan
matematikadan tanishsiz:
x -3 -2 -1
y 9 4 1

IV. Algoritmni grafik ko‘rinishda ifodalanishi


Algoritmning bu ko‘rinishdagi ifodasi bilan funksiyaning grafigi,
ob-havoning o‘zgarish grafigi, avtobuslarning yo‘nalish sxemasi orqali
sizga tanish.
Algoritmlash asoslarini o‘rganishning yana bir qulay grafik
ko‘rinishi dir. Blok-sxemalar yo‘nalish chiziqlari
orqali tutashtirilgan ma’lum buyruq yoki ko‘rsatmani aks ettiruvchi
maxsus geometrik ko‘rinishlar – bloklardan tashkil topadi:

8
algoritmning boshlanishini va
tugallanganligini bildiradi
ma’lumotlarni kiritishni bildiradi

ma’lumotlarni chiqarishni bildiradi

Barcha amallar, masalan qiymat berish


yoki tegishli ko‘rsatmalar berishni
bildiradi

shart tekshirilishini bildiradi

takrorlanish boshlanishini bildiradi


yordamchi algoritmga murojaatni
bildiradi
sxemadagi harakat yo‘nalishini bildiradi

V.Algoritmni dastur rasmida ifodalanishi.


Ma’lumki, kompyuter dasturlar asosida ishlaydi va boshqariladi.
Demak, bu kabi algoritmlar bajarilishi uchun algoritm
ijrochisiga, ya’ni kompyuterga tushunarli bo‘lishi lozim.
Odatda, algoritmning kompyuter tushunadigan tilda
yozilishi deb ataladi. Kompyuter tushunadigan til
esa deb ataladi. Jahonda minglab dasturlash tillari
mavjud va rivojlanib bormoqda. Hozirgi kunda Python,
BASIC, Pascal, VBA, Delphi, C, C++ dasturlash tillari keng tarqalgan
va o‘rganish uchun qulay.
DASTURLASH TILLARI TARIXI

«Ikki tipdagi dasturlash tillari mavjud — birinchisi ustida hamma


“urushadi”, boshqasida esa hech kim yozmaydi».

(B.Stroustrup, C++ dasturlash tilining asoschisi)

9
Dastur fayli doimiy xotirada (qattiq diskda) saqlanadi, bajarilish
vaqtida esa vaqtinchalik (operativ) xotiraga yuklanadi. Kompyuterda
axborotni kiritish klaviatura (kiritish qurilmasi) orqali, chiqarish esa
monitor (chiqarish qurilmasi) orqali amalga oshiriladi.
Kompyuter faqat ikki tipdagi signallar: 0 va 1 (mashina kodlari)
bilan ishlay oladi. 1010101010010101010 ko‘rinishdagi dasturni
yozish inson uchun qiyin masala. Shuning uchun ham insoniyatga
tushunarli bo‘lgan dasturlash tillari bilan birgalikda kompyuterga
tushunarli bo‘lgan yaratildi.

1.1-rasm. Markaziy protsessor tuzilishi

Mashina tillariga yaqin bo‘lgan dasturlash tillari


(Assembler), inson fikrlashiga yaqinroq bo‘lgan
dasturlash tillari (Python, Java, C#) deb
ataladi. Dasturlash tillarining har birining ajoyib tarixi mavjud.

10
1.2-rasm. Dasturlash tillari turlari
XX asrning 50-yillarida, mashina darajasiga eng yaqin bo'lgan past
darajadagi paydo bo'ldi. U protsessor bilan bog'langan,
shuning uchun uni o'rganish protsessor arxitekturasini o'rganishga
o'xshaydi. Bugungi kunda ham assembler tilida yozilgan, xotira
resurslari juda cheklangan dasturlar kichik
qurilmalar(mikrokontrollerlar)ning ajralmas qismi hisoblanadi.
Keyingi bosqich - ning paydo bo‘lishi bo‘lib, shuningdek
ushbu davrda yaratilgan ham hanuzgacha maktablarda
dasturlashni o'rgatishda asosiy til sifatida qo'llaniladi.
Dastlab operatsion tizim assembler tilida yozilgan bo‘lib, uni
o‘zgartirish va o‘rganish ancha qiyin bo‘lgan, keyinchalik
tizimli dasturlash uchun ni ishlab chiqdi va B.Kernigan bilan
birgalikda tizimini shu tilda qayta yozdi.
So‘ngra UNIX operatsion tizimi keng tarqaldi (hozirda uning
GNU / Linux versiyalari ko'proq ma'lum) va unda ishlaydigan
dasturchilar soni ham keskin ko‘paydi.
Keyingi bosqich (80-yillar) yirik sanoat dasturlarini yaratishni
soddalashtirishi kerak bo'lgan ning
(OOP) paydo bo‘lishi bilan tavsiflanadi. C tilining
imkoniyatlaridan qoniqmadi, shuning uchun u OOP qo'shish orqali bu
tilni kengaytiradi. Yangi til C++ deb nomlandi.
C++ TILI TARIXI
Ilgari dasturchilar uzun 1 va 0 lar qatoridan iborat bo‘lgan
kompyuter buyruqlari bilan ishlashgan. Tez orada Assembler tili ixtiro
qilingandan so‘ng, ular mashina buyruqlarini odam uchun tushunarli
bo'lgan ko'rinishda namoyish etishlari mumkin edi.

11
Vaqt o'tishi bilan va kabi yuqori darajadagi tillar
paydo bo'ldi. Ushbu tillar yordamida so'zlar va gaplarning mantiqiy
loyihalashlaridan foydalangan holda dasturlash mumkin bo'ldi,
masalan, Let I = 100. Ushbu buyruqlar tomonidan mashina
tiliga tarjima qilingan. dasturni o'qiyotganda, uning
buyruqlarini (yoki kodini) mashina tili buyruqlariga ketma-ket o‘giradi.
dastur kodini to'liqligicha obyekt fayliga tarjima qiladi.
Ushbu bosqich deb ataladi.
Tarjimon tillarining yana biri bo‘lgan bilan ishlash
nisbatan osonroq, chunki dastur buyruqlari yozilgan ketma-ketlikda
bajariladi, bu esa dasturning bajarilishini nazorat qilishni
osonlashtiradi. Biroq, kompilyatsiya qilingan dasturlar tezroq ishlaydi,
chunki dastur buyruqlarini mashina tiliga tarjima qilish kompilyatsiya
bosqichini o‘zida amalga oshiriladi.
Ba'zi tillarda (masalan, Visual Basic) interpretator vazifasini
dinamik kutubxona bajaradi. Java tilining interpretatori virtual mashina
(Virtual mashina yoki VM). Brauzer odatda virtual mashina sifatida
ishlatiladi (masalan, Internet Explorer yoki Netscape).
Ko'p yillar davomida dasturning asosiy afzalligi uning qisqaligi va
bajarilish tezligi deb hisoblangan. Dasturchilar dasturni iloji boricha
qisqartirishga harakat qilishdi, chunki xotira juda qimmat edi. Ammo
kompyuterlar tobora portativ (ko'chma) bo‘lganligi sababli, arzonroq
(xotira ayniqsa sezilarli darajada arzon) va tezligi oshdi, bu esa o‘z
navbatida, rivojlanishga olib keldi. Bugungi kunda dasturchining ish
vaqtining narxi ancha yuqori. Endilikda professional ravishda yozilgan
va oson ishlaydigan dasturlarga talab o‘sib bormoqda.
DASTURLAR
so'zi ikki ma'noda ishlatiladi: dasturchi tomonidan yozilgan
alohida buyruq bloklari (yoki dastur kodini) va tayyor bir dasturiy
mahsulot. Shunday qilib, dasturni dasturchi tomonidan yozilgan
buyruqlar to'plami yoki kompyuterda bajariladigan dasturiy mahsulot
sifatida aniqlash mumkin.
Tarjimon dasturlari ikkiga bo‘linadi. Birinchi holda,
interpretatorlar dastur kodini mashina buyruqlariga tarjima qilishadi va
kompyuter ularni darhol bajaradi. Interpretatorlar bilan ishlash osonroq
bo‘lsada, aksariyat dasturlar kompilyatorlar yordamida yaratiladi,

12
chunki kompilyatsiya qilingan kod ancha tezroq. C++ tili ham
kompilyatsiya qilinadigan dasturlash tiliga misol bo‘la oladi.
Vaqt o'tishi bilan dasturchilar oldida turgan muammolar o'zgardi.
Shu bilan birga, ko'pincha dasturlarni yozganlar ham, ulardan
foydalanganlar ham kompyuter bilimlari sohasidagi mutaxassislar
edilar. Bugungi kunda esa ko'p o'zgarishlar bo‘ldi.
Ajablanarlisi shundaki, foydalanuvchilarning yangi avlodiga
dasturlar bilan ishlashni osonlashtirish uchun ushbu dasturlarning
murakkabligi sezilarli darajada oshdi. Zamonaviy dasturlarda
foydalanuvchilarga qulay bo‘lgan interfeyslar qo'llaniladi, ular ko'plab
oynalar, menyular, dialog oynalari va ko‘plab vizual grafik vositalar
bilan jihozlangan. Inson va kompyuter o'rtasidagi o'zaro
munosabatlarning ushbu yangi darajasini qo'llab-quvvatlash uchun
yozilgan dasturlar bundan o'n yil oldin yozilganlarga qaraganda ancha
murakkab.
Kompyuterlar uchun butunjahon internet axborot tarmog'ining
rivojlanishi bilan bozorga kirishning yangi davri boshlandi. Hozirda har
qachongidan ham ko'proq kompyuter foydalanuvchilari bor.
Dasturlash talablarining o'zgarishi bilan tillar ham, dastur yozish
texnologiyasi ham o'zgardi.
C++TILINING SOHALARI
Obyektga yo'naltirilgan tahlil, loyihalash va dasturlash g'oyasi
paydo bo'lganda, Byarn Stroustrup (Bjarne Stroustrup) C tilini (tijorat
dasturiy mahsulotlarini ishlab chiqarish uchun eng mashhur) uni
obyektga yo'naltirilgan dasturlash uchun zarur bo'lgan vositalar bilan
boyitish orqali kengaytirdi.
C++ tili haqli ravishda C davomi deb nomlangan bo‘lsada va C
tilidagi har qanday ishlaydigan dastur C++ kompilyatori tomonidan
qo'llab-quvvatlanadi, C dan C++ ga o'tishda juda katta o‘zgarish amalga
oshirildi. C++ tili C tili bilan bog'liq, shuning uchun dasturchilar C dan
C++dan foydalanishga osongina o'tishlari mumkin edi. Biroq, ko'plab
dasturchilar C++ tilidan to'liq foydalanish uchun avvalgi bilimlaridan
voz kechib, yangi bilimlarlarga, ya'ni dasturlash muammolarini
tushunish va hal qilishning yangi usulini o'rganishga ega bo‘lishlari
kerakligini aniqladilar.
Ko'pchilikda savol tug'iladi: "C++ C tilining davomi bo'lganligi
sababli, avval C ni o'zlashtirishim kerakmi?" Stroustrup va boshqa

13
ko'plab dasturchilar, C++ dan foydalanadiganlar, bu kerak emas va buni
qilmaslik yaxshiroq deb hisoblashadi.
C++ VA JAVA
C++ hozirda tijorat dasturiy mahsulotlarini ishlab chiqarish uchun
ishlatiladigan asosiy til hisoblanadi. So'nggi yillarda Java kabi
dasturlash tili tufayli bu hukmronlik biroz o‘zgardi. Qanday bo'lmasin,
bu ikki til shu qadar o'xshashki, ulardan birini o'rganish orqali siz
boshqasini 90% o'zlashtirasiz.
ANSI STANDARTI
(American National Standards
Institute - ANSI) rahbarligida faoliyat yuritadigan standartlar qo'mitasi
C++tili uchun xalqaro standartni yaratdi.
C++ standarti hozirgi kunda - International Standard
Organization (xalqaro standartlash tashkiloti) deb nomlanadi. Bundan
tashqari, C++ tili standarti haqida gapirganda, ba'zida ular NCITS
(National Committee for Information Technology Standards - axborot
texnologiyalari standartlari bo'yicha Milliy qo'mita) yoki X3 (NCITS
qo'mitasining eski nomi) yoki ANSI/ISO degan ma'noni anglatadi.
Ushbu kitobda biz mashhur atama bo‘lgan ANSI standartiga amal
qilamiz.
ANSI standarti C++ tilining apparat jihatdan mustaqil bo‘lishini
ta'minlashga urinishdir (ya'ni kompyuterdan kompyuterga uzatiladi).
Bu shuni anglatadiki, dastur Microsoft kompilyatori uchun ANSI
standartiga muvofiq yozilgan, boshqa ishlab chiqaruvchining
kompilyatori yordamida xatosiz kompilyatsiya qilinadi. Bundan
tashqari, ushbu kitobda keltirilgan dasturlar ANSI-ga mos bo'lganligi
sababli, ular Mac, Windows yoki Alpha platformalarida ishlaydigan
kompyuterlarda xatosiz kompilyatsiya qilinishi kerak.
Ko'pgina C++ tilini o'rganuvchilar uchun ANSI standarti ideal
bo'lib qolmoqda. Shunga qaramay, dasturiy mahsulotning an'anaviy
ANSI standartlariga muvofiqligi professional dasturchilar uchun
muhimdir.
C++ tili dasturchidan dasturni yozishdan oldin uni loyihalashdan
iborat tayyorgarlik bosqichini o'tkazishni talab qiladi.
Professional dasturchilar deyarli har kuni real hayotda duch
keladigan murakkab muammolar rostan ham dastlabki loyihasini talab

14
qiladi va u qanchalik professionallik bilan amalga oshirilsa, dastur
ularni minimal vaqt va pul bilan hal qilishi mumkin.
Har qanday dasturni loyihalashga tayyorgarlik ko'rishda
beriladigan birinchi savol quyidagicha: "men qanday muammoni hal
qilmoqchiman?" Har bir dastur aniq belgilangan maqsadga ega bo‘lishi
kerak.
Har bir o'zini hurmat qiladigan dasturchi ikkinchi savolni
quyidagicha qo'yadi: "ushbu muammoni allaqachon mavjud bo'lgan
dasturiy mahsulotlar yordamida hal qilish mumkinmi?" Ko'pincha,
bunday yechim mutlaqo yangi dastur yaratishdan ko'ra yaxshiroq
bo‘lishi mumkin. Bunday yechimni taklif qiladigan dasturchi hech
qachon ish yetishmasligidan aziyat chekmaydi: muammolarga iqtisodiy
yechimlarni topish qobiliyati kelajakda uning mashhurligini
ta'minlaydi.
Muammoni tushunib, bu mutlaqo yangi dastur yozishni talab qiladi
degan xulosaga kelib, siz loyihalash bosqichiga tayyor bo'lasiz. Har
qanday tijorat dasturini yaratish muammoni sinchkovlik bilan tahlil
qilishni va uning samarali yechimini loyihalashni talab qiladi.
Sizning kompilyatoringiz o'zining o'rnatilgan matn muharririga
ega yoki siz fayllarni formatlash atributlarisiz matn formatida
saqlaydigan har qanday kod kiritish muharriridan foydalanishingiz
mumkin. Bunday muharrirlarga Windows Notepad, DOS Edit, Brief,
Epsilon, EMACS buyruqlari misol bo'la oladi. WordPerfect, Word va
boshqalar fayllarni matn formatida saqlashga imkon beradi.
Matn muharrirlari yordamida yaratilgan fayllar deb
ataladi. Ular odatda kengaytmaga .cpp, .cp yoki .c ega. ushbu kitobda
dastur kodlarini o'z ichiga olgan fayllar kengaytmaga .cpp ega.
ESLATMA: Ko'pgina C++ kompilyatorlari uchun dasturning asl
matnini o'z ichiga olgan fayl qaysi kengaytmaga ega bo‘lishi muhim
emas, garchi ko'pchilik .cpp kengaytmani sukut holatda ishlatadi.
DASTUR KODINI KOMPILYATSIYA QILISH
Sizning faylingizdagi dasturning asl matni uni ko'rib chiqadigan
har bir kishi uchun tushunarli bo'lmasada (ayniqsa C++ tilini
bilmaganlar uchun), u inson tomonidan idrok etilishi mumkin bo'lgan
ko‘rinishda taqdim etilgan. Dastur matni fayli - bu hali dastur emas va
uni bajarish yoki ishga tushirish mumkin emas, ya’ni dasturga
aylantirish uchun kompilyator ishlatiladi.

15
Dastur kodini kompilyatsiya qilish tugagandan so'ng, obyekt fayli
yaratiladi. Ushbu fayl odatda .obj kengaytmaga ega. Ammo bu hali
bajarilmagan dastur. Obyekt faylini bajariladigan faylga aylantirilib
ishga tushirilishi mumkin.
-bu kompilyator bilan birga keladigan, alohida sotib
olinadigan yoki dasturchining o'zi tomonidan yaratilgan va tuzilgan
tarkibiy fayllar to'plami. Barcha C++ kompilyatorlari dasturga
kiritilishi mumkin bo'lgan funksiyalar (yoki protseduralar) va sinflar
kutubxonasi bilan birga keladi. Shunday qilib, bajariladigan faylni
yaratish uchun siz quyida keltirilgan amallarni bajarishingiz kerak.
1. .cpp kengaytmaga ega bo'lgan dastur faylini yarating.
2. Dastur kodini kompilyatsiya qiling va .obj kengaytmali obyekt
faylini oling.
3. .obj faylini kerakli kutubxonalar bilan birgalikda dastur faylini
ishlatish uchun kompilyatsiya qiling.
Dasturdagi har qanday xato tuzatilishi kerak va buning uchun
dastur matnini tahrirlash, uni qayta kompilyatsiya qilish va yana
ishlatish kerak.
C++ TILIDAGI BIRINCHI DASTUR HELLO.CPP
An'anaga ko'ra, dasturlash kitoblarida dasturlarning birinchi
misollari “Hello World!” so'zlarini yoki mavzu bo'yicha ba'zi
o'zgarishlarni ko'rsatish bilan boshlanadi. Bu kitobda biz an'analarga
amal qildik. Barcha qoidalarga amal qilgan holda C++ dasturlash tilida
birinchi dasturni kiriting. Yozishni tugatgandan so'ng, faylni saqlang,
kompilyatsiya qiling va bajaring. Dastur “Hello World!” so'zlarini
konsolga chiqarishi kerak. Ushbu dasturning barcha kodlari keyingi
darslarda batafsil ko'rib chiqiladi.
ESLATMA: Quyidagi listing chap tomonida qatorning tartib
sonlari yozilgan bo‘lib, ularni muharrir oynasiga kiritish shart emas.
Masalan, Listing 1.1 da birinchi qatorida siz quyidagilardan boshlab
kiritishingiz kerak:
#include <iostream>
Listing 1.1. Hello.cpp dasturi
1 #include <iostream>
2 using namespace std;
3 int main(){
4 cout << "Hello World!\n";
5 return 0;
6}

16
Siz kiritgan dastur matni bu yerda keltirilgan listingga mos
kelishiga ishonch hosil qiling. Tinish belgilariga e'tibor bering. 4-
qatordagi “ << ” belgisi chiqarish operatoridir. 4- va 5-qator nuqta-
vergul (;) bilan tugaydi. Dastur kodi satrini tugatish uchun ushbu belgini
qo‘yish kerak.
Kompilyatsiya jarayonidagi xatolar turli sabablarga ko'ra yuzaga
kelishi mumkin. Yaxshi kompilyatorlar nafaqat xatolik haqida xabar
berishadi, balki ular aniqlangan xatoning aniq manzilini ham
ko'rsatadilar.

Nazorat savollari va topshiriqlar:


1. C++ dasturi tarixi haqida nimani bilasiz?
2. Interpretator va kompilyator o'rtasidagi farq nima?
3. Quyidagi dasturni ko'rib chiqing va uni ishga tushirmasdan nima
qilayotganini tushunishga harakat qiling.
1 #include <iostream>
2 using namespace std;
3 int main(){
4 int x = 5;
5 int y = 7:
6 cout << "\n"
7 cout << x + y << * * << x * y;
8 cout << "\n";
9 return 0;
10 }
4. 3-mashqdagi dasturni kiriting va keyin uni kompilyatsiya qiling va
ishga tushiring. U nima vazifani bajaradi?
5. Quyidagi dasturni kiriting va kompilyatsiya qiling. Qanday xato
xabarlarini oldingiz?
1 include <iostream>
2 using namespace std;
3 int main(){
4 cout << "Hello World\n";
5 return 0;
6}
6. 5-mashqdan dasturdagi xatoni tuzating va keyin uni qayta
kompilyatsiya qiling, kompilyatsiya qiling va bajaring.

17
2-MAVZU: C++ DASTURLASH TILINING TUZILISHI
 Dev C++ dasturlash muhiti
 C++ dasturlash tilida dastur sintaksisi
 Cout obyekti haqida qisqacha ma'lumot
 Izohlar

C++ dasturlari obyektlar, funksiyalar, o'zgaruvchilar va boshqa


elementlardan iborat. Ushbu kitobning aksariyati ularning har birining
batafsil tavsifiga bag'ishlangan.
Dev-C++ ni https://www.bloodshed.net/ rasmiy sayti orqali
kompyuterga yuklab olishingiz mumkin.

2.1-rasm. Dasturni o‘rnatish jarayoni

2.2-rasm. Dasturni o‘rnatish jarayoni

18
2.3-rasm. Dev C++ dasturining ishchi oynasi
2.4-rasm. Dev C++ dasturida yangi fayl ochish

Ctrl+N tugmalari yordamida yangi fayl yaratiladi.

19
2.5-rasm. Dev C++ dasturida kompilyatsiya va dasturni bajarish
jarayoni
Compile & Run yoki F11 klavishlarini bosish orqali kompilyatsiya
va dasturni bajarish amalga oshiriladi.

2.6-rasm. Dev C++ dasturida faylni saqlash


Save file oynasi ochiladi. Faylni nomlab, Сохранить tugmasini
bosish orqali, fayl kompyuter xotirasiga saqlanadi.
20
hello.cpp fayli yaratiladi.
ODDIY C++ DASTURI
1-mavzuda keltirilgan oddiy hello.cpp dasturini batafsilroq ko'rib
chiqamiz. Muhokama qilish uchun 2.1 Listingida hello.cpp faylini
keltiramiz.
Listing 2.1. hello.cpp dasturi
1 #include <iostream>
2 using namespace std;
3 int main()
4{
5 cout << "Hello World!\n";
6 return 0;
7}
Natija: Hello World!
Tahlil: 1-qatorda iostream kutubxonasi chaqiriladi. Dasturda
birinchi bo'lib preprotsessor uchun signal bo'lib xizmat qiladigan #
belgisi mavjud. Kompilyatorni har safar ishga tushirganingizda,
preprotsessor ham ishga tushadi. U dasturni o'qiydi, funt belgisi ( # )
bilan boshlanadigan satrlarni topadi va dastur kompilyatsiya
qilinishidan oldin ushbu satrlar bilan ishlaydi.
- bu buyruq bo'lib, undan keyin fayl nomi keladi. Fayl
nomini o'z ichiga olgan burchakli qavslar (< >) ushbu faylni saqlash
uchun ajratilgan barcha papkalarda qidirish kerakligini anglatadi. Agar
sizning kompilyatoringiz to'g'ri sozlangan bo'lsa, unda burchakli
qavslar preprotsessorga iostream fayli ekanligini ko'rsatadi. Iostream
fayli (input-output-stream-kiritish-chiqarish operatori) ma'lumotlarni
ekranga chiqarish jarayoniga xizmat qiluvchi cout obyekti tomonidan
ishlatiladi. Preprotsessor kompilyatordan oldin ishlaydi va (#) belgisi
bilan boshlanadigan barcha satrlarni bajaradi, dastur kodini
kompilyatsiya qilishga tayyorlaydi. Dasturning asosiy kodi 3-qatorda
main () funksiyasini chaqirish bilan boshlanadi. C++ tilidagi har bir
dastur funksiyasini o'z ichiga oladi. Odatda funksiyalar boshqa
funksiyalar tomonidan chaqiriladi, ammo maxsus funksiya
bo‘lib, dastur ishga tushirilganda u avtomatik ravishda chaqiriladi.
Main () funksiyasi, boshqa qiymat qaytaradigan funksiyalar kabi
qaytish tipini (return) e'lon qilishi kerak. hello.cpp dasturida main()
funksiyasi int tipidagi qiymatni qaytaradi (integer so'zidan - butun),
ya'ni dastur oxirida bu funksiya operatsion tizimga butun sonni
qaytaradi. Bunday holda, 6-qatorda ko'rsatilgandek, 0 butun qiymati
21
qaytariladi. Qiymatni operatsion tizimga qaytarish unchalik muhim
emas va umuman olganda, bu qiymat tizimning o'zi tomonidan
ishlatilmaydi, ammo C++ tili standarti main() funksiyasini barcha
qoidalarga muvofiq e'lon qilishni talab qiladi.
ESLATMA: Ba'zi kompilyatorlar main() funksiyasini void tipidagi
qiymatni qaytarmaydigan tipda e'lon qilishga ham imkon beradi. Main
() funksiyasi int tipida e`lon qiling va ushbu funksiyaning oxirgi
qatoriga
return 0; ifodasini qo'ying.
ESLATMA: Ba'zi operatsion tizimlar dastur tomonidan
qaytarilgan qiymatni tekshirish imkoniyatini beradi. Funksiyani normal
tugatish sifatida return 0; qiymatini qaytarish maqsadga muvofiq.
Barcha funksiyalarni ochish figurali qavs ({) bilan boshlanadi va
yopish figurali qavs (}) bilan tugaydi. Main () funksiyasining figurali
qavslari 4 va 7 qatorlarga joylashtirilgan. Figurali qavslarni ochish va
yopish o'rtasida joylashgan har qanday kod funksiyaning tanasi
hisoblanadi.
Bizning eng oddiy dasturimizning barcha kodlari 5-qatorda
joylashgan. Cout obyekti satrlarni ekranga chiqarish uchun ishlatiladi.
Cin va cout, C++ tilida mos ravishda ma'lumotlarni kiritish
(masalan, klaviaturadan) va ularni chiqarish (masalan, konsolga) uchun
ishlatiladi.
obyekti qanday ishlatiladi: cout so'zini kiriting, so'ngra
chiqarish operatorini qo'ying << (bundan keyin biz uni
deb ataymiz). Ushbu operatordan keyin satr yoki biror qiymat
ekranda ko'rsatiladi. Agar siz matn satrini ekranda ko'rsatmoqchi
bo'lsangiz, 5-qatorda ko'rsatilgandek, uni qo'shtirnoq ichiga ( “ ”)
yozing.
- bu chop etiladigan belgilar to'plami.
Matn satrining ikkita oxirgi belgisi (\n) Hello world so'zlaridan
keyin yangi qatorga o'tish degan ma'noni anglatadi. Main () funksiyasi
7-qatorda tugaydi.
Cout obyektidan foydalanib qiymatni ekranga chiqarish uchun cout
so'zini kiritish va undan keyin (<<) belgisi kiritish kerakligi aytib
o‘tildi. Ikkita belgini kiritganingizga qaramay, C++ kompilyatori ularni
bitta operator sifatida qabul qiladi.

22
Listing 2.2. Cout obyektidan foydalanish
1 #include <iostream>
2 using namespace std;
3 int main(){
4 cout << "Hello there.\n";
5 cout << "Here is 5: " << 5 << " n";
6 cout << "The manipulator endl writes a new line to the screen.";
7 cout <<endl;
8 cout << "Here is a very big number:\ t" << 70000 << endl;
9 cout << "Here is the sum of 8 and 5:\ t" << 8+5 << endl;
10 cout << "Here's a fraction:\ t\ t" << (float) 5/8 << endl;
11 cout << "And a very very big number:\ t";
12 cout << (double) 7000 + 7000 << endl;
13 cout << "Don't forget to replace Jesse Liberty with your name…\n";
14 cout << "Jesse Liberty is a C++ programmer!\n";
15 return 0;
16 }

Chiqarish operatoridan so‘ng chiqarish ma'lumotlarini ko'rsating.


Cout obyektidan foydalanish Listing 2.2 da ko'rsatilgan. Ushbu dastur
matnini xuddi yozilganidek kiriting, faqat quyidagi so‘zlar bundan
mustasno: Jesse Liberty ismining o'rniga ismingiz va familiyangizni
lotin harflari bilan almashtiring.
Natija:
Hello there.
Here is 5: 5
The manipulator endl writes a new line to the screen.
Here is a very big number: 70000
Here is the sum of 8 and 5: 13
Here's a fraction:
0.625
And a very very big number: 4.9e+07
Don't forget to replace Jesse Liberty with your name…
Jesse Liberty is a C++ programmer!
ESLATMA: Ba'zi kompilyatorlar cout obyektidan keyin
foydalanilganda matematik amallarni qavs ichida bo‘lishini talab qiladi.
Bunday holda, 10-qator quyidagicha o'zgartirilishi kerak edi:
cout << "Here is the sum of 8 and 5:\ t" << (8+5) << endl;
Agar dastur cout obyekti va unga tegishli funksiyalaridan
foydalansa iostream faylini kiritish kerak. 5-qatorda cout obyektidan
foydalanishning eng oddiy holati ko'rsatilgan. \n belgisi-bu cout
obyektiga ekranda yangi qatorga o‘tishni ko'rsatadigan maxsus
formatlash belgisidir.
6-qatorda cout obyektiga uchta qiymat beriladi va ularning har biri
chiqarish operatori tomonidan ajratiladi. Birinchi qiymat "Here is 5: "
qatoridir. Ikki nuqtadan keyin bo'sh joy borligiga e'tibor bering: bo'sh

23
joy matn satrining bir qismidir. Keyin 5 qiymati chiqarish operatori
yordamida cout obyektiga uzatiladi va undan so‘ng yangi qatorga o‘tish
belgisi kelgan (bu belgi har doim ikki yoki bitta tirnoqlar ichida
yoziladi). Ushbu ifodani bajarayotganda ekranda ushbu qator paydo
bo'ladi.
Here is 5: 5
7-qatorda ekranda axborot xabari ko'rsatiladi, shundan so'ng 8-
qatorda endl operatori ishlatiladi. Ushbu operator ham yangi qatorga
o‘tish operatori hisoblanadi.
ESLATMA: Endl operatori (satr oxiri) degan ma'noni
anglatadi.
9-qatorda yana bir formatlash belgisi ishlatilgan - \t, bu belgi
ma`lumotlari o‘rtasida bir tabulyatsiya o‘lchamida bo‘sh joy qo‘yish
uchun ishlatiladi (9-12-qatorlar). 9-qator Long int tipidagi qiymatlarni
chop etadi. 10-qatorda cout obyekti matematik amal natijalarini
chiqarishi mumkinligi ko'rsatilgan. Cout obyektiga qiymat emas, balki
butun matematik ifoda 8+5 uzatiladi, ammo 13 soni ekranda
ko'rsatiladi.
11-qatorda cout obyekti boshqa matematik amalning natijasini
chiqaradi-5/8. Identifikator (float) cout obyektiga natijani kasr son
sifatida ko'rsatish kerakligini bildiradi.
13-qatorda 7000 + 7000 ifodasi cout obyektiga uzatiladi va
identifikator (double) natijaning chiqarishini eksponent ko'rinishda
o'rnatadi.
15-qatorga ismingizni kiritishingiz mumkin.
IZOHLAR
Dastur yozayotganda nima maqsadda yozayotganingiz har doim
aniq bo'ladi. Ammo, agar siz bir oydan keyin ushbu dasturga
qaytishingiz kerak bo'lsa, unda ajablanarli tomoni shundaki, siz nima
haqida yozganingizni deyarli eslay olmaysiz va tafsilotlar haqida
gapirishning hojati yo'q.
Dastur maqsadini esda saqlash va boshqalarga dasturingizni
tushunishga yordam berish uchun izohlardan foydalanish maqsadga
muvofiq.
-bu kompilyator tomonidan e'tiborsiz qoldirilgan, ammo
dasturda alohida satr yoki butun blokning maqsadini to'g'ridan-to'g'ri
tavsiflashga imkon beradigan matn.

24
IZOH TURLARI
C++ tilida ikki xil izoh ishlatiladi:
 Ikkita slash (//)
 slash va yulduzcha (/*) kombinatsiyasilari.
Ikkita slash (C++ uslubidagi izoh deb nomlanadi) yordamida
olingan izohlar bo‘lib, kompilyatorga izohdan keyingi
hamma narsani e'tiborsiz qoldirishni buyuradi. Slash va yulduzcha bilan
yozilgan izohga (C uslubidagi izoh deb nomlanadi)
deyiladi va kompilyatorga izoh belgilari boshlanishidan to izohni
tugatish belgisi paydo bo'lguncha hamma narsani e'tiborsiz qoldirishni
aytadi. Har bir ochiladigan / * belgilar juftligi */yopilish juftligiga mos
kelishi kerak.
C uslubidagi izohlar C++ tilida ham qo'llaniladi. C++ da
dasturlashda izohga olish uchun asosan ikkita slash belgilaridan
foydalaniladi va C uslubidagi izohlar faqat dasturning katta bloklarini
vaqtincha o'chirish uchun ishlatiladi.

IZOHLARDAN FOYDALANISH
Listing 2.3 da izohlardan foydalanish ko‘rsatilgan, ular dasturning
bajarilishi va uning natijalariga ta'sir qilmaydi.
Listing 2.3. hello.cpp dasturi misolida izohlar
1 #include <iostream>
2 int main()
3{
4 /* bu izoh,
5 bu qadar davom etadi
6 izohning oxiri yulduzcha va Slash belgisi bilan tugaydi */
7 cout << "Hello world!\n";
8 // ushbu izoh satr oxirida tugaydi
9 cout << "That comment ended! \n";
10 // ikki marta slashdan keyin hech nima bo'lmasligi mumkin,
11 /* bu belgilar orasi */
12 return 0;
13 }
Natija:
Hello world!
That comment ended!
Tahlil: 4-6-qatorlardagi izohlar, 8, 10 va 11-qatorlardagi izohlar
kabi, kompilyator tomonidan umuman e'tiborga olinmaydi. 8-qatordagi
izoh ushbu satr oxirida tugaydi, ammo 4 va 11-qatorlarda boshlangan
izohlarni to‘ldirish uchun izohning tugash belgisi (*/) talab qilinadi.

25
Nazorat savollari va topshiriqlar
1. Kompilyator va preprotsessor o'rtasidagi farq nima?
2. Main () funksiyasining o'ziga xos xususiyati nimada?
3. Qanday izohlarni bilasiz va ular bir-biridan qanday farq qiladi?
4. Izohlar bir qatorda joylashtirilishi mumkinmi?
5. Izohlar bir nechta satrlarni egallashi mumkinmi?
6. “ I love C++” xabarini ko'rsatadigan dasturni yozing.
7. Kompilyatsiya qilish va bajarish mumkin bo'lgan eng kichik
dasturni yozing.
8. Xatolar: ushbu dasturni kiriting va uni kompilyatsiya qiling. Nima
xatolik berdi?
1 #include <iostream>
2 using namespace std;
3 int main(){
4 cout << Is there a bug here?";
5 return 0;
6}

26
3-MAVZU: O’ZGARUVCHILAR VA IFODALAR

 O'zgaruvchilar va o‘zgarmaslarni e'lon qilish, aniqlash.


 O'zgaruvchilarga qiymatlarni o‘zlashtirish va ularni
dasturda ishlatish
 O'zgaruvchilar qiymatlarini ekranga chiqarish
Dasturlar ishlatilgan ma'lumotlarni saqlash qobiliyatiga ega
bo‘lishi kerak. Ushbu ma'lumotlarni taqdim etish va boshqarish uchun
o'zgaruvchilar va konstantalar qo'llaniladi.
O'ZGARUVCHI NIMA?
C++ tilida ma'lumotni saqlash uchun ishlatiladi.
O'zgaruvchini kompyuter xotirasida dastur foydalanish uchun mavjud
bo'lgan ba'zi qiymatlarni saqlashi mumkin bo'lgan katakcha sifatida
tasavvur qilish mumkin.
Kompyuter xotirasini bir qator katakchalar deb hisoblash
mumkin. Barcha katakchalar ketma-ket raqamlangan. Ushbu sonlar
deb ataladi. O'zgaruvchi bir yoki bir nechta
katakchalarni egallaydi, ularda ba'zi qiymatlarni saqlash mumkin.

3.1-rasm. O'zgaruvchini kompyuter xotirasida saqlash


O'zgaruvchining nomi (masalan, MyVariable) xotira
katakchasidagi yozuv sifatida tasavvur qilinishi mumkin, undan haqiqiy
xotira manzilini bilmasdan uni topishingiz mumkin. 3.1-rasmda bu
sxematik tarzda taqdim etilgan. Ushbu rasmga ko'ra, MyVariable
o'zgaruvchisi manzili 103 bo'lgan katakchadan boshlanadi. Uning
o'lchamiga qarab, MyVariable o'zgaruvchisi bir yoki bir nechta xotira
katakchalarini egallashi mumkin.
C++ tilidagi o'zgaruvchini aniqlashda kompilyatorga uning tipi,
masalan, int, char yoki boshqa turdagi ma'lumotlarni taqdim etish
kerak. Ushbu ma'lumot kompilyator unga qancha joy ajratilishi
kerakligini va ushbu o'zgaruvchida qanday qiymat saqlanishini biladi.

27
Har bir katak bir bayt hajmga ega. Agar butun tipdagi
o'zgaruvchiga to'rt bayt kerak bo'lsa, unda buning uchun to'rtta katak
ajratiladi, ya'ni aynan o'zgaruvchining tipi bo'yicha (masalan, int)
kompilyator ushbu o'zgaruvchiga qancha xotira (qancha katakcha)
ajratilishi kerakligini baholaydi.
Bir xil tipdagi o'zgaruvchilar uchun turli rusumdagi
kompyuterlarda turli xil xotira hajmi ajratilishi mumkin, shu bilan birga
bitta kompyuter ichida bir xil tipdagi ikkita o'zgaruvchi har doim
o‘zgarmas hajmga ega bo'ladi.
Char tipidagi o'zgaruvchi (belgilarni saqlash uchun ishlatiladi)
ko'pincha bir bayt hajmiga ega.
Ko'pgina kompyuterlarda short int(qisqa butun) tipi uchun odatda
ikkita bayt, long int (uzun butun) tipi uchun to'rt bayt, int tipi uchun
(qisqa yoki uzun kalit so'zsiz) ikki yoki to'rt bayt ajratilishi mumkin.
Butun qiymatning kattaligi kompyuter tizimi (32 yoki 64 bitli) va
ishlatilgan kompilyator tomonidan belgilanadi. Ushbu kitob 4 baytli
butun sonlardan foydalanishga qaratilgan, ammo sizda boshqa variant
bo‘lishi mumkin.
3.1 listingida keltirilgan dastur sizning kompyuteringizda ushbu
tiplarning aniq hajmini aniqlashga yordam beradi. faqat bir bayt
xotirani egallaydigan bitta harf, son yoki belgini anglatadi.
Listing 3.1. Turli xil tiplarning o'lchamlarini aniqlash
1 #include <iostream>
2 using namespace std;
3 int main()
4 {cout << "The size of an int is:\t\t" << sizeof(int) << " bytes.\n";
5 cout << " The size of a short int is:\t\t" << sizeof(short) << " bytes.\n";
6 cout << " The size of a long int is:\t\t" << sizeof(long) << " bytes.\n";
7 cout << " The size of a char is:\t\t" << sizeof(char) << " bytes.\n";
8 cout << " The size of a float is:\t\t" << sizeof(float) << " bytes.\n";
9 cout << " The size of a double is:\t\t" << sizeof(double) << " bytes.\n";
10 cout << " The size of a bool is:\t\t" << sizeof(bool) << " bytes.\n";
11 }
12 return 0;
13 }

Natija:
The size of an int is: 4 bytes.
The size of a short int is: 2 bytes.
The size of a long int is: 4 bytes.
The size of a char is:1 bytes.
The size of a float is:4 bytes.
The size of a double is:4 bytes.

28
The size of a bool is:1 bytes.
ESLATMA: Kompyuteringizda har xil tipdagi o'zgaruvchilarning
o'lchamlari boshqacha bo‘lishi mumkin.
Listing 3.1 operatorlarining aksariyati sizga tanish. 4-10 qatorlarda
sizeof() funksiyasidan foydalanish siz uchun yangi bo‘lishi mumkin.
Sizeof () funksiyasining natijasi kompilyator va kompyuterga bog'liq
bo'lib, uning maqsadi parametr sifatida uzatiladigan obyektlarning
o'lchamlarini aniqlashdir. Masalan, sizeof() funksiyasining 4-qatorida
int kalit so'zi uzatiladi. Funksiya ma'lum bir kompyuterda int tipidagi
o'zgaruvchining baytlarida hajmni qaytaradi. Bizning misolimizda int
va long int tiplari uchun to'rt bayt qiymati qaytariladi.

ISHORALI (SIGNED) VA ISHORASIZ (UNSIGNED) TIPLAR


Dasturlarda ishlatiladigan butun o'zgaruvchilari ishorali va ishora-
siz bo‘lishi mumkin. Ba'zan o'zgaruvchiga faqat musbat sonlardan
foydalanishni o‘zlashtirish foydali bo'ladi. Unsigned kalit so'zisiz butun
tiplar (short va long) ishorali hisoblanadi. Ishorali butun sonlar manfiy
yoki musbat bo‘lishi mumkin. Ishorasiz sonlar har doim musbatdir.
Ham ishorali, ham ishorasiz butun sonlar uchun bir xil baytlar
ajratilganligi sababli, ishorasiz butun sonda saqlanishi mumkin bo'lgan
maksimal son ishorali butun sonda saqlanishi mumkin bo'lgan
maksimal sondan ikki baravar ko'pdir. Unsigned short int tipi
yordamida siz 0..65535 oralig'idagi sonlarni joylashtirishingiz mumkin.
Short butun tipi bilan ifodalangan sonlarning yarmi manfiy, shuning
uchun bu tip yordamida sonlarni faqat – 32768..32767 oralig'ida
ifodalash mumkin.
C++ tilida boshqa tipdagi o'zgaruvchilar mavjud. Ular butun
sonlarga, haqiqiy (nuqtali) va belgi kabilarga bo'linadi.
Haqiqiy o'zgaruvchilar kasrlar sifatida ifodalanishi mumkin
bo'lgan qiymatlarni o'z ichiga oladi. Belgilar o'zgaruvchilari bir baytni
egallaydi va 256 ASCII belgilar va belgilarni, shuningdek
kengaytirilgan ASCII belgilar to'plamlarini saqlash uchun ishlatiladi.
kompyuterlarda ishlatiladigan standart belgilar
to'plami sifatida tushuniladi. ASCII-bu axborot almashinuvi uchun
Amerika standart kodi hisoblanadi (American Standard Code for
Information Interchange). Deyarli barcha kompyuter operatsion
tizimlari ASCII kodini qo'llab-quvvatlaydi.

29
C++ dasturlarida ishlatiladigan o'zgaruvchilarning asosiy tiplari
3.1-jadvalda keltirilgan. Shuningdek, u ko'rsatilgan tipdagi
o'zgaruvchilarning odatiy o'lchamlarini va ushbu o'zgaruvchilarda
saqlanishi mumkin bo'lgan chegara qiymatlarini ko'rsatadi. Siz 3.1-
Listingda keltirilgan dasturning natijalarini 3.1- jadval bilan
taqqoslashingiz mumkin.
Turi Hajmi, bayt Qiymati
bool 1 true yoki false
unsigned short int 2 0…..65535
short int 2 -32768…..32767
unsigned long int 4 0….4294967295
long int 4 -2147483648….2147483647
int(16ta son) 2 -32768…..32767
int(32ta son) 4 -2147483648….2147483647
unsigned int(16ta son) 2 0…..65535
unsigned int(32ta son) 4 0….4294967295
char 1 256ta belgilar qiymati
float 4 1,2e38………3,4e38
double 8 2,2e308……..1,8e308
3.1- jadval. O'zgaruvchilar tiplari

ESLATMA: Kompilyator versiyasiga va kompyuter rusumiga


qarab, o'zgaruvchilarning o'lchamlari 3.1- jadvalda ko'rsatilganlardan
farq qilishi mumkin. Agar sizning kompyuteringizda olingan natijalar
3.1 Listingidan keyin berilgan natijalar bilan bir xil bo'lsa, unda 3.1-
jadval kompyuteringizga tegishli.

O'ZGARUVCHINI NOMLASH
O'zgaruvchini yaratish yoki nomlash uchun siz uning tipini
o‘zlashtirishingiz kerak, undan keyin (bir yoki bir nechta bo‘sh
joylardan keyin) o‘zgaruvchi nomi nuqta-vergul bilan tugashi kerak.
O'zgaruvchining nomi uchun deyarli har qanday harf birikmasidan
foydalanish mumkin, ammo unda bo'sh joy bo'lmasligi kerak, masalan:
x, J23qrsnf va myAge. O'zgaruvchilarni baholashga imkon beradigan
ismlar yaxshi deb hisoblanadi, chunki yaxshi tanlangan o‘zgaruvchi
nomi umuman dasturning ishlashini tushunishni osonlashtirishi

30
mumkin. Quyidagi ifoda myAge nomli butun son o'zgaruvchisini
aniqlaydi: int myAge;
ESLATMA: O'zgaruvchini e'lon qilganda, unga xotira ajratiladi
(zaxiralanadi).
Professional dasturchilar j23qrsnf kabi o'qib bo'lmaydigan
o'zgaruvchi nomlardan foydalanishmaydi, bir harfli o'zgaruvchilar
(masalan, x yoki i) faqat takrorlash hisoblagichlari kabi vaqtinchalik
o'zgaruvchilar uchun ishlatiladi. MyAge yoki howMany kabi iloji
boricha ma'lumotli nomlardan foydalanishga harakat qiling. Bunday
ismlar, hatto vaqt o'tgach ham, ma'lum bir dastur satrlarini
yozganingizda nimani nazarda tutganingizni eslab qolishingizga
yordam beradi.
Keyingi dasturni ko‘rib chiqing. Dasturning dastlabki besh
qatoriga asoslanib, quyida e'lon qilingan o'zgaruvchilar nima uchun
ekanligini taxmin qilishga harakat qiling.
1-misol:
int main()
{
unsigned short x;
unsigned short y;
unsigned short z;
Z = * Y;
return 0;
}
2-misol:
int main ()
{
unsigned short Width;
unsigned short Length;
unsigned short Area;
Area = Width • Length;
return 0;
}
Shubhasiz, ikkinchi misolda o'zgaruvchilarni o‘zlashtirish haqida
tasavvur qilish osonroq, chunki siz u yoki bu o'zgaruvchining nima
uchun mo'ljallanganligi haqida bosh qotirishingiz shart emas.
HARFLARNING KATTA-KICHIKLIGIGA SEZGIRLIK
C++ tili harflarga sezgir. Boshqacha qilib aytganda, katta va kichik
harflar har xil harflar deb hisoblanadi. Age, Age va AGE nomli
o'zgaruvchilar uch xil o'zgaruvchi sifatida qaraladi.
Ko'pgina dasturchilar o’zgaruvchi nomlarni faqat kichik harflar
bilan yozishni afzal ko'rishadi. Agar nom uchun ikkita so'z kerak bo'lsa
31
(masalan, mening mashinam), unda eng mashhur konvensiyalar my_car
yoki myCar variantlaridan foydalanadi.
ESLATMA: Ko'pgina professional dasturchilar Venger
o'zgaruvchini nomlash uslubini qo'llaydilar. G'oya shundan iboratki,
har bir o'zgaruvchida uning tipini ko'rsatadigan prefiks bo‘lishi kerak.
Shunday qilib, butun tipdagi o'zgaruvchilarining nomlari (int tipi)
kichik harf bilan boshlanishi kerak. Tegishli prefikslar konstantalar,
global o'zgaruvchilar, ko'rsatkichlar va boshqa obyektlar bilan
belgilanishi kerak. Biroq, bu C++ dasturiga qaraganda C tilida
dasturlashda muhimroq, chunki bu nostandart tiplarni yoki
foydalanuvchi tomonidan belgilangan tiplarni yaratishni qo'llab-
quvvatlaydi.
KALIT SO’ZLAR
Ba’zi so'zlar dastlab C++ tilida saqlangan va shuning uchun ularni
o‘zgaruvchi nomlari sifatida ishlatib bo'lmaydi. Bunday so'zlar
deb ataladi va kompilyator tomonidan dasturni boshqarish uchun
ishlatiladi. Bularga if, while, for va main kabilar kiradi.
Tavsiya etiladi!
 O’zgaruvchini aniqlashda nomdan oldin o'zgaruvchining
tipini ko'rsating.
 O'zgaruvchilar uchun ma'lumot beruvchi nomlardan
foydalaning.
 C++ tilida katta va kichik harflar farq qilishini unutmang.
 Kompyuteringizdagi har bir o'zgaruvchining xotira tipi
qancha baytni egallashini va ushbu tipdagi o'zgaruvchilarda qanday
qiymatlarni saqlash mumkinligini aniqlang.
Tavsiya etilmaydi!
 Ishorasiz o'zgaruvchilarga manfiy sonlarni bermang.
 Kalit so'zlarni o’zgaruvchi nomlar sifatida ishlatmang.
BITTA TIPLI BIR NECHTA O'ZGARUVCHILARINI
YARATISH
C++ tilida dastur satrida bir vaqtning o'zida bir xil tipdagi bir
nechta o'zgaruvchilarni yaratish imkoniyati mavjud. Buning uchun
vergul bilan ajratilgan o‘zgaruvchi nomlar Listingi keltirilgan tipni
ko'rsating. Masalan:
unsigned int myAge, myWeight; // unsigned int tipidagi o'zgaruvchilar
long int area, width, length; // Long int tipidagi o'zgaruvchi

32
Ushbu misolda ikkala o'zgaruvchi, myAge va myWeight, ishorasiz
butun sonlar deb e'lon qilinadi. Ikkinchi qatorda area, width va length
nomli uchta o'zgaruvchi e'lon qilinadi. Ushbu o'zgaruvchilarning
barchasiga bir xil tipdagi (long) berilgan, shuning uchun
o'zgaruvchilarni aniqlashning bir qatorida har xil tiplarni aralashtirish
mumkin emas.
O'ZGARUVCHILARGA QIYMATLARNI
O‘ZLASHTIRISH
Shu maqsadda o‘zlashtirish operatori (=) ishlatiladi. Shunday qilib,
width o'zgaruvchisiga 5 sonini berish uchun quyidagilarni yozing:
Unsigned short Width;
Width = 5;
ESLATMA: Long tipi - long int tipining qisqartirilgan nomi, short
- short int tipining qisqartirilgan nomi.
Misol sifatida width o'zgaruvchisini quyidagicha ishga tushirish
mumkin:
unsigned short Width = 5; //initsializatsiya
o‘zlashtirishga o'xshaydi, ayniqsa butun
o'zgaruvchilari ishga tushirilganda. Quyida, konstantalarni ko'rib
chiqayotganda, ba'zi qiymatlarni ishga tushirish kerakligini bilib olasiz,
chunki ularga nisbatan o‘zlashtirish amalini bajarish mumkin emas.
Bir vaqtning o'zida bir nechta o'zgaruvchini aniqlash mumkin
bo'lganidek, ularni yaratishda bir vaqtning o'zida bir nechta
o'zgaruvchini initsializatsiya qilish mumkin. Masalan:
// long turdagi ikkita o'zgaruvchi va ularni ishga tushirish
long width = 5, length = 7;
Ushbu misolda Long int tipidagi kenglik o'zgaruvchisi 5 qiymati
va shu tipdagi uzunlik o'zgaruvchisi 7 qiymati bilan initsializatsiya
qilinadi. Bitta satrda bir nechta o'zgaruvchini aniqlashda ulardan faqat
bir nechtasini ham initsializatsiya qilish mumkin:
int myAge = 39, yourAge, hisAge = 40;
Ushbu misolda int tipidagi uchta o'zgaruvchi yaratiladi va faqat
birinchi va uchinchi o'zgaruvchilar initsializatsiya qilinadi.
Listing 3.2 da kompilyatsiya qilishga to'liq tayyor dastur
keltirilgan. U to'rtburchakning maydonini hisoblab chiqadi, shundan
so'ng natija ekranda ko'rsatiladi.

33
Listing 3.2. O'zgaruvchilardan foydalanish
1 #include <iostream>
2 using namespace std;
3 int main()
4{
5 unsigned short int Width = 5, Length;
6 Length = 10;
7 // ishorasiz qisqa turdagi maydon o'zgaruvchisi
8 // ko'paytirish natijasi
9 unsigned short int Area = (Width * Length);
10 cout << "Width:" << Width << "\n";
11 cout << "Length: " << Length << endl;
12 cout << "Area: " << Area << endl;
13 return 0;
14 }
Natija:
Width:5
Length: 10
Area: 50
Tahlil:
2-qatorda cout chiqarish obyektining ishlashini ta'minlaydigan
iostream kutubxonasini o'z ichiga olgan preprotsessor e’loni mavjud.
Aslida, dastur o'z ishini 4-qatorda boshlaydi.
6-qatorda width o'zgaruvchisi ishorasiz short int kabi qiymatni
saqlash uchun aniqlanadi va bu o'zgaruvchini 5 soni bilan
initsializatsiya amalga oshiriladi. 7-qatorda Length o'zgaruvchisiga 10
qiymat beriladi.
11-qatorda ishorasiz short int tipidagi maydon o'zgaruvchisi
aniqlanadi, u kenglik va uzunlik o'zgaruvchilarining qiymatlarini
ko'paytirish natijasida olingan qiymat bilan boshlanadi. 11-13
qatorlarda dasturning barcha o'zgaruvchilarining qiymatlari ekranda
ko'rsatiladi. E'tibor bering, yangi qator uchun maxsus endl ifodasi
ishlatiladi.
TYPEDEF KALIT SO'ZI
Ba'zan unsigned short int kabi kalit so'zlarni qayta-qayta yozish
zerikarli bo'lishi mumkin. C++ tilida kalit so'zidan foydalanib,
ushbu ifoda uchun taxallus (psevdonim) yaratish imkoniyati mavjud,
bu tipni aniqlashni anglatadi.
Taxallusni yaratishda uni yangi tipni yaratishdan farqlash kerak.
Ma'lumotlar tipi taxallusini yaratish uchun avval typedef kalit so'zi,
so'ngra mavjud tipi yoziladi, undan keyin yangi nom va nuqta-vergul
belgisi yoziladi. Masalan, qatorni bajarayotganda
34
typedef unsigned short int USHORT;
USHORT yangi nomi yaratilmoqda, uni unsigned short int tipidagi
o'zgaruvchini aniqlash kerak bo'lgan joyda ishlatish mumkin. 3.3
Listingi unsigned short int so'zlari o'rniga USHORT taxallusidan
foydalangan holda 3.2 Listingini o'zgartiradi.
Listing 3.3. Typedef yordamida tipni aniqlashga misol
1 #include <iostream>
2 using namespace std;
3 typedef unsigned short int USHORT;
4 int main()
5{
6 USHORT Width = 5:
7 USHORT Length;
8 Length = 10:
9 USHORT Area = Width • Length;
10 cout << "Width:" << Width << "\n":
11 cout << "Longth: " << Length << end1;
12 cout << "Area: " << Area << endl;
13 return 0;
14 }
Natija:
Width:5
Length: 10
Area: 50
Tahlil:
4-qatorda typedef kalit so'zidan foydalangan holda USHORT
identifikatori ishorasiz short int tipidagi taxallus sifatida aniqlanadi.
Shunday qilib, ushbu dastur 3.2 Listingida keltirilgan avvalgisiga
o'xshaydi va ikkala dasturning natijalari bir-biriga mos keladi.
QANDAY HOLLARDA SHORT VA INT TIPLARIDAN
FOYDALANISH KERAK?
Ayrim dasturchilar uchun o'zgaruvchini long tipi va short tipi
yordamida qachon e'lon qilish to'g'risida qaror qabul qilish ko'pincha
qiyin. Qoida juda oddiy: agar sizning qiymatingiz mo'ljallangan tip
uchun juda katta bo‘lishi uchun eng kichik imkoniyat bo'lsa, long
tipidan foydalaning.
3.1-jadvalda keltirilganidek, unsigned short int turidagi
o'zgaruvchilar odatda ikki baytga teng va 65535 dan oshmaydigan
qiymatni saqlashi mumkin. Signed short int sonlar o'z diapazonini
musbat va manfiy sonlar o'rtasida taqsimlaydi, shuning uchun ularning
maksimal qiymati unsigned short int ning yarmiga teng.

35
Unsigned long int tipidagi o'zgaruvchilar juda katta sonni (4 294
967 295) saqlashi mumkin. Agar siz undan ham ko'proq sonlar bilan
ishlashingiz kerak bo'lsa, siz float yoki double tiplaridan foydalanishga
o'tishingiz kerak bo'ladi. Float va double tipidagi o'zgaruvchilar juda
katta sonlarni saqlashi mumkin, ammo aksariyat kompyuterlarda faqat
dastlabki 7 yoki 19 sonlar muhim bo'lib qoladi, ya'ni belgilangan sonlar
sonidan keyin son yaxlitlanadi. Short tipidagi o'zgaruvchilaridan
foydalanilganda esa xotira tejaladi.
ISHORASIZ BUTUN SONLAR QIYMATLARINING
TO‘LISHI
Agar Unsigned long int lardan foydalanganda ularning maksimal
chegarasidan oshib ketsangiz nima bo'ladi?
Unsigned int son maksimal qiymatiga yetganda, keyingi o'sish
bilan u nolga qaytariladi. 3.4- Listingida short tipdagi o'zgaruvchiga
qiymat to‘lishi ko‘rsatilgan.
Listing 3.4. Unsigned int qiymatlarining birga ortishiga misol.
1 #include <iostream>
2 using namespace std;
3 int main()
4{
5 unsigned short int smallNumber;
6 smallNumber = 65535;
7 cout << "small number:" << smallNumber << endl;
8 smallNumber++;
9 cout << "small number:" << smallNumber << endl;
10 smallNumber++;
11 cout << "small number:" << smallNumber << endl;
12 return 0;
13 }
Natija :
small number: 65535
small number:0
small number:1
Tahlil:
4-qatorda unsigned short int tipidagi smallNumber o'zgaruvchisi
e'lon qilinadi, bu kompyuterda 0 dan 65535 gacha bo'lgan qiymatni
saqlashga qodir bo'lgan ikki baytli o‘zgaruvchidir. 5-qatorda
smallNumber o'zgaruvchisiga maksimal qiymat beriladi, u 6-qatorda
ekranda ko'rsatiladi. 7-qatorda smallnumber o'zgaruvchisi 1 ga
ko'payadi. O'sish (++) orqali, ya`ni inkrement operatori yordamida
amalga oshiriladi. Shu bilan birga, unsigned short int o'zgaruvchisi

36
65535 dan katta sonni saqlay olmaydi, shuning uchun uning qiymati 0
ga qaytariladi, bu 8-qatorda ko'rsatiladi.
9-qatorda smallNumber o'zgaruvchisi yana bittaga ko'payadi,
shundan so'ng uning yangi qiymati ekranda ko'rsatiladi.
Ishorali butun sonlar ishorasiz butunlardan farq qiladi. Maksimal
musbat qiymatdan oshib ketganda, o'zgaruvchi minimal manfiy
qiymatni oladi. 3.5 Listingi short int tipidagi o'zgaruvchida saqlangan
maksimal musbat songa birlik qo'shilganda nima sodir bo‘lishini
ko'rsatadi.
Listing 3.5. Signed int qiymatlarining to‘lishi.
1 #include <iostream>
2 using namespace std;
3 int main(){
4 short int smallNumber;
5 smallNumber = 32767;
6 cout << "small number:" << smallNumber << endl;
7 smallNumber++;
8 cout << "small number:" << smallNumber << endl;
9 smallNumber++;
10 cout << "small number:" << smallNumber << endl;
11 return 0;
12 }
Natija:
small number: 32767
small number:-32768
small number:-32767
Tahlil:
4-qatorda smallNumber o'zgaruvchisi short int tipi bilan e'lon
qilinadi. Ushbu dastur avvalgisi bilan bir xil amallarni bajaradi, ammo
butunlay boshqa natijalar ekranda ko'rsatiladi.
Ushbu misol shuni ko'rsatadiki, ishorali maksimal musbat butun
ko'paygan taqdirda, nol qiymat (unsigned int bo'lgani kabi) emas, balki
minimal manfiy son olinadi.
O‘ZGARMASLAR
O'zgaruvchilar kabi, ham ma'lumotlarni saqlash uchun
mo'ljallangan xotira kataklaridir. Ammo, o'zgaruvchilardan farqli
o'laroq, konstantalar o'zgarmaydi (ismning o'zi aytganidek-o‘zgarmas).
C++ tilida ikki xil o‘zgarmas mavjud: literal va belgili.
-bu dasturning o'zida to'g'ridan-to'g'ri kiritilgan
qiymat. Masalan,
int myAge = 39;

37
ifodada myAge int tipidagi o'zgaruvchidir, bir soni 39 literal
o‘zgarmasdir. O‘zgarmas 39 ga hech qanday qiymat berolmaysiz.
-bu nom bilan ifodalangan o‘zgarmas. Biroq,
o'zgaruvchidan farqli o'laroq, boshlang'ich konstantaning qiymatini
o'zgartirish mumkin emas.
Agar sizning dasturingizda talabalar deb nomlangan bitta butun
o'zgaruvchisi bo'lsa, siz maktabda qancha sinf borligini va har bir sinfda
qancha o'quvchi borligini bilish sharti bilan maktab o'quvchilarining
umumiy sonini hisoblashingiz mumkin (aytaylik, har bir sinf 15
o'quvchidan iborat):
talabalar = sinflar * 15;
ESLATMA: “*” belgisi ko'paytirishni anglatadi.
Ushbu misolda 15 soni literal o‘zgarmasdir. Ammo agar ushbu
so'zma-so'z o‘zgarmas belgi bilan almashtirilsa, kelajakda sizning
dasturingizni o'qish va o'zgartirish osonroq bo'ladi:
students = classes * studentsPerClass;
Agar siz keyinchalik har bir sinfdagi o'quvchilar sonini
o'zgartirishingiz kerak bo'lsa, buni studentsPerClass o‘zgarmasi
aniqlangan dastur qatorida bir marta qilishingiz mumkin.
#DEFINE E`LONI BILAN O‘ZGARMASLARNI
ANIQLASH
An'anaviy tarzda o‘zgarmasni aniqlash uchun quyidagi ifodani
kiriting:
#define studentsPerClass 15;
Shuni esda tutingki, studentsPerClass o‘zgarmasi o'ziga xos tipga
ega emas (int, char va boshqalar). #Define e’loni oddiy matnni
almashtirishni amalga oshiradi. Har safar preprotsessor
studentsPerClass so'ziga duch kelganda, uni 15 bilan almashtiradi.
CONST KALIT SO'ZI BILAN O‘ZGARMASLARNI
ANIQLASH
#Define e’loni o'z vazifalarini bajarayotgan bo‘lsada, C++ da
konstantalarni aniqlashning yangi, qulayroq usuli mavjud:
const unsigned short int studentsPerClass = 15;
Ushbu misolda studentsPerClass deb nomlangan ishorali
o‘zgarmas e'lon qilinadi, ammo bu safar ushbu o‘zgarmas uchun
unsigned short int tipi aniqlanadi. Ushbu o‘zgarmas va oldingi (#define

38
e’loni bilan e'lon qilingan) o'rtasidagi eng muhim farq shundaki, u tipga
ega va kompilyatorda uning ishlatilishi maqsadga muvofiq.
ESLATMA: Dastur davomida konstantalarni o'zgartirish mumkin
emas. Agar o'zgartirish kerak bo'lsa, masalan, studentsPerClass
konstantalari, siz dasturdagi tegishli o'zgartirish kiritishingiz va uni
qayta kompilyatsiya qilishingiz kerak.
Tavsiya etiladi!
 O'zgaruvchilarning qiymatlari ruxsat etilgan chegaradan
oshmasligiga ishonch hosil qiling.
 O'zgaruvchilarga ularning maqsadlarini aks ettiruvchi
mazmunli nomlar bering.
 Kompyuter xotirasini yanada samarali boshqarish uchun
short va long tiplardan foydalaning.
Tavsiya etilmaydi!
 Kalit so'zlarni o’zgaruvchi nomlar sifatida ishlatmang.
ENUM O‘ZGARMASLARI
yangi ma'lumotlar tipini yaratishga imkon beradi va keyin
qiymatlari o‘zgarmas qiymatlar to'plami bilan cheklangan ushbu
tipdagi o'zgaruvchilarni aniqlaydi. Masalan, siz rangni ro‘yxat sifatida
e'lon qilishingiz va buning uchun beshta qiymatni o‘zlashtirishingiz
mumkin: qizil, ko'k, yashil, oq va qora.
Enum kalit so'zidan keyin tip nomi, figurali qavsni ochish, vergul
bilan ajratilgan o‘zgarmas qiymatlar ro‘yxati, figurali qavsni yopish va
nuqta-vergul bilan yoziladi.
Masalan: enum COLOR { qizil, kok, yashil, oq, qora };
Ushbu ifoda ikkita vazifani bajaradi.
1.Yangi tipdagi COLOR nomli ro‘yxat yaratiladi.
2. Belgilar konstantalari aniqlanadi: 0 qiymati bilan qizil; 1 qiymati
bilan ko'k; 2 qiymati bilan yashil va boshqalar.
Har bir enum konstantasi ma'lum bir butun son qiymatiga to'g'ri
keladi. Birinchi indeks 0 qiymati bilan boshlanadi va har bir keyingi
qiymat avvalgisidan kattaroq bo'ladi. Biroq, har qanday o‘zgarmasni
ixtiyoriy qiymat bilan boshlash mumkin, bu holda aniq boshlanmagan
konstantalar ortib borayotgan ketma-ketlikni davom ettiradi va ularning
oldidagi qiymatni mos yozuvlar sifatida oladi. Agar
enum Color { RED=100, BLUE, GREEN=500, WHITE, BLACK=700
};

39
bo‘lsa, qizil o‘zgarmas 100 qiymati ega bo'ladi; moviy - 101 o‘zgarmas;
yashil - 500 o‘zgarmas; oq - 501 o‘zgarmas; qora - 700 o‘zgarmas.
Endi rang tipidagi o'zgaruvchilarni aniqlash mumkin, ammo
ularning har biriga sanab o'tilgan qiymatlardan faqat bittasi berilishi
mumkin (bu holda qizil, ko'k, yashil, oq yoki qora yoki 100, 101, 500,
501 yoki 700). Rang o'zgaruvchisiga har qanday rang qiymati berilishi
mumkin. Enum o'zgaruvchilari aslida unsigned int tipiga ega ekanligini
va berilgan enum konstantalari butun sonli o'zgaruvchilarga
o‘zlashtiringanligini tushunish muhimdir. Biroq, ba'zida ranglar,
haftaning kunlari yoki boshqa shunga o'xshash qiymatlar to'plami bilan
ishlashda ushbu qiymatlarni ism bilan nomlash yaxshi fikrdir. Listing
3.7 enum foydalanadigan dasturni taqdim etadi.
Listing 3.7. Enumdan foydalanish
1 #include <iostream>
2 using namespace std;
3 int main(){
4 enum Days { Sunday, Monday, Tuesday,
5 Wednesday, Thursday, Friday, Saturday };
6 int choice;
7 cout << "Enter a day (0-6): "
8 cin << choice;
9 if (choice = Sunday || choice == Saturday)
10 cout << "\nYou're already off on weekends!\n";
11 else
12 cout << "\n0kay, I'l1 put in the vacation day.\n";
13 return 0;
14 }
Natija:
Enter a day (0-6): 6
You' re already off on weekends!
Tahlil:
4-qatorda yettita o‘zgarmas qiymatga ega kunlar Listingi
aniqlanadi. Ularning barchasi noldan boshlab sonlarning ortib
borayotgan ketma-ketligini hosil qiladi. Shunday qilib, seshanba
qiymati 2 ga teng.
Foydalanuvchiga 0 dan 6 gacha bo'lgan qiymatni kiritish taklif
etiladi. U Sunday so'zini kirita olmaydi, chunki dastur belgilarni enum
qiymatiga o‘girishni ta'minlamaydi. Ammo siz foydalanuvchi kiritgan
qiymatni 9-qatorda ko'rsatilgandek o‘zgarmas listing qiymatlari bilan

40
taqqoslash orqali tekshirishingiz mumkin. Enumdan foydalanish
dasturni tahlil qilishni osonlashtiradi.

Listing 3.8. butun sonli const foydalanish


1 #include <iostream>
2 using namespace std;
3 int main(){
4 const int Sunday = 0;
5 const int Monday = 1;
6 const int Tuesday = 2;
7 const int Wednesday = 3;
8 const int Thursday = 4;
9 const int Friday = 5;
10 const int Saturday = 6;
11 int choice;
12 cout << "Enter a day (0-6): ";
13 cin << choice;
14 if (choice = Sunday || choice == Saturday)
15 cout << "\nYou're already off on weekends!\n";
16 else
17 cout << "\n0kay, I'll put in the vacation day.\n";
18 return 0;
19 }
Natija:
Enter a day (0-6): 6
You're already off on weekends!
Tahlil:
Ushbu dasturning natijalari Listing 3.7 dagi dastur natijalari bilan
bir xil. Ammo ushbu versiyada barcha o‘zgarmaslar (yakshanba,
dushanba va boshqalar) aniq belgilangan va kunlar listingi tipi yo'q.
Nazorat savollari topshiriqlar
1. Butun son va haqiqiy o'zgaruvchilar o'rtasidagi farq nima?
2. Unsigned short int va long int tiplari o'rtasidagi farq nima?
3. Agar enum shu tarzda berilgan bo'lsa, unda ko'k necha qiymatga
teng?
enum COLOR { WHITE, BLACK = 100, RED, BLUE, GREEN = 300
};

41
4. Quyidagi o’zgaruvchi nomlardan qaysi biri yaxshi, yomon yoki
umuman yaroqsiz deb hisoblanishi mumkin?
a) Age
b)!ex
b) R79J
D) TotalIncome
e) _Invalid

5. 3.14159 ga teng bo'lgan pi soni uchun o‘zgarmasni e'lon qiling.


6. Float tipidagi o'zgaruvchini e'lon qiling va uni pi konstantasi
yordamida ishga tushiring.

42
4-MAVZU: C++ TILINING AMALLARI. INKREMENT,
DECREMENT, SIZEOF, MANTIQIY, RAZRYADLI, TAQQOSLASH.
AMALLARNING USTUNLIKLARI VA BAJARILISH YO‘NALISHLARI
 Operatorlar
 Bloklar
 Ifodalar
 Berilgan mantiqiy shartni bajarish natijasi asosida dasturni
tarmoqlashni amalga oshirish
 C++dasturchisi nuqtai nazaridan TRUE va FALSE nima?

-bu ma'lum bir ketma-ketlikda bajariladigan buyruqlar


(ifodalar) to'plamidir. C++ tilida nuqta-vergul bilan tugaydi.
Ifodaning eng oddiy misoli sifatida qiymatni o‘zlashtirish amalini
keltirish mumkin:
x = a + b;
Algebradan farqli o'laroq, bu ifoda x ning a+b ga teng ekanligini
anglatmaydi. ushbu ifodani quyidagicha tushunish kerak: biz a va b
o'zgaruvchilar qiymatlarini yig`indisini x o'zgaruvchiga o‘zlashtiramiz
yoki x o'zgaruvchiga a+b qiymatni beramiz. Ushbu ifodada bir vaqtning
o'zida yig'indini hisoblash va qiymatni o‘zlashtirish ikkita amallari
birgalikda bajarilishiga qaramay, ifodadan keyin faqat bitta nuqta-
vergul belgisi qo‘yiladi. Operator ( = ) tenglik belgisining o'ng
tomonida joylashgan operandlarda bajarilgan amallar natijalarini uning
chap tomonidagi operandga o‘zlashtiradi.
Nafaqat bo'sh joylarni, balki yangi qatorga o‘tish belgilarini ham
o'z ichiga olgan bo‘sh joy belgilari odatda ifodalarda e'tiborga
olinmaydi. Yuqoridagi ifodani quyidagicha yozish mumkin:
x=a+b;
yoki quyidagicha:
X =a
+
b;

Bo‘sh joy belgilaridan dasturning o'qilishini yaxshilash uchun


foydalanish mumkin, bu esa u bilan ishlashni osonlashtiradi. Ammo
noto'g'ri ishlatilganda, dastur kodini butunlay chalkashtirib yuborishi

43
mumkin. Bo'sh joy belgilari ekranda va chop etishda ko'rinmaydi, faqat
matn elementlari orasidagi turli xil bo‘sh joylargina ko'rinadi.
BLOKLAR VA MURAKKAB IFODALAR
Ba'zan dasturni tushunishni osonlashtirish uchun mantiqiy o'zaro
bog'liq ifodalarni deb nomlangan komplekslarga birlashtirish
qulay. Blok ochiladigan figurali qavs ({) bilan boshlanadi va yopuvchi
figurali qavs (}) bilan tugaydi.
{
temp = a;
a = b;
b = temp;
}
Tavsiya etiladi!
 Har ochiladigan figurali qavs ishlatilganda yopiladigan
figurali qavsni ham qo‘yishni unutmang.
 Dasturdagi ifodalarni nuqta-vergul belgisi bilan tugating.
Tavsiya etilmaydi!
 Dasturingizni boshqa yo'l bilan emas, balki aniqroq qilish
uchun bo'sh joy belgilaridan oqilona foydalaning.
AMALLAR
unda ishtirok etadigan operandlar soni bo'yicha unar,
binar va ternar amallarga bo'linadi. Amal bajarilganda, qiymat
qaytariladi. Shunday qilib, 3+2 amali 5 qiymatini qaytaradi. Barcha
amallar bir vaqtning o'zida ifodalardir.
Quyidagi uchta misolni keltiraylik:
3. 2; / / 3.2 qiymatini qaytaradi
PI; / / 3.14 qiymatini qaytaradigan haqiqiy o‘zgarmas
Secondsperminute; / / 60 ni qaytaradigan butun o‘zgarmassi
Aytaylik, PI 3.14 ga teng o‘zgarmas, Secondsperminute 60 ga teng
o‘zgarmas, uchta ifoda ham amallar bo'lishi mumkin.
//Ifoda
x = a + b;
a va b o'zgaruvchilarining qiymatlarini qo'shibgina qolmay, balki
natijani x o'zgaruvchiga o‘zlashtiradi. Amallar har doim o‘zlashtirish
operatorining o'ng tomonida joylashgan:
y = x = a + b;

44
Amallar ketma-ketligi quyidagicha:
a va b ni qo'shing .
a + b natijasini x o'zgaruvchiga o‘zlashtiring.
Agar a, b va x o'zgaruvchisi butun bo'lsa, hamda a qiymati 2 ga va
b qiymati 5 ga teng bo'lsa, u holda x o'zgaruvchisiga 7 qiymat beriladi.
Ba'zi amallarni bajarish misoli Listing 4.1 da keltirilgan.
Listing 4.1. Murakkab amallar bajarilishi
1 #include <iostream>
2 using namespace std;
3 int main(){
4 int a=0, b=0, x=0, y=35;
5 cout << " a: "<<a <<" b: "<<b;
6 cout << " x: " << x << " y:" << y <<"\n";
7 a = 9;
8 b = 7;
9 y = x = a+b;
10 cout << " a: "<<a <<" b: "<<b;
11 cout << " x: " << x << " y: " << y <<"\n";
12 return 0;
13 }
Natija:
a: 0 b: 0 x: 0 y: 35
a: 9 b: 7 x: 16 y: 16
Tahlil:
4-qatorda to'rtta o'zgaruvchi e'lon qilinadi va ishga tushiriladi.
Ularning qiymatlari 5 va 6-qatorlarda ko'rsatiladi. 7-qatorda a
o'zgaruvchiga 9 qiymati beriladi. 8-qatorda b o'zgaruvchisiga 7 qiymati
beriladi. 9-qatorda a va b o'zgaruvchilarining qiymatlari qo‘shiladi va
natija x o'zgaruvchiga beriladi, x = a+b amalining natijasi, o'z
navbatida, y o'zgaruvchiga uzatiladi.
- o'zgaruvchilar va qiymatlar ustida amallarni bajarish
uchun ishlatiladigan simvol yoki simvollar to‘plamidir. Operatorlar
operandlar qiymatiga ta`sir ko‘rsatadi. C++ da operandlar alohida
harflar yoki sonli ifodalar bo‘lishi mumkin. C++ tilida asosiy to‘rt
turdagi operatorlar mavjud:
1. O‘zlashtirish (tayinlash) operatorlari;
2. Matematik operatorlar;
3. Taqqoslash operatorlari;
4. Mantiqiy operatorlar.

45
O‘ZLASHTIRISH (TAYINLASH) OPERATORI
O‘zlashtirish operatori ( = ) tenglik belgisining chap tomonida
joylashgan operand qiymatini uning o'ng tomonida hisoblangan qiymat
bilan almashtirishga imkon beradi. Shunday qilib, ifoda
x = a + b;
operandga x qiymatini belgilaydi, bu a va b o'zgaruvchilar
qiymatlarini qo'shish natijasidir.
O‘zlashtirish operatorining chap tomonida bo‘lishi mumkin
bo'lgan operand manzil operandi yoki l-qiymat (ingliz tilidan l-left,
chap operand) deyiladi. O‘zlashtirish operatorining o'ng tomonida
bo‘lishi mumkin bo'lgan operand operatsion operand yoki r-qiymat
(ingliz tilidan r-o'ng, o'ng operand) deyiladi.
O‘zgarmaslar faqat r-qiymatlari bo‘lishi mumkin, chunki dastur
davomida o‘zgarmas qiymatlarni o'zgartirish mumkin emas. Shunday
qilib, siz quyidagicha yozishingiz mumkin:
x = 35; // to'g'ri
Lekin bu xato:
35 = x; // xato!
Aytib o‘tilganidek, l-qiymat-bu o‘zlashtirish ifodasining chap
tomonida turishi mumkin bo'lgan operand va r - qiymat-bu ifodaning
o'ng tomonida turishi mumkin bo'lgan operand. E'tibor bering, barcha
1-qiymatlar r-qiymat bo‘lishi mumkin, ammo barcha r-qiymatlar 1-
qiymat bo'lmasligi mumkin. 1-qiymat bo‘lishi mumkin bo'lmagan r-
qiymatga misol literal o‘zgarmasdir. Shunday qilib, siz x=5; deb
yozishingiz mumkin, lekin 5=x; deb yozolmaysiz: (x l-qiymat
yoki r-qiymat bo‘lishi mumkin, lekin 5 faqat r-qiymat bo‘lishi
mumkin).
O‘zlashtirish operatorlari 4.1-jadvalda berilgan.
Operator Misol Izoh
= a = b; a = b;
+= a += b; a = a + b;
-= a -= b; a = a - b;
*= a *= b; a = a * b;
/= a /= b; a = a / b;
%= a %= b; a = a % b;
4.1-jadval. O‘zlashtirish operatorlari

46
MATEMATIK OPERATORLAR
C++ asosan 5 ta matematik operatordan foydalanadi: qo'shish ( +
), ayirish ( - ), ko'paytirish ( + ), butun bo'lish ( / ) va qoldiqli bo‘lish
(%).
Qo'shish va ayirish amallarini tushunish oson: ular ikkita
operandning yig'indisi yoki ayirmasini bildiradi. Shuni ta'kidlash
kerakki, ishorasiz butun sonlarni ayirishda ayirma manfiy son bo'lsa,
noto‘g`ri natijaga olib kelishi mumkin. Shunga o‘xshash Listing 4.2
bilan tanishib chiqing.
Listing 4.2. Butun sonni to‘lib qolishiga misol
1 #include <iostream>
2 using namespace std;
3 int main()
4{
5 unsigned int difference;
6 unsigned int bigNumber = 100;
7 unsigned int smallNumber = 50;
8 difference = bigNumber - smallNumber;
9 cout << "Difference is: " << difference;
10 difference = smallNumber - bigNumber;
11 cout << "\nNow difference is: " << difference <<endl;
12 return 0;
13 }
Natija:
Difference is: 50
Now difference is: 4294967246
Tahlil: Ayirish operatori 10-qatorda ishlatiladi va natija 11-
qatorda ko'rsatiladi, bu holda to‘g`ri natija chiqadi. 12-qatorda ayirish
operatori yana chaqiriladi, ammo bu safar kichik musbat sondan katta
musbat son chiqariladi. Natija manfiy bo‘lishi kerak, ammo u musbat
son sifatida hisoblanganligi (va chiqarilganligi) sababli, o'tgan darsda
aytib o'tilganidek, xotiraning to‘lib qolishi sodir bo'ladi.
BUTUN BO'LISH VA QOLDIQLI (MODULLI) BO'LISH
Butun bo'lish odatdagidan biroz farq qiladi. 21 sonini 4 soniga
(21/4) bo‘lishda, javobda 5 butun soni va qoldiq 1 chiqadi.
Qoldiqni olish uchun siz 21 sonini 4 ga qoldiqli bo‘lishingiz kerak
(21% 4), natijada biz 1 qoldig`ini olamiz.
Shunday qilib, 1% 10 ifodasining natijasi 1 ga teng; 2% 10 2 ga
teng va hokazo; va 10% 10 0 ga teng. 11% 10 bo'linishining natijasi
yana 1 ga teng; 12% 10 yana 2 ga teng va hokazo.

47
1-misol:
5 ni 3 ga bo'lganda, javob 1 ga teng.
Bir butun sonni boshqasiga bo‘lganda, natija sifatida siz ham butun
sonni olasiz. Shuning uchun 5/3=1 ga teng.
Kasrli natijani olish uchun haqiqiy sonlardan foydalanish kerak.
5.0 / 3.0 ifodasi kasrli javob beradi: 1.66667.
Turli tipni qo'shish uchun ikkita usul mavjud. Siz eski uslubdan
yoki yangi takomillashtirilgan static_cast operatoridan
foydalanishingiz mumkin. Ikkala variant ham 4.3 Listingida
ko'rsatilgan.
Listing 4.3. O'zgaruvchini float tipiga keltirish
1 #include <iostream>
2 using namespace std;
3 void intDiv(int x, int y)
4{
5 int z = x / y;
6 cout << "z: " << z << endl;
7}
8 void floatDiv(int x, int y)
9{
10 float a = (float)x; // eski uslub
11 float b = static_cast<float>(y); // zamonaviy uslub
12 float c = a / b;
13 cout << "c: " << c << endl;
14 }
15 int main()
16 {
17 int x = 5, y = 3;
18 intDiv(x,y);
19 floatDiv(x, y);
20 return 0;
21 }
Natija:
z: 1
c: 1.66667
Tahlil:
17-qatorda ikkita butun o'zgaruvchi e'lon qilinadi. 18-qatorda ular
parametrlar sifatida intDiv funksiyalari, 19 - qatorda floatDiv
funksiyalari berilgan. Ikkinchi funksiya 9-qator bilan boshlanadi. 10 va
11-qatorlarda butun qiymatlar haqiqiy turga keltiriladi va float tipidagi
o'zgaruvchilarga beriladi. Bo'linish natijasi 12-qatorda float turidagi
uchinchi o'zgaruvchiga o‘zlashtiriladi va 13-qatorda ko'rsatiladi.

48
Agar sizda myAge o'zgaruvchisi bo'lsa va uning qiymatini ikkiga
orttirmoqchi bo'lsangiz, quyidagilarni yozishingiz mumkin:
int myAge = 5;
int temp;
temp = myAge + 2; / / 5 + 2 natijani temp ga qo'ying
myAge = temp; / / yosh qiymatini yana myAgega o‘giradi
Biroq, bu usul haddan tashqari uzun. C++ tilida siz o‘zlashtirish
operatorining ikkala tomoniga bir xil o'zgaruvchini qo'yishingiz
mumkin, masalan, oldingi blok faqat bitta ifodaga qisqartiriladi:
myAge = myAge + 2;
Algebrada bu ifoda ma'nosiz deb hisoblanadi, ammo C++ tilida u
quyidagicha o'qiladi: myAge o'zgaruvchisining qiymatiga ikkini
qo'shing va natijani myAge o'zgaruvchisiga o‘zlashtiring.
Oldingi yozuvning yanada sodda versiyasi mavjud, ammo uni
o'qish qiyinroq:
myAge += 2;
(+=) ushbu o‘zlashtirish operatori r-qiymatni 1-qiymatga qo'shadi,
so'ngra natijani yana l-qiymatiga yozadi. Agar ifoda bajarilishidan oldin
myAge o'zgaruvchisi 4 qiymatga ega bo'lsa, u bajarilgandan so'ng
myAge o'zgaruvchisining qiymati 6 ga teng bo'ladi.
Yig`indi bilan o‘zlashtirish operatoridan tashqari, ayirish ( - = ),
bo'lish ( / = ), ko'paytirish (*=) va qoldiqli (modulli) bo'lish (%=)
bo'lgan o‘zlashtirish operatori ham mavjud.
INKREMENT VA DEKREMENT
Ko'pincha dasturlarda o'zgaruvchilarga birlik qo'shiladi (yoki
ayiriladi). C++ tilida qiymatni 1 ga oshirish , 1 ga kamaytirish
esa deb ataladi. Ushbu harakatlar uchun maxsus operatorlar
taqdim etiladi.
( ++ ) o'zgaruvchining qiymatini 1 ga oshiradi
va (--) uni 1 ga kamaytiradi. Shunday qilib, agar
sizda C o'zgaruvchisi bo'lsa va uni bittaga oshirmoqchi bo'lsangiz,
quyidagi ifodani ishlating:
C++; // C qiymatini birga oshirish
Xuddi shu ifodani quyidagicha yozish mumkin:
C = C + 1;
bu, o'z navbatida, ushbu ifodaga tengdir.
C + = 1;

49
Inkrement operatori ham, dekrement operatori ham ikkita variantda
ishlaydi: . Prefiks o'zgaruvchining nomidan oldin
(++myAge) va postfiks undan keyin (myAge++) yoziladi.
Oddiy ifodada foydalanish unchalik katta ahamiyatga ega emas,
ammo murakkab holda, bitta o'zgaruvchining ortishini amalga
oshirishda, so'ngra natijani boshqa o'zgaruvchiga o‘zlashtirishda bu
juda muhimdir.
Prefiks operatorining semantikasi quyidagicha: bir qiymatni
qo'shish va keyin uni o'qish. Postfiks operatorining semantikasi
boshqacha: qiymatni o'qish va keyin qiymatni 1 ga oshirish.
Agar x qiymati 5 ga teng bo'lgan butun o'zgaruvchisi bo'lsa:
int a = ++x;
ushbu operatorlar bajarilganda, kompilyator x o'zgaruvchiga 1 ni
qo'shadi (u 6 ga teng bo‘ladi) va keyin bu qiymatni a o'zgaruvchiga
o‘zlashtiradi. Shunday qilib, a va x o'zgaruvchining qiymati 6 ga teng.
Agar quyidagicha yozilsa:
int b = x++;
ular kompilyatorga o'zgaruvchining joriy qiymatini o‘zlashtirishni va
keyin o'zgaruvchiga qaytib, uni qo'shish kerakligi aytadi.
Bunday holda, b o'zgaruvchisining qiymati 6 ga tengligi
ko‘rsatiladi, ammo o'zgaruvchining qiymati allaqachon 7 ga teng.
Listing 4.4. ikkala turdagi inkrement va dekrement operatorlaridan
foydalanish ko‘rsatib o‘tilgan.
Listing 4.4. Prefiks va postfiks operatorlari
1 #include <iostream>
2 using namespace std;
3 int main(){
4 int myAge = 39;
5 int yourAge = 39;
6 cout << "I am: " << myAge << " years old.\n";
7 cout << "You are: " << yourAge << " years old\n";
8 myAge++; // postfiks inkrementi
9 ++ yourAge; / / prefiks ortishi
10 cout << "One year passes… n";
11 cout << "I am: " << myAge << " years old.\n":
12 cout << "You are: " << yourAge << " years old\n";
13 cout << "Another year passes\n";
14 cout << "I am: " << myAge++ << " years old.\n";
15 cout << "You are: " << ++yourAge << " years old\n";
16 cout << "Let's print it again.\n";
17 cout << "I am: " << myAge << " years old,\n";
18 cout << "You are: " << yourAge << " years old\n";

50
19 return 0;
20 }
Natija:
I am 39 years old
You are 39 years old
One year passes
I am 40 years old
You are 40 years old
Another year passes
I am 40 years old
You are 41 years old
Let's print it again
I am 41 years old
You are 41 years old
Tahlil:
7 va 8-qatorlarda ikkita butun o'zgaruvchi e'lon qilinadi va ularning
har biri 39 qiymati bilan boshlanadi. Ushbu o'zgaruvchilarning
qiymatlari 9 va 10-qatorlarda ko'rsatiladi.
11-qatorda myAge o'zgaruvchisi postfiks inkrement operatori
bilan, 12-qatorda esa prefiks inkrement operatori yordamida yourAge
o'zgaruvchisi qo'shiladi. Ushbu amallarning natijalari 14 va 15-
qatorlarda keltirilgan; ko'rib turganingizdek, ular bir xil (bizning
tajribamizning ikkala ishtirokchisi ham 40 yoshda).
17-qatorda myAge o'zgaruvchisi (postfiks inkrement operatori
yordamida) qo'shiladi, shu bilan birga ekranda chiqariladi. Bu yerda
operatorning postfiks formasi ishlatilganligi sababli, o'sish chiqarish
amalidan keyin amalga oshiriladi, shuning uchun 40 qiymati yana
chiqarildi. Keyin (postfiks varianti bilan taqqoslash uchun) 18-qatorda
prefiks inkrement operatori yordamida yourAge o'zgaruvchisi
qo'shiladi. Ushbu amal ekranga chiqarishdan oldin amalga oshiriladi,
shuning uchun ko'rsatilgan qiymat 41 ga teng.
Nihoyat, 20 va 21-qatorlarda xuddi shu qiymatlar yana ko'rsatiladi.
O'sish endi bajarilmaganligi sababli, myAge o'zgaruvchisining qiymati
endi 41 ga teng.
OPERATORLARNING USTUVOR YO'NALISHLARI
Savol tug`ilishi tabiiy. Qaysi amal (qo'shish yoki ko'paytirish)
birinchi bo'lib murakkab ifodada amalga oshiriladi?
Masalan:
x= 5 + 3 * 8;

51
Agar qo'shish birinchi bo'lib amalga oshirilsa, unda javob 8 * 8
yoki 64 ga teng. Agar ko'paytirish birinchi bo'lib amalga oshirilsa, unda
javob 5 + 24 yoki 29 ga teng.
Har bir operator ustuvor qiymatga ega. Ko'paytirish yig`indiga
qaraganda yuqori ustuvorlikka ega, shuning uchun bu ifodaning
qiymati 29 ga teng.
Agar ikkita matematik operator bir xil ustuvorlikka ega bo'lsa, ular
chapdan o'ngga qarab bajariladi. Shunday qilib, ifodada
x = 5 + 3 + 8 * 9 + 6 * 4;
birinchidan, ko'paytirish hisoblab chiqiladi va chapdan o'ngga:
8*9 = 72 va 6*4 = 24. Endi xuddi shu ifoda osonroq ko'rinadi:
x = 5 + 3 + 72 + 24;
Keyin yig`indi, chapdan o'ngga bajariladi: 5 + 3 = 8; 8 + 72 = 80; 80 +
24 = 104.
Biroq, barcha operatorlar ushbu tartibiga rioya qilmaydi. Masalan,
o‘zlashtirish operatorlari o'ngdan chapga hisoblanadi! Ifodani ko'rib
chiqing:
TotalSeconds = NumMinutesToThink + NumMinutesToType *60;
Aytaylik, ushbu ifodada siz NumMinutesToType
o'zgaruvchisining qiymatini 60 soniga ko'paytirmoqchi emassiz va
keyin natijani NumMinutesToThink o'zgaruvchisining qiymati bilan
qo'shishni xohlamaysiz. Daqiqalarning umumiy sonini olish uchun
avval ikkita o'zgaruvchining qiymatlarini qo'shishingiz, so'ngra bu
sonni 60 ga ko'paytirib va shu bilan soniyalarning umumiy sonini
olishingiz kerak.
Bunday holda, operatorlarning ustuvorligi bilan belgilangan
amallarni bajarish tartibini o'zgartirish uchun siz qavslardan
foydalanishingiz kerak. Qavsga olingan elementlar boshqa matematik
operatorlarga qaraganda yuqori ustuvorlikka ega. Shuning uchun, ifoda
ushbu ko‘rinishda yozilishi kerak:
TotalSeconds = (NumMinutesToThink + NumMinutesToType) * 60;
Murakkab ifodalarni yaratishda qavs qo'yish kerak bo‘lishi
mumkin. Masalan, soniyalarning umumiy sonini, so'ngra ko'rib
chiqarishga kiritilgan odamlarning umumiy sonini hisoblashingiz va
shundan keyingina bu sonlarni ko'paytirishingiz kerak:

52
TotalPersonSeconds = ( ( (NumMinutesToThink +
NumMinutesToType) * 60) * (PeopleInTheOffice +
People0nVacation) );

Ushbu murakkab ifoda ichkaridagi qavsdan boshlab o'qiladi.


Birinchidan, NumMinutesToThink o'zgaruvchisining qiymati
NumMinutesToType o'zgaruvchisining qiymatiga qo'shiladi, chunki
ular ichki qavslarda berilgan. Keyin olingan miqdor 60 ga
ko'paytiriladi. Shundan so'ng, PeopleInTheOffice o'zgaruvchisining
qiymati PeopleOnVacation o'zgaruvchisining qiymatiga qo'shiladi.
Nihoyat, hisoblangan odamlarning umumiy soni soniyalarning umumiy
soniga ko'paytiriladi.
Yuqoridagi ifodani kompyuter osonlikcha hisoblab chiqadi, ammo
bu odam uchun uni o'qish, tushunish va o'zgartirish oson degani emas.
Vaqtinchalik butun o'zgaruvchilar yordamida ushbu ifodani qayta
yozishingiz mumkin:
TotalMinutes = NumMinutesToThink + NumMinutesToType;
TotalSeconds = TotalMinutes * 60;
TotalPeople = PeopleInTheOffice + People0nVacation;
TotalPersonSeconds = TotalPeople TotalSeconds;
Ushbu variantni yozish uchun ko'proq vaqt kerak bo'ladi, ammo
tushunish ancha oson. Faqatgina ushbu dastur kodining maqsadini
tushuntirib beradigan izohlarni qo'shish va 60 sonini ishorali o‘zgarmas
bilan almashtirish qoladi. Ushbu dastur qismini o'qish va undan keyingi
foydalanish uchun deyarli ideal deb hisoblash mumkin.
Tavsiya etiladi!
 Esda tutingki, ifodalar qiymatlar bilan ishlaydi.
 O'zgaruvchini ifodada ishlatishdan oldin uni oshirish yoki
kamaytirish uchun prefiks operatoridan foydalaning (++o'zgaruvchi).
 Ifodada ishlatilgandan keyin o'zgaruvchining ko'payishi
yoki kamayishi uchun postfiks operatoridan (o'zgaruvchi++)
foydalaning.
 Ularning ustuvorliklari tufayli operatorlarni bajarish
tartibini o'zgartirish uchun qavslardan foydalaning.
Tavsiya etilmaydi!
 Juda ko'p ichki qavslardan foydalanmang, chunki bunday
ifodalarni tushunish qiyin bo'ladi.

53
C++ tilining oldingi versiyalarida mantiqiy ifodalarning natijalari
butun sonlar bilan ifodalangan, ammo yangi ANSI standartida faqat
ikkita mumkin bo'lgan qiymatga ega bo'lgan yangi-bool tipi joriy
qilingan: true yoki false.
ESLATMA: Ko'pgina kompilyatorlar ilgari bool tipiga
yo'naltirilgan bo'lib, u long int tipi bilan ichki ko'rinishda taqdim etilgan
va shuning uchun hajmi to'rt baytga teng edi. Endi ANSI-ga mos
keladigan kompilyatorlar ko'pincha bir baytli bool tipini taqdim
etadilar.
TAQQOSLASH OPERATORLARI
ikkita qiymatning tengligi yoki
tengsizligini aniqlash uchun ishlatiladi. Taqqoslash ifodalari har doim
true (true) yoki false (false) qiymatlarini qaytaradi.
ESLATMA: Yangi ANSI standarti yangi bool tipini taqdim etadi
va barcha shart operatorlari endi bool - true va false tipidagi qiymatni
qaytaradi.
Agar bitta myAge butun o'zgaruvchisi 39 qiymatini, ikkinchisi
sizning butun son o'zgaruvchingiz 40 qiymatini o'z ichiga olsa, u holda
( = = ) tenglik operatoridan foydalanib, ushbu o'zgaruvchilar teng yoki
yo'qligini bilib olishingiz mumkin:
myAge= = yourAge;
Ushbu ifoda 0 yoki false (false) ni qaytaradi, chunki taqqoslangan
o'zgaruvchilar teng emas. Ifoda myAge > yourAge;
shuningdek, 0 (yoki false) ni qaytaradi.
ESLATMA: C++ tilida dasturlashni boshlagan ko'pchilik
o‘zlashtirish operatorini (=) tenglik operatori (==) bilan almashtiradilar.
Noto'g'ri operatordan tasodifiy foydalanish aniqlash katta xatoga olib
kelishi mumkin.
Umuman olganda, C++ tilida oltita taqqoslash operatori ishlatiladi:
teng ( = = ), kichik ( < ), katta ( > ), kichik yoki teng ( < = ), katta yoki
teng (>=) va teng emas (!=). 4.1-jadvalda nafaqat barcha taqqoslash
operatorlari ro‘yxati keltirilgan, balki ulardan foydalanish misollari
ham keltirilgan.
Tavsiya etiladi!
 Esda tutingki, taqqoslash operatorlari true yoki false qiymatini
qaytaradi.

54
Tavsiya etilmaydi!
 O‘zlashtirish operatorini (=) tenglik operatori (==) bilan
almashtirmang.

Operator Nomi Misol Qiymati


== Teng 100==50; false
50==50; true
!= Teng emas 100!=50; true
50!=50; false
> Katta 100>50; true
50>50; false
>= Katta yoki teng 100>=50; true
50>=50; true
< Kichik 100<50; false
50<50; false
<= Kichik yoki teng 100<=50; false
50<=50; true
4.1-jadval. Taqqoslash operatorlari

Nazorat savollari va topshiriqlar


1. Operatorlar nima?
2. C++ tilida operatorlar nechta guruhga bo’linadi?
3. C++ tilida ifoda tushunchasi nima?
4. Inkrement nima?
5. Dekrement nima?
6. O‘zlashtirish operatorlariga misollar keltiring.
7. Quyidagi dastur natijasini topishga harakat qiling.
#include <iostream>
using namespace std;
int main() {
unsigned short int smallNumber;
smallNumber = 65535;
cout << "small number:" << smallNumber << endl;
smallNumber++;
cout << "small number:" << smallNumber << endl;
smallNumber++;
cout << "small number:" << smallNumber << endl;
return 0;
}

55
5-MAVZU. C++ KIRITISH VA CHIQARISH
OPERATORLARI VA MANTIQIY(BOOLEAN) BILAN
ISHLASH
 Kiritish operatorlari
 Chiqarish operatorlari
 Satrlar
CHIQARISH-KIRITISH OPERATORLAR BILAN
TANISHISH
C++ dasturlash tili ma'lumotlarning ekranda yoki faylda qanday
ko'rsatilishini yoki dastur tomonidan qanday o'qilishini aniq
belgilamaydi. Shunga qaramay, bu xususiyatlar dasturchi ishining
muhim qismidir, shuning uchun C++ standart kutubxonasi
kutubxonasini o'z ichiga oladi, bu kiritish- chiqarish (input-output) ni
soddalashtiradi.
ESLATMA: -bu qo'shimcha funksiyalar uchun
dasturga ulanishi mumkin bo'lgan .obj fayllari to'plami.
Iostream sinflari dastur tomonidan ekranda ko'rsatilgan
ma'lumotlarni bitma-bit ma'lumotlar operatori sifatida ko'rib chiqadi.
Oqimlardan foydalanishning asosiy maqsadlaridan biri bu
ma'lumotlarni disk yoki kompyuter displeyi bilan sinxronlashtirishdir.
Dasturning o'zi faqat ushbu jarayonlarni amalga oshiradigan operatorlar
bilan ishlaydi. Sxematik ravishda, bu g'oya 5.1-rasmda tasvirlangan.

Diskka yozish (shuningdek ekranga chiqarish) juda qimmatga


tushadi. Ma'lumotlarni diskka yozish va diskdan o'qish juda ko'p vaqt
talab etadi, bu esa dasturning bajarilishini uzoq vaqt cheklab qo'yishi
mumkin.

5.1-rasm. Oqimlar yordamida inkapsulyatsiya


56
C++ buferlangan operatorlar bilan ma'lumotlar almashinuvini
amalga oshirishda obyektga yo'naltirilgan yondashuvni qo'llaydi.
 Streambuf sinfi buferni boshqaradi, shuning uchun uning
funksiyalari buferni to‘ldirish, bo'shatish, tozalash va boshqa amallarni
bajarish imkoniyatini beradi.
 IOS sinfi chiqarish-kiritish operatorlari sinflari uchun asosiy
hisoblanadi. Streambuf obyekti ios sinfining a'zosi o'zgaruvchisi
sifatida ishlaydi.
 Istream va ostream sinflari ios sinfining hosilalari bo'lib,
mos ravishda ma'lumotlarni operator bilan kiritish va chiqarish uchun
javobgardir.
 Iosteam sinfi istream va ostream sinflarining hosilasi bo'lib,
ekranga chop etish uchun chiqarish-kiritish usullarini taqdim etadi.
 Fstream sinflari fayllardan kiritish-chiqarish uchun
ishlatiladi.
STANDART KIRITISH-CHIQARISH OBYEKTLARI
Iostream sinflarini o'z ichiga olgan dastur ishga tushirilganda to'rtta
obyekt yaratiladi va ishga tushiriladi.
ESLATMA: Iostream sinf kutubxonasi kompilyatorga o'rnatilgan.
Ushbuni dasturingizga qo'shish uchun dasturning birinchi satrlarida
#include<iostream > ifodasini yozish kifoya.
 Cin obyekti (inglizcha "see-in" dan "si-in" deb talaffuz
qilinadi) klaviatura kiritishni boshqaradi.
 Cout obyekti (inglizcha "see-out" dan "C-out" deb talaffuz
qilinadi) ekranga chiqarishni boshqaradi.
 Cerr obyekti (inglizcha "see-err" dan "C-er" deb talaffuz
qilinadi) buferlanmagan xato chiqarishini standart xato chiqarish
qurilmasiga, ya'ni ekranga o'tkazadi.
 Clog obyekti (inglizcha "See-log" dan "C-log" deb talaffuz
qilinadi) standart xato xabarlarini chiqarish qurilmasida (ekranda)
paydo bo'ladigan buferlangan xato xabarlarini qayta ishlaydi.
Ma'lumotlarni kiritish va chiqarish uchun dastur operatsion
tizimning maxsus buyruqlari bo'lgan fayllardan ham foydalanishi
mumkin.
deganda chiqadigan ma'lumotlarni qurilmaga yuborish
yoki standartdan boshqa qurilmadan ma'lumotlarni o'qish tushuniladi.

57
DOS va UNIX operatsion tizimlarida maxsus kirish (<) va chiqarish (>)
yo'naltirish operatorlari qo'llaniladi.
DOS operatsion tizimida chiqarish (>) va kiritish (<) uchun
cheklangan yo'naltirish buyruqlari to'plami mavjud. UNIX tizimining
yo'naltirish buyruqlari xilma-xildir, ammo asosiy g'oya bir xil bo'lib
qoladi: ma'lumotlar ekranda ko'rsatiladi, faylga yoziladi yoki boshqa
dasturga uzatiladi. Dasturga kirish fayllardan yoki klaviaturadan
amalga oshiriladi.
Umuman olganda, yo'naltirish iostream kutubxonalariga emas,
balki operatsion tizimning funksiyalariga ko'proq tegishli. C++ tili
to'rtta standart qurilmaga kirish va kiritish-chiqarish qurilmalarini
yo'naltirish uchun kerakli buyruqlar to'plamini taqdim etadi.

CIN YORDAMIDA MA'LUMOTLARNI CHIQARISH


ma'lumotlarni kiritish uchun javobgardir va dasturga
iostream sinfi kiritilganda mavjud bo'ladi. Oldingi misollar kiritilgan
ma'lumotlarni dastur o'zgaruvchilariga o‘zlashtirish uchun haddan
tashqari yuklangan kirish operatoridan (>>) foydalanadi. Ma'lumotlarni
kiritish uchun quyidagi sintaksis ishlatiladi:
int someVariable;
cout << "Enter a number: "
cin >> someVariable;

Avval uchinchi qatorga to'xtalamiz:


cin>> someVariable;

Cin obyektini dastur kodida e'lon qilishning hojati yo'q. Cin


obyekti cin buferida saqlangan ma'lumotlarni local someVariable
o'zgaruvchisiga yozadigan kirish operatorini ( >> ) o'z ichiga oladi.
Bundan tashqari, kirish operatori barcha asosiy tipdagi ma'lumotlarni,
ya`ni int&, short&, long&, double&, float&, char&, char+ va
boshqalarni kiritish uchun mos keladigan tarzda kompilyator cin>>
someVariable ifodasini uchratganda, kirish operatorining
someVariable o'zgaruvchisi turiga mos keladigan varianti chaqiriladi.
Yuqoridagi misolda someVariable int tipiga ega, shuning uchun
ortiqcha yuklangan funksiyaning keyingi versiyasi chaqiriladi:
istream & operator>> (int&);

58
E'tibor bering, parametr havola sifatida uzatilganligi sababli, kirish
operatori asl o'zgaruvchini o'zgartirishi mumkin. Cin dan foydalanish
Listing 5.1 da ko'rsatilgan.
Listing 5.1. Har xil tipdagi ma'lumotlarni kiritish uchun cin
operatoridan foydalanish
1 #include<iostream>
2 using namespace std;
3 int main()
4 { int myInt;
5 long myLong;
6 double myDouble;
7 float myFloat;
8 unsigned int myUnsigned;
9 cout<<"int:"; cin>>myInt;
10 cout<<"Long:"; cin>>myLong;
11 cout<<"Double:"; cin>>myDouble;
12 cout<<"Float:"; cin>>myFloat;
13 cout<<"Unsigned:"; cin>>myUnsigned;
14 cout<<"\n\nInt:\t"<<myInt<<endl;
15 cout<<"Long:\t"<<myLong<<endl;
16 cout<<"Double:\t"<<myDouble<<endl;
17 cout<<"Float:\t"<<myFloat<<endl;
18 cout<<"Unsigned:\t"<<myUnsigned<<endl;
19 return 0; }
Natija:
int:2
Long:7000
Double:987654321
Float:3.33
Unsigned:25
int:2
Long:7000
Double:9.8765e+08
Float:3
Unsigned:25
Cin obyekti, shuningdek, belgilar qatoriga ko'rsatgichni (char)
argument sifatida qabul qilishi mumkin, bu sizga belgilar buferini
yaratishga va uni cin bilan to‘ldirishga imkon beradi. Masalan, siz
quyidagilarni yozishingiz mumkin:
char YourName[50];
cout << "Enter your name;
cin >> Your Name;

59
Agar siz Jesse nomini kiritsangiz, YourName o'zgaruvchisi J, e, s,
s, e va \0 belgilar bilan to‘ldiriladi. Oxirgi belgi nol belgisi bo'ladi,
chunki cin uni avtomatik ravishda kiritadi.
SATRLARNI KIRITISHDA YUZAGA KELADIGAN
MUAMMOLAR
Cin obyekti bilan ilgari tavsiflangan barcha amallarni
muvaffaqiyatli bajarganingizdan so'ng, satrga to'liq ismni kiritishga
harakat qilsangiz, bu amalga oshirishda xatolik beradi. Gap shundaki,
cin bo‘sh joyni sukut bo'yicha berilgan satr ajratuvchi sifatida ko'rib
chiqadi. Satrda bo'sh joy aniqlangandan so'ng, satrni kiritish oxirgi nol
belgini qo'shish bilan yakunlanadi. Ushbu muammo listing 5.2 da
ko'rsatilgan.
Listing 5.2. Cin yordamida bir nechta so'zlarni kiritish
1 #include<iostream>
2 using namespace std;
3 int main()
4 { char YourName[50];
5 cout<<"Your first name:";
6 cin>>YourName;
7 cout<<"Here it is:"<<YourName<<endl;
8 cout<<"Your entire name:";
9 cin>>YourName;
10 cout<<"Here it is:"<<YourName;
11 return 0;}
Natija:
Your first name:Madina
Here it is: Madina
Your entire name: Madina Bobojonova
Here it is: Madina Bobojonova
Listing 5.3. Qiymatlar qatorini kiritish
1 #include <iostream>
2 unsigned int myUnsigned;
3 char using namespace std;
4 int main()
5 {int myInt;
6 long myLong;
7 double myDouble;
8 float myFloat;
9 myWord[50];
10 cout << "int:"; cin >> myInt;
11 cout << "Long:"; cin >> myLong;
12 cout << "Double: ";cin >> myDouble;
13 cout << "Float: ";cin >> myFloat;
14 cout << "Word: ";cin >> myWord;
15 cout << "Unsigned: ";cin >> myUnsigned;

60
16 cout <<"\n\nInt:\t" << myInt << endl;
17 cout << "Long:\t" << myLong << endl;
18 cout << "Double:\t" << myDouble << endl;
19 cout << "Float:\t" << myFloat << endl;
20 cout << "Word:\t" << myWord << endl;
21 cout << "Unsigned:\t" << myUnsigned << endl;
22 cout << "\n\nInt, Long, Double, Float, Word, Unsigned: ";
23 cin >> myInt >> myLong >> myDouble;
24 cin >> myFloat >> myWord >> myUnsigned;
25 cout << "\n\nInt:\t" << myInt << endl;
26 cout << "Long:\t" << myLong << endl;
27 cout << "Double:\t" << myDouble << endl;
28 cout << "Float:\t" << myFloat << endl;
29 cout << "Word:\t" << myWord << endl;
30 cout << "Unsigned:\t" << myUnsigned << endl;
31 return 0;}
Natija:
int:2
Long:30303
Double:393939397834
Float:3.33
Word: Hello
Unsigned:85
int:2
Long:30303
Double:393939397834
Float:3.33
Word: Hello
Unsigned:85
Int, Long, Double, Float, Word, Unsigned: 3 304938 393847473
6.66 bye -2
int:3
Long: 304938
Double:3.93939397e+08
Float:6.66
Word: bye
Unsigned:4294967294
cin istream obyekti bo'lganligi sababli, bitta kiritish amalining
natijasi quyida ko'rsatilganidek, keyingi kiritish amalining boshlanishi
bo‘lishi mumkin:
Int VarOne, varTwo, varThree;
cout << "Enter three numbers: ";
cin >> VarOne >> varTwo >> varThree;
cin >> VarOne >> varTwo >> varThree; qatorida birinchi kirish
cin >> VarOne tomonidan amalga oshiriladi, natijada istream obyekti
qaytib keladi va varTwo o'zgaruvchisiga ikkinchi qiymatni
o‘zlashtirishga imkon beradi. Bu quyidagi yozuvga teng:
61
((cin >> VarOne) >> varTwo) >> varThree;
Belgiga havolani qabul qiladigan operator >> standart kirish
moslamasidan bitta belgini o'qish uchun ishlatilishi mumkin. Buning
uchun get () a'zo funksiyasidan foydalaniladi. Bunday holda siz
parametrlarsiz get() dan foydalanishingiz yoki parametr sifatida belgi
havolasini qabul qiladigan xuddi shu funksiyaning variantidan
foydalanishingiz mumkin.

PARAMETRSIZ GET() FUNKSIYASIDAN


FOYDALANISH
Birinchidan, parametrlarsiz dan foydalanishni
ko'rib chiqing. Bunday holda, funksiya fayl oxiriga yetganda topilgan
belgi yoki EOF (faylning oxiri – end of file) qiymatini qaytaradi.
Parametrlarsiz get () funksiyasi kamdan kam qo'llaniladi.
Shunday qilib, cin.get () bir qator o'zgaruvchilarni ketma-ket ishga
tushirish uchun ishlatilmaydi, chunki funksiya tomonidan qaytarilgan
qiymat iostream obyekti emas.
Shuning uchun quyidagi yozuv ishlamaydi:
cin.get () >>myVar0ne >> myVarTwo; // xato
cin.get () > > myVarOne iostream obyekti emas, balki int tipidagi
qiymatni qaytaradi.
Listing 5.4. Parametrlarsiz get () funksiyasidan foydalanish
1 #include <iostream>
2 using namespace std;
3 int main()
4 {char ch,EOF;
5 while((ch=cin.get())!=EOF)
6 {cout<<"ch:"<<ch<<endl;}
7 cout<<"\nDone!\n";
8 return 0;}
Natija:
hello
ch:h
ch:e
ch:l
ch:l
ch:o
ch:

62
PARAMETRLI GET () FUNKSIYASIDAN FOYDALANISH
Get() funksiyasida belgi o'zgaruvchisini ko'rsatadigan parametr
o'rnatilganda, ushbu o'zgaruvchiga keyingi kirish operatori belgisi
beriladi. Bu iostream obyektini qaytaradi, bu sizga Listing 5.5 da
ko'rsatilgandek ketma-ket qiymatlarni kiritish imkonini beradi.
Listing 5.5. Parametrlar bilan get () funksiyasidan foydalanish
1 #include <iostream>
2 using namespace std;
3 int main()
4 { char a,b,c;
5 cout<<"Enter three letter:";
6 cin.get(a).get(b).get(c);
7 cout<<"a:"<<a<<"\nb:"<<b<<"\nc:"<<c<<endl;
8 return 0;}

Natija:
Enter three letter: one
a:o
b:n
c:n
Tavsiya etiladi!
 Qatordagi bo‘sh joylar bilan ajratilgan qiymatlarni kiritish
kerak bo'lganda > > kiritish operatoridan foydalaning.
 Agar siz satrning barcha belgilarini, shu gapdan bo‘sh
joylarni ketma-ket kiritishingiz kerak bo'lsa, belgi parametri bilan get()
funksiyasidan foydalaning.
STANDART SATRLARNI KIRITISH
Belgilar qatorini to‘ldirish uchun siz kirish operatoridan (>>) va
get() va funksiyalaridan foydalanishingiz mumkin.
get() funksiyasining yana bir varianti uchta parametrni oladi.
Birinchi parametr bu belgilar qatoriga ko'rsatgich, ikkinchisi avtomatik
ravishda qo'shilgan terminal nol belgisini hisobga olgan holda satrdagi
maksimal belgilar sonini bildiradi va uchinchisi satr ajratuvchi
belgilarni belgilaydi.
Agar ikkinchi parametr 20 ga teng bo'lsa, get() funksiyasi 19 ta
belgini kiritadi va birinchi parametr ko'rsatgan satrning kiritilishini
to'xtatadi, shundan so'ng u oxirgi nol belgisini qo'shadi. Uchinchi
parametr sukut bo'yicha yangi qatorga o‘tish sifatida o'rnatiladi ('\n').
Agar ushbu belgi satrning oxirgi ruxsat etilgan belgisi kiritilishidan

63
oldin uchrashsa, funksiya bu joyga terminal nol belgisini kiritadi va
keyingi kirish funksiyasi sifatida o'qiladi.
Listing 5.6. get () funksiyasidan foydalanish
1 #include <iostream>
2 using namespace std;
3 int main()
4 {char stringOne[256];
5 char stringTwo[256];
6 cout<< "Enter string one:";
7 cin.get(stringOne,256);
8 cout<<"stringOne:"<<stringOne<<endl;
9 cout<<"Enter string two:";
10 cin>>stringTwo;
11 cout<<"stringTwo:"<<stringTwo<<endl;
12 return 0;}
Natija:
Enter string one: 2
stringOne:2
Enter string two: 3
stringTwo:3
Listing 5.7. Getline () funksiyasidan foydalanish
1 #include <iostream>
2 using namespace std;
3 int main(){
4 char stringOne[256];
5 char stringTwo[256];
6 char stringThree[256];
7 cout<< "Enter string one:";
8 cin.get(stringOne,256);
9 cout<<"stringOne:"<<stringOne<<endl;
10 cout<<"Enter string two:";
11 cin>>stringTwo;
12 cout<<"stringTwo:"<<stringTwo<<endl;
13 cout<<"Enter string three:";
14 cin.get(stringThree,256);
15 cout<<"stringThree:"<<stringThree<<endl;
16 return 0; }
Natija:
Enter string one: 2
stringOne:2
Enter string two: 3
stringTwo:3
Enter string three: stringThree:
COUT YORDAMIDA MA'LUMOTLARNI CHIQARISH
Siz ilgari ni chiqarish operatori (<<) bilan birga sonlar
va boshqa ma'lumotlarni ko'rsatish uchun ishlatgansiz. Ushbu obyekt

64
shuningdek ma'lumotlarni formatlash, ustunlarni tekislash va sonli
qiymatlarni o'nlik va o'n oltilik formatda chiqarish imkonini beradi.
Siz to'g'ridan-to'g'ri flush o‘zgaruvchisining qiymatini chiqarishni
quyidagi operator orqali chaqirishingiz mumkin:
cout << flush;
Ushbu usul, agar undagi barcha ma'lumotlar ekranda
ko'rsatilmagan bo'lsa, chiqarish buferini aniq tozalashga imkon beradi.
COUT OBYEKTINING FUNKSIYA A'ZOLARI
Cin get() va getline () obyekt usullariga qanday murojaat
qilganimizga o'xshab, cout obyekti bilan put() va write ()
funksiyalaridan foydalanish mumkin.
Put () funksiyasi standart chiqarish qurilmasiga bitta belgini
chiqaradi. Ushbu funksiya ostream ga havolani qaytarganligi sababli,
cout ostream obyekti hisoblanadi, ma'lumotlarni kiritishda bo'lgani kabi
bir qator qiymatlarni chiqarish uchun put() funksiyasiga ketma-ket
murojaat qilish mumkin.

Listing 5.8. write () funksiyasidan foydalanish


1 #include<iostream>
2 #include<math.h>
3 using namespace std;
4 int main()
5 {char one[]="one if by land";
6 int fulllength=strlen(one);
7 int tooshort=fulllength-4;
8 int toolong=fulllength+6;
9 cout.write(one,tooshort)<<"\n";
10 cout.write(one,toolong)<<"\n";
11 return 0;
12 }

COUT.WIDTH() FUNKSIYASIDAN FOYDALANISH


Odatda, chiqarish maydonining kengligi avtomatik ravishda
chiqarish buferidagi barcha qator belgilarini aniq joylashtirish uchun
o'rnatiladi. Ammo funksiyasidan foydalanib, chiqarish
maydonining kengligining aniq qiymatini o‘zlashtirishingiz mumkin.
Ushbu funksiya cout obyekti funksiyasi sifatida chaqiriladi, chunki bu
uning a'zo funksiyasi. Width () funksiyasi faqat keyingi chiqarish
maydonining kengligini o'zgartiradi.

65
Listing 5.9. Chiqarish maydonining kengligini sozlash
1 #include<iostream>
2 #include<math.h>
3 using namespace std;
4 int main()
5{
6 cout<<"start>";
7 cout.width(25);
8 cout<<123<<"<end\n";
9 cout<<"start>";
10 cout.width(25);
11 cout<<123<<"<next>";
12 cout<<456<<"<end\n";
13 cout<<"start>";
14 cout.width(4);
15 cout<<123456<<"<end\n";
16 return 0;
17 }
Odatda, cout obyekti yuqoridagi misolda ko'rsatilgandek width ()
funksiyasi tomonidan berilgan bo'sh maydon pozitsiyalarini bo‘sh
joylar bilan to‘ldiradi. Biroq, ba'zida bo'sh joylarni boshqa belgilar
bilan to‘ldirish kerak bo'ladi, masalan, yulduzcha (*).
Listing 5.10. Fill () funksiyasidan foydalanish
1 #include<iostream>
2 #include<math.h>
3 using namespace std;
4 int main()
5{
6 cout<<"start>";
7 cout.width(25);
8 cout<<123<<"<end\n";
9 cout<<"start>";
10 cout.width(25);
11 cout.fill('*');
12 cout<<123<<"<end\n";
13 return 0;
14 }

66
Listing 5.11. Printf () funksiyasi
1 {
2 printf("%s","hello world\n");
3 char*phrase="hello again!\n";
4 printf("%s",phrase);
5 int x=5;
6 printf("%d\n",x);
7 char*phrasetwo="here's some values:";
8 char*phrasethree="and also these:";
9 int y=7,z=35;
10 long longvar=98456;
11 float floatvar=8.8f;
12 printf("%s %d %s %ld %f\n",phrasetwo,y,z,phrasethree,longvar,floatvar);
13 char*phrasefour="formatted";
14 printf("%s %5d %10d %10.5f\n",phrasefour,y,z,floatvar);
15 return 0;
16 }

Bu yerda nuqtaning chap tomonidagi belgilar chiqarilgan


qiymatlardagi belgilarning umumiy sonini, o'ngdagi belgilar esa kasr
sonini belgilaydi. Masalan, %5d spetsifikatori 5 ta belgidan iborat
butun sonning chiqarishini va %15.5 umumiy uzunligi 15 ta belgidan
iborat haqiqiy sonning chiqarishini belgilaydi, 5 esa kasr qismini tashkil
qiladi. Printf() dan foydalanishning turli usullari Listingi 5.11 da
ko'rsatilgan.
C++ da ma'lumotlar chiqarishini formatlash uchun siz maxsus
belgilar yoki ularning kombinatsiyalaridan foydalanishingiz mumkin.
Cout obyekti bo'lgan ifodalarda quyidagi
ishlatiladi:
\n-yangi qator;
\t-tabulyatsiya;
\\-teskari chiziq;
\ddd (sakkizlik koddagi son) - ASCII belgisi;
\a-ovozli signal (murojaat);
Satr chiqarishi ifodasi misoli:
cout <<\aAn error occured\t;
Ushbu ifoda nafaqat kompyuter ekranida xato xabarini ko'rsatadi,
balki eslatma signalini beradi va keyingi tabulyatsiya holatiga o'tadi .
Sizning e'tiboringizga iomanip.h faylini yoqishni talab qilmaydigan
manipulyatorlarning ro‘yxati keltirilgan.
flush -- chiqarish buferini tozalaydi;
endl -- yangi qatorga o‘tishni kiritadi va chiqarish buferini tozalaydi;
67
oct-chiqarilgan sonlar uchun sakkizli asosni o'rnatadi;
dec-chiqarilgan sonlar uchun o'nlik asosni o'rnatadi;
hex-chiqarilgan sonlar uchun o'n oltilik asosni o'rnatadi.
Endi biz iomanip.h ni yoqishni talab qiladigan manipulyatorlar
to'plamini beramiz.
setbase (asos) - chiqarilgan sonlar uchun asosni o'rnatadi (2 = ikkilik,
8 = sakkizlik, 10 = o'nlik, 16 = o'n oltilik);
setw (kenglik) -- chiqarish maydonining minimal kengligini belgilaydi;
setfill (belgi) - chiqarish maydonining bo'sh joylarini to‘ldirish belgisini
o'rnatadi;
setprecision (aniqlik) – haqiqiy sondagi butun sondan keyingi belgilar
sonini belgilaydi;
Masalan, satrda
cout << setw(12) << setfill (# ) << hex << x <<endl:
maydonning kengligi 12 belgidan iborat, to‘ldirish belgisi #,
chiqarilgan sonlarning sakkizli asosi o'rnatiladi, shundan so'ng x
o'zgaruvchining qiymati ko'rsatiladi, yangi qatorga o‘tish belgisi
qo'shiladi va bufer tozalanadi. Flush, endl va setw-dan tashqari barcha
manipulyatorlar, agar boshqa o'rnatishlar amalga oshirilmasa, dastur
davomida yoqilgan bo'lib qoladi. Setw manipulyatorini o'rnatish cout
obyekti bilan joriy chiqarishdan so'ng darhol bekor qilinadi.

MA'LUMOTLARNI KIRITISH VA CHIQARISH UCHUN


FAYLLARDAN FOYDALANISH
C++ operatorlari klaviatura, shuningdek ekran va diskka
chiqariladigan ma'lumotlarni qayta ishlashning usullarini ta'minlaydi.
Qanday bo'lmasin, kirish va chiqarish operatorlari yoki boshqa standart
funksiyalar va manipulyatorlardan foydalanish mumkin.
Tavsiya etiladi!
 Fayl to'g'ri ochilganligini o‘zgarmas ravishda tekshirib turing.
 Oldindan mavjud bo'lgan ifstream va ofstream obyektlarini qayta
ishlating.
 Barcha fstream obyektlarini ular bilan ishlashni tugatgandan so'ng
yoping.
Tavsiya etilmaydi!
 Cin va cout obyektlarini yopish yoki bekor qilishga urinmang.

Nazorat savollari va topshiriqlar:


68
1. Kirish operatori nima va u qanday ishlaydi?
2. Chiqarish operatori nima va u qanday ishlaydi?
3. cin funksiyasining variantlarini sanab o'ting. get () va ularning asosiy
farqlarini ko'rsating.
4. cin va getline() ni tushuntiring.
5. Chiqarish operatori yordamida uzun butun sonlarni chiqarish uchun
nima o'rnatiladi?
6. Chiqarish operatori qanday qiymatni qaytaradi?
7. Qaysi parametr ofstream obyekt konstruktori tomonidan qabul
qilinadi?
8. IOS::ate argumenti nimani o'rnatadi?
9. Iostream sinfining to'rtta standart obyekti - cin, cout, cerr clog
yordamida dastur yozing.
10. Foydalanuvchiga to'liq ismini kiritishni va keyin ushbu nomni
ekranga chiqarishni taklif qiladigan dastur yozing.
11. Dasturda argumentlarni teskari tartibda chiqaradigan dastur yozing.

69
6-MAVZU. C++ TILIDA SHART OPERATORLAR
 If operatori
 Else operatori
 Mantiqiy operatorlar
Odatda, dastur ketma-ket bajariladi. shartni tekshirishga
imkon beradi (masalan, ikkita o'zgaruvchining tengligi) va taqqoslash
natijasiga bog'liq bo'lgan boshqa kanalga yo'naltirish orqali dasturning
bajarilishini o'zgartiradi.
If operatorining eng oddiy ko‘rinishi quyidagicha:
If(shart)
ifoda;
Qavs ichidagi shart har qanday ifoda bo‘lishi mumkin, lekin odatda
munosabatlar operatorlarini o'z ichiga oladi. Agar bu ifoda noto'g'ri
bo'lsa, keyingi operator o'tkazib yuboriladi. Agar u rost qiymatini
qaytarsa, u holda operator bajariladi. Quyidagi misolni ko'rib chiqing:
if (bigNumber > smallNumber)
bigNumber = smallNumber;
Bu yerda bigNumber va smallNumber o'zgaruvchilarining
qiymatlari taqqoslanadi. Agar bigNumber o'zgaruvchisining qiymati
kattaroq bo'lsa, unda ushbu dastur parchasining ikkinchi qatorida uning
qiymati smallNumber o'zgaruvchisining qiymatiga teng bo'ladi.
Qavsga olingan ifodalar bloki bitta ifodaga teng bo'lganligi sababli,
bu xususiyat if operatori bilan satr ortida juda keng bo‘lishi mumkin
bo'lgan butun bloklardan foydalanishga imkon beradi:
if(shart)
{
ifoda1;
ifoda2;
ifoda3
}
Ifoda blokini qo'llashning oddiy misoli:
if (bigNumber > smallNumber)
{
bigNumber = smallNumber;
cout << "bigNumber: " << bigNumber << "\n";
cout << "smallNumber: " << smallNumber << "\n";
}
Bu safar, agar bigNumber o'zgaruvchisining qiymati smallNumber
o'zgaruvchisining qiymatidan katta bo'lsa, unda katta o'zgaruvchi
nafaqat kichik o'zgaruvchining qiymatiga teng o'rnatiladi, balki ekranda
satrlar ham ko'rsatiladi. Listing 6.1 munosabatlar operatorlaridan

70
foydalanishga asoslangan dastur tarmoqlanishining yana bir misolini
ko'rsatadi.
Listing 6.1. Shart operatorlari misoli
1 #include <iostream>
2 using namespace std;
3 int main(){
4 int RedSoxScore, YankeesScore;
5 cout << "Enter the score for the Red Sox: ";
6 cin >> RedSoxScore;
7 cout << "\nEnter the score for the Yankees: "
8 cin >> YankeesScore;
9 cout << " n";
10 if (RedSoxScore > YankeesScore)
11 cout << "Go Sox!\n";
12 if (RedSoxScore < YankeesScore)
13 {
14 cout << "Go Yankees!\n";
15 cout << "Happy days in New York!\n";
16 }
17 if (RedSoxScore == YankeesScore)
18 {
19 cout << "A tie? Naah, can't be.\n";
20 cout << "Give me the real score for the Yanks: ";
21 cin >> YankeesScore;
22 if (RedSoxScore > YankeesScore)
23 cout << "Knew it! Go Sox!";
24 if (YankeesScore > RedSoxScore)
25 cout << "Knew it! Go Yanks!";
26 if (YankeesScore == RedSoxScore)
27 cout << "Wow, it really was a tie!";
28 }
29 cout << "\nThanks for telling me.\n";
30 return 0;
31 }
Natija:
Enter the score for the Red Sox: 10
Enter the score for the Yankees: 10
A tie? Naah, can't be
Give me the real score for the Yanks: 8
Knew it! Go Sox!
Thanks for telling me…
Tahlil:
Ushbu dasturda foydalanuvchidan ikkita beysbol jamoasi uchun
ball hisobini kiritish so'raladi. Kiritilgan ballar butun sonli
o'zgaruvchilarda saqlanadi. Ushbu o'zgaruvchilarning qiymatlari if
operatori tomonidan 15, 18 va 24-qatorlarda taqqoslanadi.

71
ESLATMA:Ko'pgina boshlang'ich dasturchilar if ifodasi bilan
ifodalanganidan keyin beparvolik bilan nuqta-vergul qo'yadilar. Bu esa
xatolikka olib keladi.
if(SomeValue < 10);
SomeValue = 10;

Ushbu dastur parchasida SomeValue o'zgaruvchisining qiymatini


10 soni bilan taqqoslash va agar u o'ndan kichik bo'lsa, uni shu songa
tenglashtirish ko'zda tutilgan edi.
Yuqoridagi dastur parchasini boshqa yo'l bilan qayta yozish
mumkin:
if (SomeValue < 10) // tekshirish
SomeValue = 10; / / o‘zlashtirish

Keraksiz nuqta-vergulni olib tashlaganingizda, ushbu qismning


oxirgi qatori if operatori blogiga o‘tadi va dastur to‘g`ri ishlaydi.
Agar bitta jamoaning ochkolari boshqasining ochkolaridan
kattaroq bo'lsa, ekranda tegishli xabar ko'rsatiladi. Agar taqqoslangan
ballar teng bo'lsa, dastur 20-qatorda boshlanadigan va 30-qatorda
tugaydigan ifodalar blokini bajaradi. Ushbu blok yana Nyu-York
jamoasi uchun ochkolar hisobini so'raydi, shundan so'ng jamoalar
o'yinlari natijalari yana taqqoslanadi.
E'tibor bering, Agar Yankees buyrug'ining boshlang'ich hisobi Red
Sox buyrug'idan oshsa, 15-qatordagi if ifodasi false qiymatini qaytaradi
va 16-qator bajarilmaydi. 18-qatorda tekshirish haqiqiy natijani beradi
(True) va 19-qatorlardagi ifodalar bajariladi. Keyin 19-qatorda if
ifodasi yordamida ballar tengligi tekshiriladi; ushbu test natijasi
noto'g'ri (False) bo‘lishi kerak (aks holda, agar 18-qatorda tekshirish
natijasida rost bo'lsa, bunday bo‘lishi mumkin emas). Bunday holda,
dastur butun blokni o'tkazib yuboradi va darhol 31-qatorni bajarishga
o'tadi.
Ushbu misolda bitta if operatori tomonidan haqiqiy natijani olish
boshqa if operatorlari tomonidan tekshiruvlarni amalga oshirishdan
xalos qilmaydi.
O'nlab turli xil uslublar mumkin bo‘lsada, quyida keltirilgan uchta
uslub boshqalarga qaraganda tez-tez ishlatiladi.
 Dastlabki ochilish qavs shartdan keyin joylashgan bo'lib,
operator blokini tugatadigan yopish figurali qavs if operatori bilan bir
72
qatorda yoziladi:
if (shart){ifoda;}

 Figurali qavslar if so'zi ostida joylashgan bo'lib, bir qatorda


yoziladi va blok operatorlari ichiga yoziladi:
if (shart)
{Ifoda;}

 Yoki oxirgi variant:


if (shart)
{
Ifoda
}

ELSE KALIT SO'ZI


Ko'pincha dasturlarda ma'lum bir shart bajarilganda (ya'ni, ushbu
shart rost qiymatini qaytarganda) dastur bitta buyruqlar blokini
bajarishi va bajarilmasa (ya'ni, ushbu shart noto'g'ri qiymatni
qaytarganda) boshqa blokni bajarishi talab qilinadi.
Bir qator shartlarni tekshirish uchun bir nechta if ifodalarini ketma-
ket ishlatishning yuqorida ko'rsatilgan usuli juda samaralidir. Bunday
hollarda dasturning o'qilishini yaxshilash uchun siz dan
foydalanishingiz mumkin.
if (shart)
ifoda;
else
ifoda;
Listing 6.2. Else kalit so'zidan foydalanishga misol
1 #include <iostream>
2 using namespace std;
3 int main(){
4 int firstNumber, secondNumber;
5 cout << "Please enter a big number: ";
6 cin >> firstNumber;
7 cout << "\nPlease enter a smaller number: ";
8 cin >> secondNumber;
9 if (firstNumber > secondNumber)
10 cout << "\nThanks!\n";
11 else
12 cout << "\n0ops. The second is bigger!";
13 return 0;
14 }

73
Natija:
Please enter a big number: 10
Please enter a smaller number: 12
Oops. The second is bigger!
Tahlil:
11-qatorda if ifodasida ko'rsatilgan shart tekshiriladi. Agar bu shart
to'g'ri bo'lsa, 12-qator bajariladi. Agar ushbu shart noto'g'ri bo'lsa,
dastur 14-qatordan ishlashni davom ettiradi. Agar 13-qatorda else kalit
so'zi o'chirilsa, shart bajarilishidan qat'i nazar, 14-qator har qanday
holatda ham bajariladi. Ammo ushbu dasturda if-else if dan keyin blok
yoki else dan keyin blok bajariladi.
IF OPERATORI
Quyida keltirilgan.
1-misol:
if (shart)
{
ifoda;
quyidagi ifoda;
}
Agar shart rost bo'lsa, unda ifoda bajariladi va undan keyin keyingi
ifoda bajariladi. Agar shart noto'g'ri bo'lsa, unda ifoda e'tiborga
olinmaydi va dastur keyingi ifodani bajarishga o'tadi.
Esda tutingki, ifoda o'rniga figurali qavsga olingan butun blok
ishlatilishi mumkin.
2-misol:
if (shart)
ifoda1;
else
ifoda2;
boshqa ifoda;

Agar shart rost qiymatini qaytarsa, ifoda1 bajariladi, aks holda


ifoda2 bajariladi. Shundan so'ng boshqa ifoda bajariladi.
Misol:
if(SomeValue < 10);
cout << "SomeValue is less than 10";
else
cout << "SomeValue is not less than 10!";
cout << "Done," << endl;

74
ICHMA-ICH SHART OPERATORLARI
If-else blokidagi ifoda bloklaridagi har qanday operatorlardan
foydalanishda yana qo'shimcha if va else operatorlaridan foydalanishda
hech qanday cheklovlar yo'q. Bunday holda, bir nechta if operatorlari
ichma-ich joylashgan:
if (shart1)
{
if (shart2)
ifoda1;
else
{
if (shart3)
ifoda2;
else
ifoda3;
}
}
else
ifoda4;
Ushbu dasturni quyidagicha tushunish mumkin: agar shart1 to'g'ri
va shart2 to'g'ri bo'lsa, ifoda1 ni bajaring. Agar shart1 rost bo'lsa va
shart2 rost bo'lmasa, shart3 ni tekshiriladi va agar rost bo'lsa, ifoda2 ni
bajariladi. Agar shart1 to'g'ri bo'lsa va shart2 va shart3 bo'lmasa, unda
ifoda3 ni bajariladi. Nihoyat, agar shart1 noto'g'ri bo'lsa, ifoda 4
bajariladi.
Bunday murakkab loyihalashni ichma-ich if ifodalari bilan
ishlatish misoli Listing 6.3 da ko'rsatilgan.
Listing 6.3. Ichma-ich If operatorlari bilan ishlashga misol
1 #include <iostream>
2 using namespace std;
3 int main(){
4 int firstNumber, secondNumber;
5 cout << "Enter two numbers.\nFirst: ";
6 cin >> firstNumber;
7 cout << " nSecond: "
8 cin >> secondNumber;
9 cout << "\n\n";
10 if (firstNumber >= secondNumber)
11 {
12 if ( (firstNumber % secondNumber) == 0)
13 {
14 if (firstNumber == secondNumber)
15 cout << "They are the same!\n";

75
16 else
17 cout << "They are evenly divisible!\n";
18 }
19 else
20 cout << "They are not evenly divisible!\n";
21 }
22 else
23 cout << "Hey! The second one is larger!\n";
24 return 0;
25 }
Natija:
Enter two numbers.
First: 10
Second: 2
They are evenly divisible!
Tahlil:
Birinchidan, foydalanuvchidan ikkita sonni kiritish so'raladi
(navbat bilan), keyin bu sonlar taqqoslanadi. Birinchi if ifodasi bilan
(17-qatorda) biz birinchi son ikkinchisidan katta yoki teng ekanligini
tekshiramiz. Agar shart yolg`on bo'lsa, unda ifoda 29-qatorda
ko'rsatilgan else operatoridan keyin amalga oshiriladi.
Agar birinchi taqqoslash rost bo'lsa, u holda 18-qatordan
boshlanadigan ko'rsatmalar bloki bajariladi, bu yerda 19-qatordagi
ikkinchi if operatoridan foydalanib, birinchi son ikkinchisiga qoldiqsiz
bo'linishi tekshiriladi (ya'ni qoldiq nolga teng). Agar bu shart
tasdiqlansa, unda birinchi son ikkinchisiga tengligi tekshiriladi. 21-
qatordagi if operatorida sonlarning tengligi tekshiriladi va keyin
ekranda sonlar tengligi xabar paydo bo'ladi.
Agar 19-qatordagi if ifodasi false qiymatini qaytarsa, u holda 26-
qatorda else ifodasi bajariladi.
Bu quyida ko'rsatilganidek, bir nechta if operatorlarini qo‘llashda
ham amal qiladi:
if (x > y) / / agar x y dan katta bo'lsa
if (x < z) / / va agar x z dan kichik bo'lsa,
x=y; / / keyin x qiymatini y ga o‘zlashtiring
Biroq, figurali qavslardan foydalanmasdan murakkab ichma-ich
shartlarni yaratishda, qaysi ifoda if operatoriga tegishli ekanligini
aniqlash qiyin bo‘lishi mumkin.
Shuni unutmangki, bo‘sh joylar dasturchi uchun dasturni tushunarli
qiladi, ammo kompilyatorning ishlashiga ta'sir qilmaydi. Listing 6.4 da
boshqa hol ko'rsatilgan.
Listing 6.4. Else-if operatorlaridan foydalanishga misol
76
1 #include <iostream>
2 using namespace std;
3 int main(){
4 int x;
5 cout << " a number less than 10 or greater than 100: ";
6 cin >> x;
7 cout << "\n";
8 if (x >= 10)
9 if (x > 100)
10 cout << "More than 100, Thanks!\n";
11 else // ushbu operator qaysi if operatoriga tegishli
12 cout << "Less than 10, Thanks!\n";
13 return 0;
14 }
Natija:
Enter a number less than 10 or greater than 100: 20
Less than 10, Thanks!
Tahlil:
Dastur 10 dan kichik yoki 100 dan katta sonni kiritishni so'raydi va
kiritilgan qiymatni talab qilingan shartga muvofiqligini tekshirishi va
keyin xabarni chiqarishi kerak.
Agar 11-qatorda joylashgan if ifodasi rost bo'lsa, unda 12-
qatordagi ifoda bajariladi. Bizning misolimizda, agar kiritilgan son 10
dan katta bo'lsa, 11-qator bajariladi. Agar bu son 100 dan katta bo'lsa,
12-qator bajariladi.
Agar kiritilgan son 100 dan kichik bo'lsa, 11-qatordagi if ifodasi
false ni qaytaradi. Bunday holda, else (13-qator) ifodasi bajarilishi
kerak, bu esa tegishli xabarni ko'rsatadi. Ammo ma'lum bo‘lishicha,
agar siz 10 dan kichik sonni kiritsangiz, dastur shunchaki o'z ishini
tugatadi.
Kompilyator nuqtai nazaridan ushbu C++ dasturida hech qanday
xato yo'q. Dastur mantiqiy xato tufayli xohlagancha ishlamaydi.
Bundan tashqari, ushbu dasturni sinab ko'rsangiz ham, u to'g'ri
ishlayotgandek ko‘rinishi mumkin, chunki 100 dan katta sonni
kiritishda dastur normal ishlaydi va xato ko‘rinmaydi.
Listing 6.5. If operatori bilan dasturlash
1 #include <iostream>
2 using namespace std;
3 int main(){
4 int x;
5 cout << "a number less than 10 or greater than 100: ";
6 cin >> x;
7 cout << "\n";

77
8 if (x >= 10)
9{
10 if (x > 100)
11 cout << "More than 100, Thanks!\n";
12 }
13 else
14 cout << "Less than 10, Thanks!\n";
15 return 0;
16 }

Natija:
Enter a number less than 10 or greater than 100: 20
Tahlil:
11 va 14-qatorlardagi figurali qavslar orasidagi hamma narsani
bitta ifodaga aylantiradi va endi 15-qatordagi else operatori 10-qatorda
turgan if ifodasi bilan aniq bog'langan.
Foydalanuvchi 20 sonini kiritdi, shuning uchun 10-qatordagi if
ifodasi true qiymatini qaytaradi ammo, 12-qatordagi if ifodasi false ni
qaytardi, shuning uchun xabar ekranda ko'rinmadi. Agar dasturchi 13-
qatordan keyin boshqa else operatoridan foydalansa yaxshi bo'lardi, u
kiritilgan son talablarga javob bermasligi haqida xabar beradi.
MANTIQIY OPERATORLAR
Ko'pincha biz bitta shartli ifodani emas, balki bir vaqtning o'zida
bir nechtasini tekshirishimiz kerak. Masalan, x y dan kattami yoki y z
dan kichikmi? Bizning dasturimiz, tegishli harakatni amalga
oshirishdan oldin, ushbu ikkala shart ham to'g'ri yoki ulardan biri
noto'g'ri ekanligini aniqlashi kerak.
Operator Nomi Misol
&& va Ifoda1 && ifoda2
|| yoki Ifoda1 || ifoda2
! inkor ! ifoda1
Jadval 4.2. Mantiqiy operatorlar
MANTIQIY VA
ikkita ifodani hisoblab chiqadi va agar ikkala
ifoda ham rostni qaytarsa, u holda operator ham rostni qaytaradi. Agar
ochligingiz rost bo'lsa va pulingiz borligi ham rost bo'lsa,
supermarketga borib, tushlik uchun o'zingizga biror narsa sotib
olishingiz ham to‘g`ri. Masalan, mantiqiy ifoda
78
if ( (x == 5) && (y == 5) )
agar ikkala o'zgaruvchi x=5 va y=5 bo'lsa, true qiymatini qaytaradi.
Agar o'zgaruvchilardan kamida bittasi 5 ga teng bo'lmasa, ifoda false
qaytadi. E'tibor bering, ifoda faqat uning ikkala qismi ham to'g'ri bo'lsa,
rostni qaytaradi.
MANTIQIY YOKI
ikkita ifodani ham hisoblab chiqadi. Agar
ulardan biri rost bo'lsa, u holda operator yoki true-ni qaytaradi. Agar
sizda pul bo'lsa yoki kredit kartangiz bo'lsa, hisobni to'lashingiz
mumkin. Shu bilan birga, bir vaqtning o'zida ikkita shartga rioya
qilishning hojati yo'q: pul va kredit kartasiga ega bo‘lish. Ulardan birini
bajarish sizga kifoya qiladi (garchi ikkalasi birgalikda yaxshiroq bo'lsa
ham). Masalan, ifoda
if ( (x == 5) || (y == 5) )
agar x o'zgaruvchining qiymati yoki y o'zgaruvchining qiymati yoki
ikkalasi ham 5 bo'lsa, true qiymatini qaytaradi.
Iltimos, diqqat qiling: mantiqiy yoki operatori || ikkita belgi bilan
ko'rsatilgan. Bitta belgi bilan ko'rsatilgan operator mutlaqo boshqa
operator.
MANTIQIY INKOR
agar ifoda false bo'lsa (noto'g'ri qiymatga
ega bo'lsa) true qiymatini qaytaradi. Aksincha, agar sinovdan o'tgan
ifoda rost bo'lsa, inkor operatori false ni qaytaradi! Masalan, ifoda
if ( !(x == 5) )

agar x 5 soniga teng bo'lmasa, true qiymatini qaytaradi. Xuddi shu


ifodani boshqacha yozish mumkin:
if (x != 5)
Aytaylik, kompilyator quyidagi mantiqiy ifodani uchratdi:
if ( (x == 5) && (y == 5) )
Bunday holda, kompilyator avval birinchi ifodani baholaydi
(x==5) va agar u noto'g'ri bo'lsa (ya'ni x 5 soniga teng bo'lmasa), u
ikkinchi ifodani hisoblamaydi (y==5), chunki operator bilan butun
ifodaning rost bo‘lishi uchun uning ikkala sharti ham to'g'ri bo‘lishi
kerak.
Xuddi shunday, agar kompilyator yoki operatoriga duch kelsa
if ( (x == 5) || (y == 5) )

79
bu yerda birinchi ifoda to'g'ri bo'ladi (×=5), keyin kompilyator ikkinchi
ifodani ham hisoblamaydi (y = 5), chunki butun ifodani to‘g`ri deb olish
uchun bitta to‘g`ri natija yetarli.
Shart operatorlari va mantiqiy operatorlar C++ tilidagi ifodalarda
ishlatiladi va true yoki false qiymatlarini qaytaradi. Boshqa barcha
operatorlar kabi, ular ham munosabatlar operatorlarini hisoblash
tartibini belgilaydigan ma'lum bir ustuvorlik darajasiga ega. Bunday
ifodaning ma'nosini aniqlashda ushbu fikrni hisobga olish kerak
if ( x > 5 && y > 5 || z > 5)
Bunday holda, dasturchining maqsadi haqida faqat taxmin qilish
mumkin. Ehtimol, bu ifoda x va y 5 dan katta bo'lsa yoki z 5 dan katta
bo'lsa, true qiymatini qaytarishini xohlagan bo‘lishi mumkin. Boshqa
tomondan, ehtimol dasturchi bu ifodani faqat x 5 dan katta bo'lsa va y
yoki z 5 dan katta bo'lsa, to'g'ri qaytarishini xohlagan bo‘lishi mumkin.
Agar x 3 ga teng bo'lsa va y va z ikkalasi ham 10 ga teng bo'lsa, u
holda 2-taxmin uchun ushbu ifoda true qiymatini qaytaradi (z 5 dan
katta, shuning uchun biz x va y qiymatlarini e'tiborsiz qoldiramiz), lekin
birinchi talqindan foydalanganda false qiymati qaytadi (u true qiymatini
bera olmaydi, chunki bu x qiymati 5 dan katta edi va bu rostni
aniqlagandan so'ng, && operatorining o'ng tomonidagi ifodani
hisoblash natijasi muhim emas, chunki butun ifodaning rosti uchun
uning ikkala qismi ham to'g'ri bo‘lishi kerak).
Bunday ifodalarda operatorlarning ustuvorliklarini tushunish juda
qiyin, shuning uchun siz qavslardan foydalanishingiz kerak, chunki
ularning yordami bilan siz nafaqat ularning ustuvorliklari tufayli
operatorlarning ketma-ketligini o'zgartirishingiz, balki bunday
chalkash ifodalarni ham aniq qilishingiz mumkin:
if ( (x > 5) && (y > 5 || z > 5) )
Yuqoridagi qiymatlardan foydalanganda, bu ifoda false qiymatini
qaytaradi. Ma'lum bo‘lishicha, x (uning qiymati 3 ga teng) 5 dan
oshmaydi, keyin ifoda operatorning chap tomonida false ni qaytaradi va
shuning uchun butun ifoda ham false ni qaytaradi. Shuni esda tutingki,
ifodaning ikkala qismi ham trueni qaytargan taqdirdagina operator
trueni qaytaradi. Misol uchun, agar siz kiygan narsangiz haqida uni
zamonaviy deb ayta olsangiz va u sizga mos kelsa, sizning didingiz
yaxshi deb hisoblanishi mumkin.
ESLATMA: Ko'pincha, qo'shimcha qavslar faqat aniq nimani
guruhlashni xohlayotganingizni aniqlash uchun ishlatilishi kerak. Esda
80
tutingki, dasturchining maqsadi yaxshi ishlaydigan, shuningdek o'qish
va tushunish oson bo'lgan dastur yozishdir.
TRUE VA FALSE HAQIDA KO'PROQ MA'LUMOT
C++ da nol false qiymatiga teng, boshqa barcha sonli qiymatlar esa
true qiymatiga teng. Har qanday ifoda har doim muhim bo'lganligi
sababli, ko'plab dasturchilar ushbu qiymat ekvivalentligidan if
operatorining shart ifodalarida foydalanadilar. Masalan,
if (x)
// agar x nolga teng bo'lmasa, unda shart to'g'ri
x = 0;
buni quyidagicha o'qish mumkin: agar x o'zgaruvchisi nolga teng
bo'lmasa, unga nol qiymatini o‘zlashtiramiz. Ushbu ifodaning
ma'nosini yanada aniqroq qilish uchun uni quyidagicha yozishingiz
mumkin:
if (x != 0) / / agar x nol bo'lmasa
x = 0;
Ikkala ifoda ham bir xil natija qaytaradi, ammo ikkinchisi aniqroq.
Dastur o‘zgarmas mavhum bo‘lib qolmasligi uchun, ifoda nolga teng
emas, balki ba'zi mantiqiy shartlarning rostini tekshirish yaxshiroqdir.
Quyidagi ikkita ifoda ham tengdir:
if (!x)
// to'g'ri, agar x nolga teng bo'lsa
agar (x == 0) // agar nolga teng bo'lsa
Biroq, ikkinchi ifoda tushunish uchun yaxshiroqdir va juda aniq,
chunki x o'zgaruvchisining matematik qiymati aniq tekshiriladi.
Tavsiya etiladi!
 Ifodalarni bajarish tartibini aniqroq ko'rsatish yoki ularning
ustuvor yo'nalishlarini o'zgartirish uchun qavslardan foydalaning.
 Dastur qismlari o'rtasidagi munosabatlarni aniqlash va
xatolarga yo'l qo'ymaslik uchun ichma-ich if operatorlari bilan
foydalanishda figurali qavslardan foydalaning.
Tavsiya etilmaydi!
 If(x) ifodasini if(x != 0) ning o‘rniga qo‘llamang. Oxirgi
variant afzalroqdir, chunki shartni tekshirish mantig'i aniqroq ko'rinadi.
 If(!x) ifodasini if(x ==0) ifodasining ekvivalenti sifatida
ishlatmang. Oxirgi variant afzalroqdir, chunki shartni tekshirish
mantig'i aniqroq ko'rinadi.

81
TERNAR OPERATOR
bir vaqtning o'zida uchta operand bilan
ishlaydigan C++ tilidagi yagona operator. Ternar operatordan
foydalanish sintaksisi quyidagicha:
(ifoda1)? (ifoda2): (ifoda3)
Ushbu satr quyidagicha o'qiladi: agar ifoda1 true ni qaytarsa,
ifoda2 bajariladi, aks holda ifoda3 bajariladi. Odatda, qaytish qiymati
ma'lum bir o'zgaruvchiga beriladi.
Listing 6.6. Ternar operatordan foydalanishga misol
1 #include <iostream>
2 using namespace std;
3 int main(){
4 int x, y, z;
5 cout << "Enter two numbers.\n";
6 cout << "First: "
7 cin >> x;
8 cout << "\nSecond: "
9 cin >> y;
10 cout << "\n";
11 if (x > y)
12 z = x;
13 else
14 z = y;
15 cout << “z: " << z;
16 cout << "\n";
17 z = (x > y) ? x : y;
18 cout << "z: " << z;
19 cout << "\n";
20 return 0;
21 }
Natija:
Enter two numbers.
First: 5
Second: 8
z: 8
z: 8
Tahlil:
Birinchidan, uchta butun o'zgaruvchilari yaratiladi: x, y va z.
Dastlabki ikkitasining qiymatlari foydalanuvchi tomonidan kiritiladi.
Keyin 13-qatorda if buyrug'i bajariladi, bu sizga kiritilgan
qiymatlarning qaysi biri kattaroq ekanligini bilib olishga imkon beradi
va aniqlangan katta qiymat 3-o'zgaruvchiga beriladi. Ushbu qiymat 17-
qatorda ko'rsatiladi.

82
Xuddi shu tekshirish 19-qatorda shartli operator tomonidan amalga
oshiriladi va z o'zgaruvchisiga katta qiymat beradi. U quyidagicha
o'qiladi: "agar x y dan katta bo'lsa, x qiymatini qaytaring; aks
holda y qiymatini qaytaring." Qaytish qiymati z o'zgaruvchiga beriladi.
ushbu qiymat ekranda 20-qatorda ko'rsatiladi. Ko'rib turganingizdek,
ternar operatorni o'z ichiga olgan ko'rsatma if...else ko'rsatmasining
qisqaroq ekvivalentidir.
Nazorat savollari va topshiriqlar:
1. Ifoda nima?
2. Yozuv x = 5 + 7; ifodami? Uning ma'nosi nima?
3. 201 / 4 ifodasining ma'nosi nima? 201% 4 ifodasining ma'nosi nima?
4. Agar myAge, a va b o'zgaruvchilari int tipiga ega bo'lsa, unda ifoda
bajarilgandan keyin ularning qiymatlari qanday bo'ladi:
myAge = 39;
a = myAge++;
b = ++myAge;
5. if (x = 3) va if(x == 3) ifodalari o'rtasidagi farq nima?
6. Quyidagi ifodalar true yoki false ni qaytaradimi?
a) 0
b) 1
B) - 1
D) x = 0
e) x == 0 qiymatiga ega deb taxmin qiling
7. Ushbu dasturni tahlil qiling va natijani taxmin qiling:
1 #include <iostream>
2 using namespace std;
3 int main(){
4 int a = 1, b = 1, c;
5 if (c = (a-b))
6 cout << "The value of cis: " << c;
7 return 0;
8 }
8. 7-mashqdan dasturni kiriting, kompilyatsiya qiling va ishga
tushiring. Natija qanday bo'ldi? Nima uchun?

83
7-MAVZU. C++ DA TAKRORLASH OPERATORLARI

 Takrorlashlar nima va ular qanday ishlatiladi?


 Takrorlashlarni tashkil qilish usullari qanday?

Har qanday dasturning tuzilishi ko'plab takrorlashlarning


kombinatsiyasidan iborat. 6-mavzuda siz if ifodasi yordamida dasturni
tarmoqlashni qanday tashkil qilishni o'rgandingiz.
TAKRORLASHLARNI TASHKIL QILISH
Bir qator muammolarni hal qilish uchun ko'pincha bir xil
harakatlarni takroriy bajarish talab etiladi. Amalda, bu yoki
algoritmlar yordamida amalga oshiriladi. Iterativ jarayonning
mohiyati amallar ketma-ketligini kerakli marta takrorlashdir.
GOTO OPERATORINING TARIXI
Dasturlash rivojlanishning dastlabki bosqichida bo'lgan yillarda
faqat kichik dasturlar ishlatilgan. Bunday dasturlarda takrorlashlar
tabulyatsiya, buyruqlar ketma-ketligi va shartsiz o'tish operatoridan
iborat edi.
C++ da nishon , so'ngra (:) deb nomlanadi. Kerakli
nishonga o'tish uchun , so'ngra nomi ishlatiladi.
Goto operatoridan foydalanish misoli Listing 7.1 da keltirilgan.
Listing 7.1. Goto operatori
1 #include <iostream>
2 using namespace std;
3 int main()
4{
5 int counter = 0; / / hisoblagichni ishga tushirish
6 loop: counter ++;// takrorlashning boshlanishi
7 cout << "counter: " << counter << "\n";
8 if (counter < 5) / / qiymatni tekshirish
9 goto loop; // boshiga qaytish
10 cout << "Complete. Counter: " << counter << "\n";
11 return 0;
12 }
Natija:
counter: 1
counter: 2
counter: 3
counter: 4
counter: 5
Complete. Counter: 5.

84
Tahlil:
7-qatorda counter o'zgaruvchisi nol qiymat bilan ishga tushiriladi.
Loop nishoni 8-qatorda takrorlashning boshlanishi ko'rsatilgan. Har bir
iteratsiyada counter qiymati bittaga oshiriladi va ekranda ko'rsatiladi.
10-qatorda counter o'zgaruvchisining qiymati tekshiriladi. Agar u 5 dan
kichik bo'lsa, unda shart bajariladi va boshqaruv goto operatoriga
o'tkaziladi, natijada 8-qatorga o'tish amalga oshiriladi. Iterativ jarayon
counter o'zgaruvchisining qiymati 5 ga yetguncha amalga oshiriladi.
Shundan so'ng, dastur takrorlashdan tashqariga chiqadi va yakuniy
natija ekranda ko'rsatiladi.
yordamida siz dasturning istalgan nuqtasiga oldinga
yoki orqaga o'tishingiz mumkin. Goto operatori biroz murakkabroq
tuzilishga ega, ammo ko'proq imkoniyatlarga ega bo'lgan takrorlash
operatorlari bilan almashtirildi: for, while va do...while.
WHILE OPERATORI YORDAMIDA
TAKRORLASHLARNI TASHKIL QILISH
ning yordami bilan tashkil etilgan takrorlashlarda
amallar ketma-ketligini bajarish takrorlashni davom ettirish sharti to'g'ri
bo'lguncha davom etadi. Listing 7.1 dastur misolida counter
o'zgaruvchisining qiymati 5 ga teng bo'lgunga qadar oshdi. Listing 7.2
da ushbu dastur while operatori yordamida qayta yozilgan.
Listing 7.2. While operatori
1 #include <iostream>
2 using namespace std;
3 int main()
4{
5 int counter = 0;
6 while(counter < 5)
7{
8 counter++;
9 cout << " counter: " << counter << "\n";
10 }
11 cout << " Complete. Counter: " << counter << ".\n";
12 return 0;
13 }
Natija:
counter: 1
counter: 2
counter: 3
counter: 4
counter: 5
Complete. Counter: 5.

85
Tahlil:
Ushbu oddiy dastur while operatori yordamida takrorlashni tashkil
qilish misolini ko'rsatadi. Har bir iteratsiyaning boshida shart
tekshiriladi va agar u bajarilsa, boshqaruv takrorlashning birinchi
operatoriga o'tkaziladi. Bizning misolimizda loopni davom ettirish
sharti 5 dan kichik bo'lgan counter o'zgaruvchisining barcha
qiymatlarini olishdir (8-qator). Agar shart bajarilsa, takrorlashning
keyingi qadami boshlanadi. 10-qatorda sanagich qiymati bittaga oshadi
va 11-qatorda ekranda ko'rsatiladi. Hisoblagich qiymati 5 ga yetgandan
so'ng, takrorlash tanasi (8-12 qatorlar) o'tkazib yuboriladi va boshqaruv
13-qatorga o'tkaziladi.
While operatoridagi shart bo'lgan mantiqiy ifodaning murakkabligi
cheklanmagan. Bu har qanday C++ mantiqiy ifodalarini while operatori
ishlatishga imkon beradi. Ifodalarni tuzishda mantiqiy amallardan
foydalanishga ruxsat beriladi: && (mantiqiy va), || (mantiqiy yoki), !
(mantiqiy inkor). Listing 7.3 while operatorining ishlashiga boshqa
misol berilgan.
Listing 7.3. While ga doir murakkab misol
1 #include<iostream>
2 using namespace std;
3 int main(){
4 unsigned short small;
5 unsigned long large;
6 const unsigned short MAXSMALL=65535;
7 cout << "Enter a small number: ";
8 cin >> small;
9 cout << "Enter a large number: ";
10 cin >> large;
11 cout << "small: " << small <<"...";
12 while (small < large && large > 0 && small < MAXSMALL)
13 { if (small % 5000 == 0)
14 cout << ".";
15 small++;
16 large-=2;}
17 cout << "\nSmall: " << small << " Large: " << large << endl;
18 return 0;}

Natija:
Enter a small number: 2
Enter a large number: 100000
small: 2…
Small: 33335 Large: 33334

86
BREAK VA CONTINUE OPERATORLARI
Ko'pincha takrorlash tanasining barcha operatorlarini bajarish
tugashidan oldin ham takrorlashning keyingi takrorlanishiga o'tish
kerak. Buning uchun ishlatiladi.
Bundan tashqari, ba'zi hollarda, takrorlashni davom ettirish
shartlari bajarilgan bo'lsa ham, takrorlashdan tashqariga chiqarish talab
qilinadi. Bunday holda ishlatiladi.
Ushbu operatorlardan foydalanishga misol Listing 7.4 da
keltirilgan. Bu allaqachon tanish bo'lgan o'yinning biroz murakkab
versiyasi. Bunday holda, kichik va katta qiymatlardan tashqari, qadam
va berilgan qiymatni kiritish taklif etiladi. Oldingi misolda bo'lgani
kabi, takrorlashning har bir iteratsiyasida kichik o'zgaruvchining
qiymati bittaga ko'payadi. Kichik o'zgaruvchi qiymati katta
o‘zgaruvchidan kattaroq bo'lganda o'yin tugaydi. Agar katta
o'zgaruvchining qiymati berilgan qiymatga (maqsad) to'g'ri kelsa, xabar
ko'rsatiladi va o'yin to'xtatiladi.
Listing 7.4. Break continuedan foydalanish
1 #include <iostream>
2 using namespace std;
3 int main(){
4 unsigned short small;
5 unsigned long large;
6 const unsigned short MAXSMALL=65535;
7 cout<<"Enter a small number:";
8 cin>>small;
9 cout<<"Enter a large number:";
10 cin>>large;
11 cout<<"small:"<<small<<"...";
12 while (small<large&&large>0&&small<MAXSMALL)
13 { if (small%5000==0)
14 cout<<"...";
15 small++;
16 large=2;}
17 cout<<"\nSmall\:-<<-Large:-<<large<<endl";
18 return 0;}
WHILE(TRUE) OPERATORIDAN FOYDALANISH
C++ tilining sintaksisi nuqtai nazaridan to'g'ri bo'lgan har qanday
ifoda takrorlashning keyingi iteratsiyasiga o'tishda tekshirilishi
mumkin bo'lgan shart sifatida harakat qilishi mumkin. Ushbu ifoda
to'g'ri bo'lsa, takrorlash bajariladi. Cheksiz takrorlashlarni tashkil qilish
uchun bunday ifoda sifatida true mantiqiy o‘zgarmasi ishlatiladi.

87
Listing 7.5. while operatoridan foydalanish
1 #include<iostream>
2 using namespace std;
3 int main()
4 {int counter=0;
5 while(true)
6{ counter++;
7 if(counter>10)
8 break; }
9 cout<<"Counter:"<<counter<<"\n";
10 return 0; }
Natija:
Counter:11
While operatori yordamida takrorlashlarni tashkil qilishda,
takrorlash tanasi umuman bajarilmaydigan vaziyat yuzaga kelishi
mumkin. Takrorlashni davom ettirish sharti har bir iteratsiyaning
boshida tekshirilganligi sababli agar ifoda false bo'lsa, takrorlashning
bajarilishi takrorlash tanasining birinchi operatorini ishga tushirishdan
oldin to'xtatiladi.
Listing 7.6. While bilan takrorlashni tugatish
1 #include<iostream>
2 using namespace std;
3 int main() {
4 int counter;
5 cout<<"How many hellos?: ";
6 cin>>counter;
7 while(counter>0)
8 {
9 cout<<"Hello\n";
10 counter--;
11 }
12 cout<<"Counter is OutPut: "<<counter;
13 return 0; }

Natija:
How many hellos? : 2
Hello
Hello
Counter is OutPut:0
DO...WHILE TAKRORLASH OPERATORIDAN
FOYDALANISH
dan foydalanganda, takrorlash tanasi
bajarilgandan so'ng shart tekshiriladi. Bu takrorlash operatorlarini
kamida bir marta bajarilishini kafolatlaydi.

88
Listing 7.7. Do.. while operatoridan foydalanish
1 #include<iostream>
2 using namespace std;
3 int main(){
4 int counter;
5 cout<<"How many hellos?: ";
6 cin>>counter;
7 do
8 {
9 cout<<"Hello\n";
10 counter--;
11 }while(counter>0);
12 cout<<"Counter is OutPut: "<<counter;
13 return 0;}
Natija:
How many hellos? : 2
Hello
Hello
Counter is OutPut:0
Listing 7.8. While operatoridan foydalanishga yana bir misol
1 #include<iostream>
2 using namespace std;
3 int main() {
4 int counter=0;
5 while(counter<5)
6 {counter++;
7 cout<<"Looping! ";
8}
9 cout<<"\nCounter: "<<counter<<"\n";
10 return 0; }
Natija:
Looping! Looping! Looping! Looping! Looping!
Counter : 5
FOR OPERATORI
yordamida takrorlashni tashkil qilish uchun uchta
majburiy amalni bajarish kerak: takrorlash o'zgaruvchilarining
boshlang'ich qiymatlari, so'ngra har bir iteratsiyada takrorlashni davom
ettirish sharti va takrorlash o'zgaruvchisining qiymatini o'zgartirish.
Professional foydalanish bilan for operatori kuchli va
moslashuvchan dasturlash operatoriga aylanadi. For operatorining
uchta mustaqil ni (ishga tushirish, davom etish
sharti va qadam) o'rnatishga imkon berishi takrorlash ishini
boshqarishda cheksiz imkoniyatlarni ochib beradi.

89
FOR TAKRORLASHI PARAMETRLARI
For takrorlashi parametrlari sintaksisi quyidagicha:
for(initsializatsiya, shart, qadam) ifodalari;

Initsializatsiya ifodasi takrorlash hisoblagichining boshlang'ich


qiymatini o‘zlashtirish yoki takrorlash ishini tayyorlaydigan boshqa
amalni bajarish uchun ishlatiladi. Shart deganda, C++ tilida
takrorlashning har bir yangi takrorlanishidan oldin bajariladigan va
mantiqiy qiymatni qaytaradigan ma'lum bir ifoda tushuniladi. Agar true
qiymati qaytarilsa, dastur takrorlash tanasining satrlarini bajaradi,
shundan so'ng takrorlash parametrlarida uchinchi ifoda bajariladi, ya`ni
hisoblagich qiymatini belgilangan qiymatga oshiradi.
1-misol:
// salomni o'n marta chop eting
for(int i=0; i<10; i++)
cout << "Hello!" < endl;
2-misol:
for(int i = 0; i < 10; i++)
cout << "Hello!" << endl;
cout << "the value of i is: "<< i << endl;
For takrorlash operatori quyidagi ketma-ketlikda
ishlaydi:
1. Dastlabki qiymat takrorlash hisoblagichiga beriladi. (Misol
uchun, i=0)
2. Takrorlashni davom ettirish shartini belgilaydigan ifoda
qiymatlari hisoblanadi. (Misol uchun, i<10)
3. Agar shart rost qiymat qaytarsa, u holda takrorlash tanasidagi
amal bajariladi, so'ngra esa hisoblagich amali bajariladi. (Misol uchun,
i++)
Har bir iteratsiyada 2 va 3-bosqichlar takrorlanadi.
For takrorlashi operatorining sintaksisi bir nechta o'zgaruvchan
hisoblagichlarni ishga tushirishga, takrorlashni davom ettirishning
murakkab shartlarini tekshirishga yoki hisoblagichlarida ketma-ket bir
nechta amallarni bajarishga imkon beradi. Agar bir nechta
hisoblagichlarga qiymatlar berilsa yoki bir nechta amallar bajarilsa, ular
ketma-ket yoziladi va vergul bilan ajratiladi.

90
FOR TAKRORLASHINING NOL PARAMETRLARI
Har qanday for takrorlashi parametrini o'tkazib yuborish mumkin.
O'tkazib yuborish nol parametrdan foydalanishni anglatadi. Nolinchi
parametr for takrorlashining qolgan parametrlaridan nuqta-vergul (;)
belgisi bilan ajratiladi.
Listing 7.9. For takrorlashining nol parametrlari
1 #include<iostream>
2 using namespace std;
3 int main() {
4 int counter=0;
5 for(;counter<5;)
6 {counter++;
7 cout<<"Looping! ";
8}
9 cout<<"\nCounter: "<<counter<<".\n";
10 return 0;}
Natija:
Looping! Looping! Looping! Looping! Looping!
Counter : 5
BO'SH FOR TAKRORLASHLARIDAN FOYDALANISH
For operatorining sintaksisi takrorlashni tavsiflashda juda
murakkab tuzilmalardan foydalanishga imkon berganligi sababli
takrorlash tanasiga ehtiyoj ba'zan umuman yo'qoladi. Bu shuni
anglatadiki, takrorlash tanasi nuqta-vergul (;) belgisi bilan tugaydigan
bo'sh qatordan iborat bo'ladi. Ushbu belgi for operatori bilan bir qatorga
joylashtirilishi mumkin.
Listing 7.10. Bo'sh takrorlashni tashkil qilish uchun operatordan
foydalanish
1 #include <iostream>
2 using namespace std;
3 int main(){
4 for (int i = 0; i<5; cout << "i: " << i++ << endl);
5 return 0;}
Natija:
i: 0
i: 1
i: 2
i: 3
i: 4

91
ICHKI TAKRORLASHLAR
Boshqa takrorlashning tanasida tashkil etilgan takrorlash
deyiladi. Bunday holda, ichki takrorlash tashqi
takrorlashning har bir iteratsiyasida to'liq bajariladi.
Listing 7.11. Ichki takrorlashlar
1 #include <iostream>
2 using namespace std;
3 int main(){
4 int rows, columns;
5 char theChar;
6 cout << "How many rows? "; cin >>rows;
7 cout << "How many columns? "; cin >> columns;
8 cout << "What character? "; cin >> theChar;
9 for (int i = 0; i<rows; i++)
10 { for (int j = 0; j<columns; j++)
11 cout << theChar;
12 cout << "\n";}
13 return 0;}
Natija:
How many rows? 4
How many columns? 12
What character? X
xxxxxxxxxxxx
xxxxxxxxxxxx
xxxxxxxxxxxx
xxxxxxxxxxxx
FOR TAKRORLASHLARINING O'ZGARUVCHAN
HISOBLAGICHLARI DOIRASI
ANSI tomonidan o'rnatilgan yangi standartga ko'ra, bunday
takrorlashda e`lon qilingan o'zgaruvchilar doirasi faqat takrorlash
tanasida amal qilishi kerak. Quyidagi dastur kodini yozib,
kompilyatoringizni yangi standartga muvofiqligini tekshirishingiz
mumkin.
1 #include <iostream>
2 using namespace std;
3 int main()
4{
5 // i o'zgaruvchining ko'lamini tekshirish
6 for (int i = 0; i<5; i++)
7{
8 cout << "i: " << i << endl;
9}
10 i = 7; // i doiradan tashqarida
11 return 0;
12 }

92
Yangi standartga mos keladigan kompilyatorlar i = 7 ifodasi uchun
xato xabari qaytarishi kerak. Ba'zi o'zgarishlar kiritilgandan so'ng,
dastur barcha kompilyatorlar tomonidan xatosiz ishlaydi.
1 #include <iostream>
2 using namespace std;
3 int main(){
4 int i; //sikldan tashqarida o'zgaruvchi
5 for (int i = 0; i<5; i++)
6 {cout << "i: " << i << end1;}
7 i = 7; // endi xatolik mavjud emas
8 return 0;}
Fibonachchi seriyasining n-chi hadi (n-1)-chi va (n-2)-chi hadlarini
qo'shish orqali hisoblanadi. Ushbu muammoni takrorlashlar yordamida
hal qilishni ko'rib chiqamiz.
Listing 7.12. Fibonachchi ketma-ketligining 1-hadini topish.
1 #include <iostream>
2 using namespace std;
3 int fib(int position);
4 int main(){
5 int answer, position;
6 cout << "Which position? ";
7 cin >> position;
8 cout << "\n";
9 answer = fib(position);
10 cout << answer << " is the ";
11 cout << position << " Fibonacci number.\n";
12 return 0;}
13 int fib(int n){
14 int minusTwo=1, minusOne=1, answer=2;
15 if (n < 3)
16 return 1;
17 for (n -=3; n; n--)
18 {minusTwo = minusOne;
19 minusOne = answer;
20 answer = minusOne + minusTwo;}
21 return answer;}
Natija:
Which position? 4
3 is the 4th Fibonacci number.
Which position? 5
5 is the 5th Fibonacci number.
Which position? 20
6765 is the 20th Fibonacci number.
Which position? 100
3314859971 is the 100th
Fibonacci number.

93
6-mavzuda siz if va if/else operatorlari bilan tanishdingiz. Biroq,
ba'zi hollarda ko'p sonli if operatoridan foydalanish dasturni yozishni
ham, tushunishni ham ancha qiyinlashtiradi. Ushbu muammoni hal
qilish uchun C++ tilida switch operatoridan foydalaniladi. Uning if
operatoridan asosiy farqi shundaki, u bir vaqtning o'zida bir nechta
shartlarni tekshirishga imkon beradi, natijada dasturning tarmoqlanishi
yanada samarali tashkil etiladi. Switch operatorining sintaksisi
quyidagicha:
switch (ifoda)
{
case qiymat_1: operator; break;
case qiymat_2: operator;break;
case qiymat_n: operator; break;
default; operator;
}
Switch ifodasidan so‘ng qavs ichida sintaksisi nuqtai nazaridan
to'g'ri bo'lgan har qanday ifoda ishlatilishi mumkin. Operator
identifikatori o'rniga har qanday operatordan, sonli ifodadan yoki
ifodalar ketma-ketligidan foydalanishga ruxsat beriladi. Lekin bu yerda
mantiqiy amallar yoki taqqoslash ifodalaridan foydalanishga yo'l
qo'yilmaydi.
SWITCH OPERATORI
Switch ifodasi bir nechta mumkin bo'lgan qiymatlarni qaytaradigan
ifoda natijalariga ko'ra dasturni tarmoqlashga imkon beradi. Switch
operatorining qavsida berilgan ifoda qiymati bilan case operatorlaridan
keyin ko'rsatilgan qiymatlar taqqoslanadi va qiymatlar mos keladigan
tegishli case operatori bajariladi. Dasturning barcha satrlari tanlangan
case operatoridan so'ng switch operatori blokining tanasi tugaguncha
yoki break operatori uchraguncha bajariladi.
Agar case operatorlarining biror bir qiymati qaytarilgan qiymatga
to'g'ri kelmasa, u holda default operatoridan keyin joylashgan dastur
satrlari bajariladi, agar ushbu operator switch blokining tanasida
bo'lmasa, boshqaruv ushbu blokdan keyingi dastur qatoriga o'tkaziladi.
1-misol:
switch (choice)
{
case 0: cout << "Zero!" << endl; break;
case 1: cout << "One!"<< endl; break;
case 2: cout << "Two!" << endl; break;
default: cout << "Default!" << endl;
}

94
Break operatori bo'lmasa, casedan keyingi operator yoki ifodadan
keyingi case blokining ifodasi bajariladi. Ko'pgina hollarda bu holat
break operatori xato bilan o'tkazib yuborilganda yuzaga keladi.
Listing 7.13. switch takrorlash operatoriga misol.
1 #include <iostream>
2 using namespace std;
3 int main (){
4 unsigned short int number;
5 cout << "Enter a number between 1 and 5:";
6 cin >> number;
7 switch (number)
8 {case 0: cout<< "Too small, sorry!";break;
9 case 5: cout<< "Good job!\n";
10 case 4: cout<< "Ice Pick!\n";
11 case 3: cout<< "Excellent!\n";
12 case 2: cout<< "Masterful!\n";
13 case 1: cout<< "Incredible!\n"; break;
14 default: cout<< "Too large!\n"; break;
15 cout << "\n\n";}
16 return 0;}
Natija
Enter a number between 1 and 5:3
Excellent!
Masterful!
Incredible!
Enter a number between 1 and 5:8
Too large!
Nazorat savollari va topshiriqlar:
1. For takrorlashida bir vaqtning o'zida bir nechta hisoblagich
o'zgaruvchilarini ishga tushirish mumkinmi?
2. Nima uchun goto operatoridan foydalanishdan qochish kerak?
3. For operatori yordamida tanasi bajarilmaydigan takrorlashni tashkil
qilish mumkinmi?
4. For takrorlashi ichida while takrorlashini tashkil qilish mumkinmi?
5. Hech qachon tugamaydigan takrorlashni tashkil qilish mumkinmi?
Misol keltiring.
6. Cheksiz takrorlash boshlanganda nima bo'ladi?
7. For takrorlashi tugagandan so'ng x o'zgaruvchining qiymati qanday
bo'ladi (int x = 0; x <100; x++)?
8. 10×10 massivni nol bilan to‘ldiradigan for takrorlashini yarating.
9. Hisoblagich 100 dan 200 gacha 2-bosqichda o'zgarib turadigan for
takrorlashini tashkil qiling.

95
10. Hisoblagichi 100 dan 200 gacha 2-bosqichda o'zgarib turadigan
vaqt takrorlashini tashkil qiling.
11. Quyidagi dastur qismidagi xatolikni toping.
int counter = 0;
while (counter < 10)
{cout << "counter: " << counter;}
12. Quyidagi dastur qismidagi xatolikni toping.
for (int counter = 0; counter < 10; counter++);
cout << counter << " "
13. Quyidagi dastur qismidagi xatolikni toping.
int counter = 100;
while (counter < 10)
{cout << "counter: " << counter;
counter--;}

96
8-MAVZU. C++ DA MASSIVLAR
 Massiv va uni e'lon qilish
 Satrlar va ularni belgilar massivi yordamida yaratish
 Massivlar va ko'rsatkichlar o'rtasidagi munosabatlar

MASSIVLAR NIMA?
lar kompyuter xotirasida saqlangan bir xil tipdagi
ma'lumotlar to'plamidir. Har bir ma'lumot birligi deb
ataladi.
Massivni e'lon qilish uchun siz uning tipini, nomini va hajmini
ko'rsatishingiz kerak. Hajmi kvadrat qavs ichida olingan son bilan
belgilanadi va ma'lum bir qatorda qancha elementni saqlash
mumkinligini ko'rsatadi, masalan:
long LongArray[25];
Ushbu misolda long int tipidagi 25 ta elementni o'z ichiga olishi
mumkin bo'lgan LongArray nomli massiv e'lon qilinadi. Kompilyator
shunga o'xshash yozuvni topib, ushbu turdagi 25 ta elementni saqlash
uchun kompyuter xotirasida joy ajratadi. Long int tipidagi bitta
qiymatni saqlash uchun 4 bayt xotira talab qilinganligi sababli berilgan
massiv uchun kompilyator 100 baytli xotiraning butun maydonini
ajratadi.
MASSIV ELEMENTLARI
Massiv elementlarining manzili massiv nomida saqlangan birinchi
element manziliga nisbatan indeks bilan aniqlanadi. Massivning
birinchi elementi nol indeksga ega. Shunday qilib, massivning birinchi
elementiga quyidagicha murojaat qilish mumkin: arrayName[0]. Agar
mavzu boshida berilgan massiv misolidan foydalansangiz, massivning
birinchi elementiga murojaat quyidagicha bo‘ladi: LongArray[0],
ikkinchi elementi - LongArray[1] va boshqalar. Umuman olganda, agar
massiv[N] e'lon qilingan bo'lsa, unda uning elementlariga indeksni
ko'rsatish orqali kirish mumkin, ya`ni massiv[0] dan massiv[n-1] kabi
indekslanadi.

97
8.1-rasm. Massiv prototipi
Shunday qilib, bizning misolimizda LongArray [25] massivi
elementlarga murojaat qilish uchun LongArray[0]dan LongArray[24]
gacha bo'lgan indekslardan foydalaniladi. Listing 8.1 beshta
elementdan iborat butun sonlar massivini e'lon qilish va uni ma'lumotlar
bilan to‘ldirish ko'rsatilgan.
Listing 8.1. Butun sonlar massividan foydalanish
1 #include <iostream>
2 using namespace std;
3 int main(){
4 int myArray[5];
5 int i;
6 for ( i=0; i<5; i++)
7 {cout << "Value for myArray[" << i << "]: ";
8 cin >> myArray[i];}
9 for (i = 0; i<5; i++)
10 cout << i << ": " << myArray[i] << "\n";
11 return 0;}
Natija:
Value for myArray[0]: 3
Value for myArray[1]: 6
Value for myArray[2]: 9
Value for myArray[3]: 12
Value for myArray[4]: 15
0: 3
1: 6
2: 9
3: 12
4: 15
ESLATMA: Shuni esda tutish kerakki, massiv elementlarini
hisoblash 1 bilan emas, balki 0 bilan boshlanadi. Agar 10 ta elementdan
iborat massiv ishlatilsa, massiv elementlariga murojaat qilish uchun
ArrayName[0] dan ArrayName[9] gacha bo'lgan indekslardan
foydalaniladi. ArrayName[10] bilan ishlash noto'g'ri bo'ladi.

98
Massivga ma'lumotlarni yozishda kompilyator elementning
kattaligi va birinchi elementga nisbatan ko'rsatilgan indeks asosida
tegishli elementning manzilini hisoblab chiqadi. Aytaylik, biz ilgari
ko'rib chiqqan LongArray massivining oltinchi elementiga ma'lum bir
qiymat yoziladi, buning uchun LongArray[5] indeksi ishlatiladi.
Kompilyator ko'rsatilgan 5 indeks qiymatini element hajmiga
ko'paytiradi (bizning misolimizda 4 bayt) va 20 baytni oladi. Keyin
kompilyator massivning oltinchi elementining manzilini hisoblab,
massiv manziliga 20 bayt indeks qo'shadi va kiritilgan qiymatni shu
manzilga yozadi.
Listing 8.2. Massivdan tashqarida yozish.
1 #include <iostream>
2 using namespace std;
3 int main(){
4 long sentinel0ne[3];
5 long TargetArray [25];
6 long sentinelTwo[3];
7 int i;
8 for (i=0; i<3; i++)
9 sentinel0ne[i] = sentinelTwo[i] = 0;
10 for (i=0; i<25; i++)
11 TargetArray[i] = 0;
12 cout << "Test 1: \n";
13 cout << "TargetArray[0]: " << TargetArray[0] << "\n";
14 cout << "TargetArray[24]: " << TargetArray[24] << "\n\n";
15 for (i = 0; i<3; i++)
16 {cout << "sentinel0ne[" << i << "]: ";
17 cout << sentinel0ne[i] << "\n";
18 cout << "sentinelTwo[" << i << "]: ";
19 cout << sentinelTwo[i]<< "\n";}
20 cout << "\nAssigning...";
21 for (i = 0; i<=25; i++)
22 TargetArray[i] = 20;
23 cout << "\nTest 2: \n";
24 cout << "TargetArray[0]: " << TargetArray[0] << "\n";
25 cout << "TargetArray[24]: " << TargetArray[24] << "\n";
26 cout << "TargetArray[25]: " << TargetArray[25] << "\n\n";
27 for (i = 0; i<3; i++)
28 cout << "sentinelOne[" << i << "]: ";
29 cout << sentinel0ne[i]<< "\n";
30 cout << "sentinelTwo[" << i << "]: ";
31 cout << sentinelTwo[i]<< "\n";
32 return 0;}

99
Natija:
Test 1:
TargetArray[0]: 0
TargetArray[24]: 0
Sentine10ne[0]: 0
SentinelTwo[0]: 0
Sentinel0ne[1]: 0
SentinelTwo[1]: 0
Sentinel0ne[2]: 0
SentinelTwo[2]: 0
Assigning…
Test 2:
TargetArray[0]: 20
TargetArray[24]: 20
TargetArray[25]: 20
Sentinel0ne[0]: 20
SentinelTwo[0]: 0
Sentine10ne[1]: 0
SentinelTwo[1]: 0
Sentinel0ne[2]: 0
SentinelTwo[2]: 0
Masalan quyidagi matematik masalani ko‘rsak. Agar ustunlar
orasidagi masofa 1 m bo‘lishi kerak bo'lsa, 10 metrli panjarani o'rnatish
uchun qancha ustunlarni qazish kerakligini hisoblang. Demak, to'g'ri
javob - 11. Agar nima uchun ekanligini tushunmasangiz, 8.2 rasmga
qarang.

8.2-rasm. Panjara ustunlarini hisoblashda xato


Massivga kirishda indeksni o'rnatishdagi kichik xatolik juda
qimmatga tushishi mumkin. Dasturchi 25 elementdan iborat massivga
murojaat qilganda indeks 24 qiymatidan oshmasligi va hisoblash 1 dan
emas, 0 dan boshlanishini inobatga olishi kerak.
MASSIVNI ISHGA TUSHIRISH
Asosiy tipdagi massivni (masalan, int yoki char) ishga tushirish
uning e'lon qilinishi bilan bir vaqtda amalga oshirilishi mumkin. Buning
uchun massiv e`lonidan so‘ng tenglik belgisini (=) va figurali qavslarda
vergul bilan ajratilgan massiv elementlarining qiymatlari Listingini
o'rnatishingiz kerak. Masalan:
int IntegerArray[5] = {10, 20, 30, 40, 50};

100
Ushbu misolda IntegerArray butun sonlar qatori e'lon qilinadi va
IntegerArray[0] elementiga 10, IntegerArray elementiga[1] - 20 va
boshqalar beriladi.
Agar siz massiv o'lchamini bermasangiz, kompilyator avtomatik
ravishda element qiymatlari Listingi bo'yicha massiv hajmini hisoblab
chiqadi. Shuning uchun quyidagi yozuv xato emas:
int IntegerArray[] = {10, 20, 30, 40, 50};

Natijada, biz oldingi misolda bo'lgani kabi bir xil qiymatlar qatorini
olamiz. Agar siz massiv hajmini o'rnatishingiz kerak bo'lsa, quyidagi
ifoda yordamida kompilyatorga murojaat qiling:
const USHORT IntegerArrayLength;
IntegerArrayLength =
sizeof(IntegerArray)/sizeof(IntegerArray[0]);
Ushbu misolda massiv elementlari soni baytdagi massiv
o'lchamining bitta element hajmiga nisbati sifatida aniqlanadi. Natija
yuqoridagi const USHORT tipidagi IntegerArrayLength
o'zgaruvchisida saqlanadi. Listingda massiv elementlarining
belgilangan sonidan ko'proq qiymatlarni ko'rsatish mumkin emas.
Shunday qilib, quyidagi ifoda kompilyator tomonidan xato xabari
ko'rsatilishiga olib keladi, chunki beshta elementdan iborat massiv
oltita qiymatni o‘zlashtirishga harakat qiladi:
int IntegerArray[5] = (10, 20, 30, 40, 50, 60);

Shu bilan birga, quyidagi ifoda xatolik bermaydi:


int IntegerArray[5] = {10, 20};

E`lon qilish paytida ishga tushirilmagan massiv elementlarining


qiymatlari o'rnatilmaydi. Odatda massivning boshlang'ich berilmagan
elementlarining qiymatlari nolga teng deb hisoblanadi.
Tavsiya etiladi!
 Kompilyatorga massiv hajmini mustaqil ravishda hisoblashiga
ruxsat bering.
 Massivlarga ularning maqsadini ifoda etadigan ma'lumotli nom
bering.
 Esda tutingki, massivning birinchi elementiga kirish uchun 0
indeksi ko'rsatilishi kerak.

101
Tavsiya etilmaydi!
 Massivdan tashqarida ma'lumotlarni yozmang.

MASSIVLARNI E'LON QILISH


Massivga har qanday nom berilishi mumkin, ammo u ushbu
massivning ko'rinishi doirasidagi boshqa barcha o'zgaruvchilar va
massivlardan farq qilishi kerak. Shunday qilib, agar dastur ilgari mycats
o'zgaruvchisini e'lon qilgan bo'lsa, mycats[5] massivini e'lon qila
olmaydi.
8.3-Listingda ko'rsatilgandek, prototip paytida massivning kattaligi
son bilan ham, o‘zgarmas yoki Listing bilan ham o'rnatilishi mumkin.
Listing 8.3. Massivni qamrab olishda o‘zgarmas va sanagichdan
foydalanish
1 #include<iostream>
2 using namespace std;
3 int main(){
4 enum WeekDays { Sun, Mon, Tue, Wed, Thu, Fri, Sat, DaysInWeek };
5 int ArrayWeek[DaysInWeek] = { 10, 20, 30, 40, 50, 60, 70 } ;
6 cout << "The value at Tuesday is " << ArrayWeek[Tue];
7 return 0;}
Natija:
The value at Tuesday is 30
Massivni e'lon qilish uchun avval unda saqlanadigan obyektlar
turini ko'rsatishingiz kerak, so'ngra massiv nomini va massiv hajmini
berishingiz mumkin. Hajmi ma'lum bir massivda ma'lum bir turdagi
qancha obyektni saqlash mumkinligini aniqlaydi.
1-misol: int MyIntegerArray[90];
2-misol: long ArrayOfPointersToLogs[100];
Massiv elementlariga kirish uchun indekslash operatori ishlatiladi.
1-misol: int theNinethInteger = MyIntegerArray[8];
2-misol: long pLong = ArrayOfPointersToLogs[8];
Massiv indekslari noldan hisoblanadi. Shuning uchun, o'z ichiga
olgan qatorga murojaat qilish uchun n elementlar, 0 dan n-1 gacha
bo'lgan indekslardan foydalaniladi.
OBYEKTLAR MASSIVI
O'rnatilgan yoki foydalanuvchi tomonidan yaratilgan har qanday
obyekt massivda saqlanishi mumkin. Ammo buning uchun avval siz
massivni e'lon qilishingiz va kompilyatorga ushbu massiv qaysi turdagi
obyektlar uchun yaratilganligini va qancha obyektni o'z ichiga olishi
mumkinligini ko'rsatishingiz kerak.
102
Kompilyator sinfni e'lon qilishda berilgan obyekt hajmiga qarab
massiv uchun qancha xotira ajratilishini hisoblab chiqadi. Massiv
elementlari ma'lumotlariga kirish ikki bosqichda amalga oshiriladi.
Birinchidan, indekslash operatoridan ([ ]) foydalanib, siz massiv
elementini ko'rsatishingiz va ma'lum bir elementga murojaat qilishingiz
mumkin.
Listing 8.4. Obyektlar qatorini yaratish
1 #include <iostream>
2 using namespace std;
3 class CAT
4{
5 public:
6 CAT() { itsAge = 1; itsWeight=5; }
7 ~CAT() {}
8 int GetAge() const { return itsAge; }
9 int GetWeight() const { return itsWeight; }
10 void SetAge(int age) { itsAge = age; }
11 private:
12 int itsAge;
13 int itsWeight;
14 };
15 int main()
16 {
17 CAT Litter[5];
18 int i;
19 for (i = 0; i < 5; i++)
20 Litter[i].SetAge(2*i+1);
21 for (i = 0; i < 5; i++)
22 {cout << "cat #" << i+1<< ": ";
23 cout << Litter[i].GetAge() << endl;}
24 return 0;
25 }
Natija:
cat #1: 1
cat #2: 3
cat #3: 5
cat #4: 7
cat #5: 9
KO'P O'LCHOVLI MASSIVLAR
Bir nechta o'lchovlarni o'z ichiga olgan massivni yaratish va undan
foydalanish mumkin. Ikki o'lchovli massiv elementiga kirish uchun siz
ikkita indeksni ko'rsatishingiz kerak; uch o'lchovli massiv elementiga -
uchta indeks va hokazo. Nazariy jihatdan har qanday o'lchovli massivni
yaratish mumkin, lekin amaliy jihatdan asosan, dasturlarda bir o'lchovli
va ikki o'lchovli massivlardan foydalaniladi. Ikki o'lchovli massivga

103
misol sifatida sakkiz qator va sakkiz ustunli kataklardan tashkil topgan
shaxmat taxtasini misol qilish mumkin.
Aytaylik, dastur SQUARE sinfini e'lon qiladi. Ushbu sinf
obyektlarini saqlash uchun ikki o'lchovli massivni e'lon qilish
quyidagicha bo'ladi:
SQUARE Board[8][8];
Xuddi shu obyektlar 64 elementli bir o'lchovli massivda saqlanishi
mumkin edi:
SQUARE Board[64];
Agar bunday massiv haqiqiy vaziyatni yaxshiroq aks ettirsa,
masalan, shaxmat dasturini yaratishda 2D massivdan foydalanish
afzalroq bo‘lishi mumkin. Shunday qilib, o'yin boshida qirol birinchi
qatorda to'rtinchi ustunni egallaydi. Nol indeksni hisobga olgan holda,
ushbu ko‘rinishning pozitsiyasi massiv obyekti bilan ifodalanadi:
Board[0][3];
Ushbu misolda birinchi indeks qatorlarni, ikkinchisi ustunlarni
raqamlashni nazorat qiladi.
KO'P O'LCHOVLI MASSIVNI ISHGA TUSHIRISH
Birinchi navbatda qiymatlarning butun takrorlashi oxirgi
ko'rsatilgan indeksdan o'tadi, shundan so'ng oldingi indeks o'zgaradi.
Shunday qilib, agar ushbu massiv mavjud bo'lsa:
int theArray[5][3];
birinchi uchta qiymat theArray[0] qatoriga, ikkinchi uchta qiymat
theArray[1] qatoriga yoziladi va hokazo.
Belgilangan qatorni quyidagi qator bilan boshlash mumkin:
int theArray[5][3] = {1,2,3,4,5, 6,7,8,9, 10,11,12,13,14, 15};
Sonlar bilan chalkashmaslik uchun qiymatlarni qo'shimcha figurali
qavslar yordamida guruhlash mumkin, masalan:
int theArray[5][3] ={ {11,2,3},
{4,5,6},
{7, 8,9},
{10, 11, 12},
{13, 14, 15}};

Kompilyator barcha ichki figurali qavslarni e'tiborsiz qoldiradi.


Qo'shimcha figurali qavslardan foydalanasizmi yoki yo'qmi barcha
qiymatlarni vergul bilan ajratish kerak. Qiymatlarning butun qatori

104
tashqi figurali qavslarga joylashtirilishi kerak va yopiladigan qavsdan
keyin nuqta-vergul belgisi qo‘yilishi kerak.
Ikki o'lchovli massivni yaratish misoli listing 8.5 da ko'rsatilgan.
Ikki o'lchovli massivning birinchi qatori 0 dan 4 gacha bo'lgan butun
sonlarni, ikkinchisi esa birinchi qatorning tegishli elementlarining ikki
baravar qiymatlarini o'z ichiga oladi.
Listing 8.5. Ko'p o'lchovli massiv yaratish
1 #include <iostream>
2 using namespace std;
3 int main()
4 {
5 int SomeArray[5][2] = { { 0,0} , { 1,2} , { 2,4} , { 3,6} , { 4,8} };
6 for (int i = 0; i<5; i++)
7 for (int j=0; j<2; j++)
8 {cout << "SomeArray[" << i << "][" << j << "]: ";
9 cout << SomeArray[i][j]<< endl;}
10 return 0;}

Natija:
SomeArray[0][0]:0
SomeArray[0][1]:0
SomeArray[1][0]:1
SomeArray[1][1]:2
SomeArray[2][0]:2
SomeArray[2][1]:4
SomeArray[3][0]:3
SomeArray[3][1]:6
SomeArray[4][0]:4
SomeArray[4][1]:8

8.3-rasm. 5×2 massiv.


Massivni e'lon qilishda kompilyatorga unda qancha obyektni
saqlash rejalashtirilganligi aniq ko'rsatiladi. Kompilyator barcha massiv
obyektlari uchun xotirani zaxiraga oladi, hatto ular dasturda bundan
keyin o'rnatilmagan bo'lsa ham. Agar siz massiv qancha elementni
saqlashi kerakligini oldindan aniq bilsangiz, unda hech qanday
muammo bo'lmaydi. Masalan, shaxmat taxtasida har doim 64 ta katak
bor. Agar dastlab massivda qancha element bo‘lishi noma'lum bo'lsa,

105
unda ushbu muammoni hal qilish uchun siz yanada moslashuvchan
xotirani boshqarish vositalaridan foydalanishingiz kerak.
KO'RSATKICH MASSIVLARI
Hozirgacha biz ko'rib chiqqan barcha massivlar o'z elementlarining
qiymatlarini xotira to'plamlarida saqlashgan. Stack xotirasidan
foydalanish dinamik xotiraning yanada moslashuvchan maydoniga
murojaat qilish orqali oldini olish mumkin bo'lgan bir qator cheklovlar
bilan bog'liq. Buni avval massivning barcha obyektlarini dinamik xotira
maydonida saqlash va keyin massivda ushbu obyektlarga
ko'rsatgichlarni yig'ish orqali amalga oshirish mumkin. Ushbu
yondashuv dasturning kompyuter Stack xotirasidan foydalanishni
sezilarli darajada kamaytiradi. Listing 8.6 Listing 8.4 da ishlagan bir xil
qatorni ko'rsatadi, ammo endi uning barcha obyektlari dinamik xotira
maydonida saqlanadi. Dasturning xotiradan foydalanish
samaradorligini oshirish uchun ushbu misolda massiv hajmi 5 dan 500
gacha oshirildi.
Listing 8.6. Dinamik xotira maydonida massivni saqlash
1 #include<iostream>
2 using namespace std;
3 class CAT
4{
5 public:
6 CAT() { itsAge = 1; itsWeight=5; }
7 ~CAT() {}
8 int GetAge() const {return itsAge; }
9 int Getheight() const { return itsWeight; }
10 void SetAge(int age) { itsAge = age; }
11 private:
12 int itsAge;
13 int itsWeight;
14 };
15 int main()
16 {
17 CAT * Family[500];
18 int i;
19 CAT * pCat;
20 for (i = 0; i < 500; i++)
21 {pCat = new CAT;
22 pCat->SetAge(2*i +1);
23 Family[i] = pCat;}
24 for (i = 0; i < 500; i++)
25 {cout << "Cat #" << i+1 <<":";
26 cout << Family[i]->GetAge() << endl;}
27 return 0;
28 }

106
Natija:
Cat #1:1
Cat #2:3
Cat #3:5
...
Cat #499:997
Cat #500:999
Bu yerda ushbu amalning natijasi dinamik almashinuv maydonida
saqlangan qatorga ko'rsatgichdir:
CAT * Family = new CAT[500];

Bunday massiv e`lonining yana bir afzalligi shundaki, Family


o'zgaruvchisi bo'lgan dasturda endi matematik amallarni boshqa har
qanday ko'rsatgich kabi bajarish mumkin bo'ladi, bu esa massiv
elementlariga kirishni boshqarishda qo'shimcha imkoniyatlarni ochadi.
Masalan, siz quyidagi amallarni bajarishingiz mumkin:
CAT * Family = new CAT[500];
CAT * pCat = oila; / / pCat oilaga ishora qiladi[0]
pCat - >SetAge (10); / / Family[0] qiymatini 10 ga belgilaydi
pCat++; / / oilaga o'tish[1]
pCat - >SetAge (20); / / oilani o‘zlashtiradi[1] qiymati 20
Ushbu misolda CAT sinfidagi 500 ta obyektdan iborat yangi
massiv e'lon qilinadi va ko'rsatgich ushbu massivning birinchi
elementiga qaytariladi. Keyin ushbu ko'rsatgich va CAT sinfida e'lon
qilingan SetAge () funksiyasi yordamida massivning birinchi obyektiga
10 qiymati beriladi. Massivning keyingi obyektiga o'tish
ko'rsatgichdagi manzilni massivga ko'paytirish orqali amalga oshiriladi,
shundan so'ng massivning ikkinchi obyektiga xuddi shu tarzda 20
qiymati beriladi.
Quyidagi uchta e`lonni ko'rib chiqing:
1: CAT FamilyOne[500];
2: CAT * FamilyTwo[500];
3: CAT * FamilyThree = new CAT[500];
Birinchi holda, 500 ta mushuk tipidagi obyektlarni o'z ichiga olgan
FamilyOne massivi e'lon qilinadi. Ikkinchi holda, Cat sinfidagi
obyektlarga 500 ta ko'rsatgichni o'z ichiga olgan FamilyTwo qatori,
uchinchi holatda esa 500 ta CAT sinfidagi obyektlar qatoriga ishora
qiluvchi FamilyThree ko'rsatgichi berilgan.

107
Dasturda qaysi e`lon ishlatilishiga qarab, massivni boshqarish
usullari tubdan o'zgaradi. FamilyThree ko'rsatgichi aslida FamilyOne
massiviga ancha yaqinroq, ammo FamilyTwo ko'rsatgichlari
massividan tubdan farq qiladi.
Tavsiya etiladi!
 Esda tutingki, 0 dan n-1 gacha bo'lgan indekslar n elementlar
qatoriga kirish uchun ishlatiladi.
 Massiv elementlariga kirishni boshqarish uchun ko'rsatkichlar
bilan matematik amallarning xususiyatlaridan foydalaning.
Tavsiya etilmaydi!
 Massivdan tashqarida ma'lumotlarni yozmang.
 Ko'rsatgichlar qatorini massivga ko'rsatgich bilan aralashtirmang.
Siz massiv elementlarini saralash yoki boshqa tartiblash
mexanizmini ishlab chiqarishingiz yoki massivlarning boshqa ko'plab
samarali variantlaridan foydalanishingiz mumkin, ular orasida eng
mashhurlari quyidagilar:
massivning har bir a'zosi avtomatik ravishda o'z
o'rnini egallaydi;
hech bir a'zo massivda ikki marta takrorlanmaydi;
massiv elementlarining bog'langan juftlari, bu yerda bitta
atama ikkinchi atamani qaytarish uchun kalit vazifasini bajaradi;
tartibsiz to'plamlar, ularning a'zolari tasodifiy tartibda
qo'shiladi va qaytariladi.

Nazorat savollari va topshiriqlar:


1. Somearray[25] massivining birinchi va oxirgi elementlariga qanday
murojaat qilish mumkin?
2. Ko'p o'lchovli massivni qanday e'lon qilish kerak?
3. Ko'p o'lchovli massiv elementlarini ishga tushiring va 0 qiymat bilan
to‘ldiring.
4. SomeArray[10][5][20] massivida nechta element mavjud?
5. "Anvar-yaxshi bola" qatoridagi oxirgi belgi nima?
6. Quyidagi dasturdagi xatolikni toping.
unsigned short SomeArray[5][4];
for (int i = 0; i<4; i++)
for (int j = 0; j<5; j++)
SomeArray[i][j] = i+j;

108
7. Quyidagi dasturdagi xatolikni toping.
unsigned short SomeArray[5][4];
for (int i = 0; i<=5; i++)
for (int j = 0; j<=4; j++)
SomeArray[i][j] = 0;
8. n(n>0) butun son va n ta haqiqiy sonlardan iborat ketma-ketlik
berilgan. Berilgan ketma-ketlikdagi barcha sonlarning butun qismlari
hamda butun qismlarining yig‘indisi chiqarilsin.
3
3.5 2.6 8.7 3 2 8 13
9. n(n>0) butun son va n ta butun sondan iborat ketma-ketlik berilgan.
Agar ketma-ketlik musbat sonlardan iborat bo‘lsa true, aks holda false
chiqarilsin.
3
5 6 -4 false
10. n(n>0) butun son va n ta butun sondan iborat ketma-ketlik berilgan.
Berilgan ketma-ketlikdagi barcha toq sonlar va ularning miqdori k
chiqarilsin.
4
3645 352

109
9-MAVZU: C++ DA BELGI VA SATRLAR
 Belgilar va sonlar
 Maxsus belgilar
 Belgilar massivi
 String sinflari

o'zgaruvchilari (char tipi) odatda bir baytni egallaydi, bu


belgilarning 256 qiymatini saqlash uchun yetarli. Char tipining qiymati
0-255 oralig'idagi son yoki ASCII belgisi sifatida talqin qilinishi
mumkin.
ASCII belgilar to'plami va uning ISO ekvivalenti (xalqaro
standartlar tashkiloti - xalqaro standartlashtirish tashkiloti) barcha
harflar, raqamlar va tinish belgilarini kodlash usulidir.
Masalan, ASCI kodida inglizcha "a" kichik harfiga 97 qiymati
berilgan.
Barcha katta va kichik harflar, barcha sonlar va tinish belgilariga 1
dan 128 gacha qiymatlar berilgan. Qo'shimcha 128 ta belgi va belgilar
kompyuterning imkoniyatlarini kengaytirish uchun ajratilgan, ammo
IBM-ning kengaytirilgan belgilar to'plami allaqachon standartga
aylangan.
ESLATMA: Kompyuterlarda harflar, tinish belgilari yoki gaplar
haqida hech qanday ma'lumot yo'q. Ularning barchasi faqat raqamlarni
tushunishadi.
Agar siz "a" kabi biror bir belgini char turidagi o'zgaruvchiga
joylashtirsangiz, unda aslida u 0 dan 255 gacha bo'lgan sonni saqlaydi.
Biroq, kompilyator ASCII-da va undan sonli ekvivalentlariga
belgilardan qanday o'tishni biladi.
Son va harf o'rtasidagi munosabatlar avtomatik amalga oshiriladi,
chunki kichik "a" harfiga 97 qiymatini o‘zlashtirish uchun hech qanday
sabab yo'q. Biroq, 5 qiymati va "5" belgisi o'rtasida katta farq borligini
tushunish muhimdir. "5" belgisi aslida 53 qiymatiga to'g'ri keladi, xuddi
"a" harfi 97 soniga to'g'ri keladi.

Listing 9.1. Belgilarni va ularning kodlari bo'yicha ko'rsatish.


1 #include <iostream>
2 using namespace std;
3 int main(){
4 for (int i = 32; i<128; i++)
5 cout << (char) i;

110
6 return 0;
7}
Natija:
!"#$%'()++,./0123456789:;<>?@ABCDEFGHIJKLMNOP
_QRSTUVWXYZ[\]"'abcdefghijklmnopqrstuvwxyz(|{~
Ushbu oddiy dastur qiymatlari 32-127 oralig'ida bo'lgan belgilarni
chiqaradi.
MAXSUS BELGILAR
C++ kompilyatori matnni formatlash uchun mo'ljallangan ba'zi
ni taniydi. Ushbu belgilarni dasturga kiritish uchun
teskari chiziq ishlatiladi (“\”, boshqaruv ketma-ketligining boshlanish
belgisi deb ataladi), undan keyingi belgilar boshqaruvchi ekanligini
bildiradi. Shuning uchun dasturga tabulyatsiya belgisini kiritish uchun
siz bitta tirnoq, teskari chiziq, t harfini va yana bitta tirnoqni
kiritishingiz kerak:
char tabCharacter = '\t';
Ushbu misolda char turi (tabCharacter nomi bilan), u darhol \t
belgisi qiymati bilan ishga tushiriladi, tabulyatsiya belgisi sifatida tan
olinadi, o'zgaruvchi e'lon qilinadi. Ma'lumotni ekranda, faylda yoki
boshqa chiqarish qurilmasida (masalan, printer) ko'rsatishda maxsus
formatlash belgilaridan foydalaniladi.
“\” belgisi undan keyingi belgining qiymatini o'zgartiradi.
Masalan, odatda n belgisi n harfini anglatadi, lekin oldingi boshqaruv
ketma-ketligi ( \ ) boshlanishining belgisi bo'lsa, u yangi qatorga o‘tish
belgisiga aylanadi.

Belgi Ma'nosi
\n Yangi qatorga o‘tish
\t Tabulyatsiya
\b Bir pozitsiyaga qaytish
\? Savol belgisi
\” Ikki tirnoq
\’ Bitta tirnoq
\\ Teskari Slesh
9.1-jadval. Boshqaruv belgilari

111
string txt = "We are the so-called "Vikings" from the north.";

Ushbu misolda “Vikings” qo‘shtirnoq ichida konsolga chiqarishi


kerak. C++ da satrlar qo‘shtirnoq ichida yozilishi kerakligi sababli, bu
yozuvni noto‘g`ri tushunadi va xatolik qaytaradi.
Ushbu muammoning yechimi teskari slash (\) belgisidan
foydalanishdir. Teskari slash (\) belgisi maxsus belgilarni string
belgilarga aylantiradi. \" ketma-ketligi satrga qo'shtirnoq qo'shadi.
Ya`ni, string txt = "We are the so-called \"Vikings\" from the north.";
Xuddi shunday \' belgisi satrga bitta tirnoq qo'shadi:
string txt = "It\'s alright.";
BELGILAR MASSIVI
Matn qatori belgilar to'plamidir. Biz hozirgacha dasturlarda
ishlatgan barcha satrlar cout operatori bilan ifodalarda ishlatiladigan
nomsiz string konstantalari edi, masalan:
cout << "hello world.\n";
Ammo C++ da satr satrning oxirgi nol belgisi bilan tugaydigan
belgilar qatori sifatida ifodalanishi mumkin. Bunday massiv boshqa har
qanday massiv kabi e'lon qilinishi va ishga tushirilishi mumkin,
masalan:
char Greeting[] = { 'H', 'e', 'l', ‘l', 'o',
'W','o','r','1','d', '0'};
Massivning oxirgi elementiga nol sonli satr belgisi (\\0) kiritiladi,
uni ko'plab C++ funksiyalari yangi qatorga o‘tish sifatida tan oladi. C++
matn satrlarini massivlarga kiritishning soddalashtirilgan usuliga imkon
beradi:
char Greeting[] = "hello world";
Ushbu sintaksisning ikkita nuqtasiga e'tibor bering.
Har bir belgi atrofida bitta tirnoq o'rniga, belgilar orasidagi vergul
va butun satr atrofidagi figurali qavslar o'rniga ushbu misolda faqat satr
atrofida qo‘shtirnoq ishlatiladi va boshqa hech narsa yo'q. Hatto
boshlash uchun odatiy figurali qavslar ham yo'q.
Terminal nol belgisini qo'shishning hojati yo'q, chunki kompilyator
buni avtomatik ravishda bajaradi.
“Hello world” qatori 12 baytni oladi. Besh bayt Hello so'ziga,
beshta world so'ziga va bo'sh joy va oxirgi nol belgisi uchun bir baytga
to'g'ri keladi.

112
Listing 9.2. Massivni belgilar bilan to‘ldirish
1 #include<iostream>
2 using namespace std;
3 int main()
4{
5 char buffer[80];
6 cout<<"Enter the string:";
7 cin>>buffer;
8 cout<<"Here's the buffer:"<<buffer<<endl;
9 return 0;
10 }
Natija:
Enter the string:Hello World
Here's the buffer:Hello
Foydalanuvchi kiritgan qatorni saqlash uchun cin >> operatoridan
foydalanish mumkin.
Biroq, cin bo'sh joyni (bo'sh joylar, tabulyatsiya va boshqalar)
tugatish belgisi sifatida ko'rib chiqadi, ya'ni u faqat bitta so'zni saqlashi
mumkin (hatto ko'p so'zlarni yozsangiz ham):
string fullName;
cout << "Type your full name: ";
cin >> fullName;
cout << "Your name is: " << fullName;
// Type your full name: John Doe
// Your name is: John
Yuqoridagi misoldan siz dastur "John Doe" ni chop etishini
kutgansiz, lekin u faqat "John" ni chop etadi.
Shuning uchun satrlar bilan ishlaganda qatorni o'qish uchun
ko'pincha getline() funksiyasidan foydalanamiz. U birinchi parametr
sifatida cinni, ikkinchi parametr sifatida satr o'zgaruvchisini oladi:
string fullName;
cout << "Type your full name: ";
getline (cin, fullName);
cout << "Your name is: " << fullName;
// Type your full name: John Doe
// Your name is: John Doe
Siz satrdagi belgilarga uning kvadrat qavs ichidagi indeks
raqamiga murojaat qilish orqali kirishingiz mumkin [].
Masalan, myString dagi birinchi belgini chop etish quyidagicha:
string myString = "Hello";
cout << myString[0];
// Outputs H
ESLATMA: String indekslari 0 dan boshlanadi: [0] birinchi belgi. [1]
ikkinchi belgi va boshqalar. Satrdagi ma'lum bir belgining qiymatini

113
o'zgartirish uchun indeks raqamiga murojaat qiling va bitta tirnoqdan
foydalaning:
string myString = "Hello";
myString[0] = 'J';
cout << myString;
// Outputs Jello instead of Hello

SATR UZUNLIGI
ni olish uchun length() yoki size() funksiyasidan
foydalaning:
string txt = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
cout << "The length of the txt string is: " << txt.length();
cout << "The length of the txt string is: " << txt.size();
C++ qoʻshish va birlashtirish uchun + operatoridan foydalanadi.
Raqamlar qo'shiladi. Satrlar birlashtiriladi. Agar siz ikkita raqam
qo'shsangiz, natijada raqam bo'ladi:
int x = 10;
int y = 20;
int z = x + y; // z = 30
Agar siz ikkita satr qo'shsangiz, natijada satr birikmasi bo'ladi:
string x = "10";
string y = "20";
string z = x + y; // z="1020"
Agar siz satrga raqam qo'shishga harakat qilsangiz, xatolik yuz beradi:
string x = "10";
int y = 20;
string z = x + y;
SATRLARNI BIRLASHTIRISH
Satrlar orasidagi + operatoridan satrlarni bir-biriga qo'shish uchun
foydalanish mumkin. Bunga birikma deyiladi:
string firstName = "John ";
string lastName = "Doe";
string fullName = firstName + lastName;
cout << fullName;
Yuqoridagi misolda biz chiqarishda John va Doe o'rtasida bo'sh
joy yaratish uchun firstName dan keyin bo'sh joy qo'shdik. Shu bilan
birga, siz tirnoqli bo'sh joy qo'shishingiz mumkin (" " yoki ' '). Siz
satrlarni append() funksiyasi bilan ham birlashtirishingiz mumkin:
string firstName = "John ";
string lastName = "Doe";
string fullName = firstName.append(lastName);
cout << fullName;

114
Ko'pgina C++ kompilyatorlari turli xil amaliy muammolarni hal
qilish uchun ishlatilishi mumkin bo'lgan sinf kutubxonalarini o'z ichiga
oladi. O'rnatilgan sinflardan biri String sinfidir.
C++ tili StrCpy () funksiyasini o'z ichiga olgan satr oxiri nol belgisi
va satr funksiyalari kutubxonasidan meros bo'lib qolgan. Ammo bu
xususiyatlarning barchasini obyektga yo'naltirilgan dasturlashda
ishlatib bo'lmaydi. String sinfi o'rnatilgan a'zo va a'zo o'zgaruvchilar
to'plamini, shuningdek, foydalanuvchidan buyruqlar olish orqali matn
satrlarini qayta ishlash bilan bog'liq ko'plab muammolarni avtomatik
ravishda hal qilish imkonini beruvchi kirish usullarini taklif etadi.
Agar sizning kompilyatoringizda o'rnatilgan String sinfi bo'lmasa,
siz o'zingizning string sinfingizni yaratishingiz kerak bo'ladi.
Boshqa massivlar kabi, belgilar massivlari ham statikdir. Siz e'lon
qilganingizda yoki ishga tushirganingizda ularning hajmini
o‘zlashtirishingiz kerak.
Nazorat savollari va topshiriqlar:
1.Satrlar bilan ishlashda qaysi kutubxona funksiyasidan foydalanish
kerak?
2. Quyidagi sarlavhaning ma’nosi nima?
#include <string>
3. Quyidagi dasturdagi xatolikni topishga harakat qiling.
#include <iostream>
using namespace std;
int main()
{
string hello = "Hello World!";
cout << hello << "\n";
return 0;
}
4. ASCII kodida inglizcha "a" kichik harfiga necha qiymat berilgan?
5. ASCII haqida nimalarni bilib oldingiz?
6. Char turi xotiradan necha bayt o’rin egallaydi?
7. ASCII kodida nechta katta va kichik harflar, belgilar bor?
8.3-mashqdan foydalanib inglizcha kichik harflarni ekranga
chiqaradigan dastur tuzing.

115
10-MAVZU. C++ DA FUNKSIYALAR

 Funksiya nima va u nimadan iborat?


 Funksiyalarni e'lon qilish va aniqlash
 Parametrlarni funksiyalarga o'tkazish
 Funksiya qiymatini qaytarish

Siz main () funksiyasi bilan tanishgansiz. Main () funksiyasi dastur


tomonidan emas, balki operatsion tizim tomonidan chaqiriladi.
Dastur biror bir funksiya chaqiruvi kelgunga qadar satrma-satr
bajariladi. Keyin boshqaruv ushbu funksiya satrlariga o'tkaziladi.
Funksiya bajarilgandan so'ng darhol funksiya chaqiruvidan keyingi
dastur qatoriga qaytadi.
Dasturning funksiyasi bilan quyidagi o'xshashlik mavjud. Misol
uchun, agar chizish paytida qalamingiz singan bo'lsa, siz chizishni
to'xtatasiz va qalam uchini yunasiz. Shundan so'ng, siz qalam
singandagi chizma joyiga qaytasiz. Dastur ba'zi bir amallarini bajarishi
kerak bo'lganda, ushbu amalni bajarish uchun mas'ul bo'lgan funksiya
chaqiriladi, shundan so'ng dastur funksiya chaqirilgan joydan o'z ishini
davom ettiradi. Listing 10.1 ida bu ko'rsatib o‘tilgan.
Listing 10.1. Funksiya chaqiruviga misol
1 #include <iostream>
2 using namespcase std;
3 void DemonstrationFunction()
4 {cout << "In DemonstrationFunction\n";
5}
6 int main()
7{
8 cout << "In main\n" ;
9 DemonstrationFunction();
10 cout << " Back in main\n";
11 return 0;
12 }
Natija:
In main
In DemonstrationFunction
Back in main
Tahlil:
5-7-qatorlarda DemonstrationFunction () funksiyasi aniqlanadi. U
xabarni ko'rsatadi va boshqaruvni dasturga qaytaradi. Main ()
funksiyasi 12-qatorda boshlanadi va 13-qatorda dastur boshqaruvi
116
hozirda main () funksiyasida ekanligi to'g'risida xabar paydo bo'ladi.
Ushbu xabar chiqarilgandan so'ng DemonstrationFunction () funksiyasi
chaqiriladi. Ushbu murojaat natijasida DemonstrationFunction ()
funksiyasida joylashgan buyruqlar bajariladi. Bunday holda, butun
funksiya 6-qatorda joylashgan bitta buyruqdan iborat bo'lib, u boshqa
xabarni chiqaradi. DemonstrationFunction() (7-qator) funksiyasi
tugagandan so'ng, dasturni boshqarish ushbu funksiya chaqirilgan
joyga qaytariladi. Bunday holda, dasturning bajarilishi 15-qatordan
davom etadi, unda main() funksiyasi ekranda yakuniy xabarni
ko'rsatadi.
FUNKSIYALARDAN FOYDALANISH
ba'zi bir haqiqiy qiymatni yoki void tipidagi qiymatni
qaytaradi. Ikkita butun sonni qo'shadigan va yig'indining qiymatini
qaytaradigan funksiya butun sonni qaytaradigan qiymat sifatida
aniqlanishi kerak. Faqat xabarni ko'rsatadigan funksiyani qaytarish
uchun hech narsa yo'q, shuning uchun u void qaytish tipini o'rnatadi.
Funksiyalar sarlavha va tana qismidan iborat.
qaytish tipi, nomi va funksiya parametrlari o'z ichiga oladi. Parametrlar
qiymatlarni funksiyaga o'tkazishga imkon beradi. Shuning uchun, agar
funksiya ikkita sonni qo'shish uchun mo'ljallangan bo'lsa, unda bu
sonlar parametr sifatida funksiyaga o'tkazilishi kerak. Bunday
funksiyaning sarlavhasi quyidagicha bo'ladi:
int Sum(int a, int b)
-funksiyaga uzatiladigan qiymatning ma'lumotlar tipi
bilan e`lon qilish. Funksiya chaqirilganda uzatiladigan haqiqiy qiymat
deb ataladi. Ko'pgina dasturchilar ushbu ikki tushunchani o‘z
o'rnida ishlatishadi. ochiladigan figurali qavs bilan
boshlanadi va bir qator qatorlarni o'z ichiga oladi (garchi funksiya
tanasi hatto nolga teng bo'lsa ham) so'ngra esa figurali qavs bilan
yopiladi. Funksiya qaytish operatori yordamida dasturga qiymatni
qaytarishi mumkin. Ushbu operator funksiyadan chiqarishni ham
anglatadi. Agar siz funksiyani qaytarish operatoriga qo'ymasangiz,
funksiya tugagandan so'ng void turi qiymati avtomatik ravishda
qaytariladi. Funksiya tomonidan qaytarilgan qiymat funksiya
sarlavhasida e'lon qilingan turga ega bo‘lishi kerak.
Listing 10.2. Oddiy funksiyadan foydalanishga misol

117
1 #include <iostream>
2 using namespace std;
3 int Add (int x, int y)
4{
5 cout << "In Add(), received " << x << " and " << y << "\n":
6 return (x+y);
7}
8 int main()
9{
10 cout << "I'm in main()!\n";
11 int a, b, c;
12 cout << "Enter two numbers: "
13 cin >> a;
14 cin >> b:
15 cout << "\nCalling Add()\n";
16 c=Add(a, b);
17 cout << "\nBack in main().\n";
18 cout << "c was set to " << c;
19 cout << "\nExiting…\n\n";
20 return 0;
21 }
Natija:
I'm in main()!
Enter two numbers: 3 5
Calling Add()
In Add(), received 3 and 5
Back in main().
c was set to 8
Exiting.
Tahlil:
Add () funksiyasi 3-qatorda aniqlanadi. U ikkita butun parametrini
oladi va butun qiymatini qaytaradi. Dasturning o'zi 9-qatorda
boshlanadi, ekranda birinchi xabarni ko'rsatadi. Keyin
foydalanuvchidan ikkita sonni kiritish so'raladi (13-14 qatorlar).
Foydalanuvchi sonlarni bo'sh joy bilan ajratib kiritadi va keyin
<Enter>tugmachasini bosadi. 16-qatorda main () funksiyasi
foydalanuvchi tomonidan kiritilgan ikkita sonni argument sifatida
Add() funksiyalariga o'tkazadi.
Dasturni boshqarish 3-qatorda boshlanadigan Add () funksiyasiga
o'tadi. a va b parametrlari ekranda ko'rsatiladi va keyin qo'shiladi.
Funksiya natijasi 6-qatorda qaytariladi va shu bilan funksiya o'z ishini
tugatadi.
FUNKSIYA NIMA?
- ma'lumotlarni boshqarishi va ba'zi qiymatlarni
qaytarishi mumkin bo'lgan kichik dasturdir. Har bir C++ dasturida
118
kamida bitta main () funksiyasi mavjud bo'lib, u dasturni ishga
tushirganda avtomatik ravishda chaqiriladi. Main () funksiyasi esa
boshqa funksiyalarni chaqirishi mumkin.
Har bir funksiya o'z nomiga ega va dasturda paydo bo'lganda,
boshqaruv ushbu funksiya tanasiga o'tadi. Ushbu jarayon
(yoki funksiyaga kirish) deb nomlanadi. Funksiyadan
qaytgach, dasturning bajarilishi funksiya chaqirilgandan keyingi
qatordan boshlanadi. Dasturni amalga oshirishning bunday sxemasi
10.1-rasmda ko‘rsatilgan.
Funksiyalar aniq va to'liq tushunarli vazifani bajarsa, ularni
mukammal tuzilgan funksiya deyishimiz kerak.
Funksiyalarning ikki turi mavjud: foydalanuvchi tomonidan
belgilangan ( ) va . O'rnatilgan funksiyalar
kompilyator paketining ajralmas qismi bo'lib, ishlab chiqaruvchi
tomonidan taqdim etiladi. Nostandart funksiyalar dasturchining o'zi
tomonidan yaratiladi.

10.1-rasm. Dasturda funksiyalarni chaqirish jarayoni


Funksiyalar qiymatlarni qaytarishi mumkin. Funksiyaga murojaat
qilgandan so'ng, u ba'zi amallarni bajarishi mumkin va keyin o'z
ishining natijasi sifatida ba'zi qiymatlarni qaytarib yuborishi mumkin.
U deb ataladi va bunda qiymat tipi e'lon qilinishi kerak.
Shunday qilib, yozuv
int myFunction();
myFunction funksiyasi butun qiymatni qaytarishini e'lon qiladi.
Shuningdek, siz funksiyaga ba'zi qiymatlarni yuborishingiz
mumkin. Yuborilgan qiymatlarning tavsifi parametrlar ro‘yxati deb
nomlanadi.
int myFunction(int someValue, float someFloat);

119
Ushbu prototip shuni anglatadiki, myFunction funksiyasi nafaqat
butun sonni qaytaradi, balki parametr sifatida ikkita qiymatni oladi:
butun va haqiqiy.
funksiya chaqirilganda unga o'tkaziladigan qiymat tipini
tavsiflaydi. Funksiyaga berilgan haqiqiy qiymatlar deb
ataladi.
int theValueReturned = myFunction(5,6.7);
Bu yerda butun theValueReturned o'zgaruvchisi myFunction
funksiyasi tomonidan qaytarilgan qiymat bilan boshlanadi va 5 va 6.7
qiymatlari ushbu funksiya argumentlari sifatida uzatiladi. Argumentlar
tipi e'lon qilingan parametr turlariga mos kelishi kerak.
FUNKSIYANI E'LON QILISH VA ANIQLASH
Dasturda funksiyalardan foydalanishdan avval funksiyani e'lon
qilishni va keyin aniqlashni talab qiladi. orqali
kompilyatorga uning nomi, qaytish tipi va parametrlari haqida xabar
beriladi. orqali kompilyator funksiyaning qanday
ishlashini bilib oladi. Agar u oldindan e'lon qilinmagan bo'lsa, dasturda
biror bir funksiyani chaqirish mumkin emas. deb,
dasturga parametrlar soni va turi, shuningdek funksiya qaytadigan
qiymat tipi to'g'risida ma'lumot beradigan funksiya e`loniga aytiladi.
Funksiyani e'lon qilishning uchta usuli mavjud.
 Funksiyaning prototipini faylga yozing va keyin uni dasturingizga
kiritish uchun #include ifodasidan foydalaning.
 Funksiya prototipini ushbu funksiyadan foydalanadigan faylga
yozing.
 Boshqa har qanday funksiya chaqirilishidan oldin funksiyani
aniqlang.
Bunday holda, funksiyani aniqlash bir vaqtning o'zida uni e'lon qiladi.
Funksiyani ishlatishdan oldin darhol aniqlash va shu bilan funksiya
prototipini yaratish uchta sababga ko'ra yaxshi deb hisoblanmaydi.
Birinchidan, faylda funksiyalarni ma'lum tartibda joylashtirish
talabi dasturni foydalanish shartlarini o'zgartirish jarayonida qo'llab-
quvvatlashni qiyinlashtiradi.
Ikkinchidan, a() funksiyalari b () funksiyasini chaqirishi vaziyati
bo‘lishi mumkin, ammo ba'zi holatlarda c() funksiyalari a ()
funksiyasini chaqirishi kerak bo‘lishi mumkin. Shu bilan birga, b()
funksiyasini aniqlashdan oldin a() funksiyasini va shu bilan birga a()

120
funksiyasini aniqlashdan oldin b () funksiyasini aniqlash mumkin emas,
ya'ni ushbu funksiyalardan kamida bittasi oldindan e'lon qilinishi kerak.
Uchinchidan, funksiya prototipiga ko'ra, funksiya ma'lum bir
parametrlar to'plamini qabul qilishi yoki ma'lum bir turdagi qiymatni
qaytarishi e'lon qilingan bo'lsa, u holda kompilyator ushbu xatoni
dasturni kompilyatsiya qilish bosqichida sezadi, bu esa uni amalga
oshirish jarayonida kutilmagan hodisalardan qochadi.
FUNKSIYA PROTOTIPI
Ko'pgina o'rnatilgan funksiyalarning prototiplari allaqachon
#include yordamida dasturga qo'shilgan sarlavha fayllariga yozilgan.
Foydalanuvchilar tomonidan yaratilgan funksiyalar uchun
dasturchining o'zi dasturga tegishli prototiplarni yaratishi kerak.
Funksiya prototipi nuqta-vergul bilan tugaydigan ifoda bo'lib,
funksiya sarlavhasi, qaytish qiymati tipidan iborat. Funksiya sarlavhasi
uning nomi va parametrlar ro‘yxatini anglatadi.
Prototipda va funksiyani aniqlashda qaytish tipi va sarlavhasi mos
kelishi kerak. Agar bunday moslik bo'lmasa, kompilyator xato xabarini
ko'rsatadi. Biroq, funksiya prototipida parametr nomlari bo‘lishi shart
emas, u faqat ularning turlarini ko'rsatish bilan cheklanishi mumkin.
Masalan, quyidagi prototip xato emas:
long Area(int, int);
Ushbu prototip long int tipidagi qiymatni qaytaradigan va ikkita
butun parametrlarini qabul qiladigan Area () deb nomlangan funksiyani
e'lon qiladi. Prototipning bunday yozuvi juda maqbul bo‘lsada, bu eng
yaxshi variant emas. Parametr nomlarini qo'shish prototipingizni
yanada aniqroq qiladi. Xuddi shu funksiya parametrlar nomlari bilan
aniqroq ko'rinadi:
long Area(int length, int width);
Endi funksiya nima uchun mo'ljallanganligi va uning parametrlari
darhol aniq.
E'tibor bering, har bir funksiya uchun qaytish tipi har doim ma'lum.
Agar u aniq e'lon qilinmasa, int tipi sukut bo'yicha qabul qilinadi.
Ammo, agar har bir funksiya, shu gapdan main () uchun qaytish tipi
aniq e'lon qilinsa, sizning dasturlaringiz aniqroq bo'ladi. Listing 10.3 da
Area () funksiyasining prototipini o'z ichiga olgan dastur mavjud.
Listing 10.3. Funksiyani e'lon qilish, aniqlash
1 #include <iostream>
2 using namespace std;

121
3 int Area(int yardLength; int yardWidth)
4 int main()
5{
6 int lengthOfYard;
7 int widthOfYard;
8 int areaOfYard;
9 cout << "\nHow wide is your yard? ";
10 cin >> widthOfYard;
11 cout << "\nHow long is your yard? ":
12 cin >> lengthOfYard;
13 area0fYard= Area(lengthOfYard,widthOfYard);
14 cout << "\nYour yard is ";
15 cout << area0fYard;
16 cout << " square feet\n\n";
17 return 0;
18 }
19 int Area(int yardLength; int yardWidth)
20 {
21 return yardLength * yardWidth;
22 }
Natija:
How wide is your yard? 100
How long is your yard? 200
Your yard is 20000 square feet
Tahlil:
Area () funksiyasining prototipi 4-qatorda e'lon qilinadi. Prototipni
20-qatorda ko'rsatilgan funksiya ta'rifi bilan solishtiring. E'tibor bering,
ularning nomlari, qaytish qiymatlari tiplari va parametr turlari to'liq
mos keladi. Agar ular boshqacha bo'lsa, kompilyator xato xabarni
ko'rsatgan bo'lar edi. Ularning orasidagi yagona farq shundaki, funksiya
prototipi nuqta-vergul bilan tugaydi va tanasi yo'q.
Shuni ham yodda tutingki, prototipdagi parametr nomlari - uzunlik
va kenglik ta'rifdagi parametr nomlari bilan bir xil: yardLength va
yardWidth.Funksiya - funksiya sarlavhasi va uning tanasidan iborat.
Sarlavha funksiyaning prototipiga o'xshaydi, bundan tashqari, bu holda
parametrlar nomlangan va sarlavha oxirida nuqta-vergul yo'q.

10.2-rasm Sarlavha va funktsiya tanasi

122
Funksiya tanasi figurali qavslarga olingan ifodalar to'plamidir.
Funksiya sarlavhasi va tanasi 10.2-rasmda ko'rsatilgan.
Funksiya prototipi sintaksisi:
funksiya turi funksiya nomi(parametr turi [parametr_nomi]...);
{
ifodalar;
}
Funksiya prototipi kompilyatorga qaytish tipi, funksiya nomi va
parametrlar ro‘yxatini uzatadi. Parametrlarning mavjudligi shart emas,
lekin agar ular mavjud bo'lsa, ularning tiplari prototipda e'lon qilinishi
kerak. Prototip qatori har doim nuqta-vergul (;) bilan tugaydi.
Funksiya ta'rifi qaytish turi va parametrlar ro‘yxati bo'yicha
prototipiga mos kelishi kerak. Unda barcha parametrlarning nomlari
bo‘lishi kerak va funksiyani aniqlash tanasi figurali qavslarda bo‘lishi
kerak.
Agar funksiya qiymatni qaytarsa, u return operatori bilan ifodani
o'z ichiga olishi kerak. Ushbu ifoda funksiya ta'rifining istalgan qismida
bo‘lishi mumkin, lekin odatda uni tugatadi.
FUNKSIYA PROTOTIP LARIGA MISOLLAR:
 long FindArea (long length, long width); / / long turdagi qiymatni
qaytaradi, ikkita parametrga ega.
 void PrintMessage (int messageNumber); / / void tipidagi qiymatni
qaytaradi, bitta parametrga ega
 int GetChoice (); / / int tipidagi qiymatni qaytaradi, parametrlarga
ega emas
FUNKSIYA TA'RIFLARIGA MISOLLAR:
long FindArea(long l, long w)
{
return 1 + w;
}

void PrintMessage(int whichMsg)


{
if (whichMsg == 0)
cout << "Hello.\n"
if (whichMsg == 1)
cout <<Goodbye. \n"
if (whichMsg > 1)
cout << "I'm confused.\n";
}

123
FUNKSIYALARNI BAJARISH
Funksiyani chaqirganda, uning bajarilishi ochiluvchi figurali
qavsidan ({) keyin birinchi bo'lgan ifoda bilan boshlanadi. Shuningdek,
funksiya tanasida if operatori yordamida shart bajarilishini amalga
oshirish mumkin. Funksiyalar boshqa funksiyalarni va hatto o'zlarini
ham chaqirishi mumkin(rekursiv funksiya).
Funksiyada siz nafaqat o'zgaruvchilarning qiymatlarini
o'tkazishingiz, balki funksiya tanasi ichidagi o'zgaruvchilarni ham e'lon
qilishingiz mumkin. Bu yordamida amalga
oshiriladi, ular shunday nomlanadi, chunki ular faqat funksiyaning
o'zida mavjud. Dasturning bajarilishi funksiyadan asosiy kodga
qaytganda, lokal o'zgaruvchilar xotiradan o'chiriladi.
Lokal o'zgaruvchilar boshqa o'zgaruvchilar kabi aniqlanadi.
Funksiyalarga berilgan parametrlar ham lokal o'zgaruvchilar deb
hisoblanadi va ular funksiyalar tanasida aniqlangan sifatida ishlatilishi
mumkin. Listingda funksiya parametrlari va funksiya ichida local
o'zgaruvchilardan foydalanish misoli keltirilgan.
Listing 10.4. Lokal o'zgaruvchilar va funksiya parametrlaridan
foydalanish
1 #include <iostream>
2 using namespace std;
3 float Convert(float);
4 int main()
5{
6 float TempFer;
7 float TempCel;
8 cout << "Please enter the temperature in Fahrenheit: ";
9 cin >> TempFer;
10 TempCel = Convert(TempFer);
11 cout << "\nHere's the temperature in Celsius: ";
12 cout << TempCel << endl;
13 return 0;
14 }
15 float Convert(float TempFer)
16 {
17 float TempCel;
18 TempCel = ((TempFer - 32) • 5) / 9;
19 return TempCel;
20 }
Natija:
Please enter the temperature in Fahrenheit: 212
Here's the temperature in Celsius: 100
Please enter the temperature in Fahrenheit: 32

124
Here's the temperature in Celsius: 0
Please enter the temperature in Fahrenheit: 85
Here's the temperature in Celsius: 29.4444
Tahlil:
6 va 7 - qatorlarda float tipidagi ikkita o'zgaruvchi e'lon qilinadi:
biri (TempFer) harorat qiymatini Farengeytda, ikkinchisi (TempCel)
Selsiy darajasida saqlash uchun. 9-qatorda foydalanuvchidan Farengeyt
haroratini kiritish so'raladi va bu qiymat Convert () funksiyasiga
o'tkaziladi.
Convert () funksiyasini chaqirgandan so'ng, dastur 17-satr bilan
ifodalangan ushbu funksiya tanasida birinchi ifoda bilan ishlashni
davom ettiradi, bu yerda TempCel deb nomlangan local o'zgaruvchi
e'lon qilinadi. E'tibor bering, ushbu local o'zgaruvchi 7 - qatorda e'lon
qilingan bir xil TempCel o'zgaruvchisi emas. Ushbu o'zgaruvchi faqat
Convert () funksiyasi ichida mavjud. TempFer parametri sifatida
berilgan qiymat, shuningdek, xuddi shu nomdagi o'zgaruvchining
main() funksiyasidan olingan local nusxadir.
Convert () funksiyasida siz FerTemp parametrini va local CelTemp
o'zgaruvchisini o'rnatishingiz mumkin, bu dasturning ishlashiga ta'sir
qilmaydi. Bunga ishonch hosil qilish uchun siz yangi nomlarni
kiritishingiz va dasturni qayta kompilyatsiya qilishingiz mumkin.
Lokal TempCel o'zgaruvchisiga quyidagi amallarni bajarish
natijasida olingan qiymat beriladi: TempFer parametridan 32 sonini
ayirish, bu farqni 5 soniga ko'paytirish va keyin 9 soniga bo‘lish. Keyin
hisoblash natijasi funksiyani qaytarish qiymati sifatida qaytariladi va
10-qatorda u tempcel o'zgaruvchisiga main () funksiyasiga beriladi. 12-
qatorda bu qiymat ekranda ko'rsatiladi.
Bizning misolimizda dastur uch marta ishga tushirildi.
Farangeytdagi suvning qaynash nuqtasi (212) Selsiy darajasida (100)
to'g'ri javob hosil qilishiga ishonch hosil qilish uchun birinchi marta 212
qiymati kiritiladi. Ikkinchi sinovda suvning muzlash nuqtasi qiymati
kiritiladi. Uchinchi marta esa kasr natijasini olish uchun tanlangan
tasodifiy son beriladi.
Har bir o'zgaruvchi dasturdagi o'zgaruvchining ishlash muddati va
mavjudligini belgilaydigan o'z doirasi bilan tavsiflanadi. Ba'zi bir
dastur blokida e'lon qilingan o'zgaruvchilar ushbu blok bilan
cheklangan doiraga ega. Ularga faqat ushbu blok ichida kirish mumkin
va dastur bajarilgandan so'ng, uning barcha lokal o'zgaruvchilari

125
avtomatik ravishda xotiradan o'chiriladi. Global o'zgaruvchilar global
miqyosga ega va ularga dasturning istalgan joyidan kirish mumkin.
Odatda, o'zgaruvchilar doirasi ular e'lon qilingan joyda aniq
bo'ladi, ammo ba'zi istisnolar hali ham mavjud.
Listing 10.5 Global va lokal o'zgaruvchilardan foydalanish
1 #include <iostream.h>
2 using namespace std;
3 float Convert(float);
4 int main()
5{
6 float TempFer;
7 float TempCel;
8 cout << "Please enter the temperature in Fahrenheit: ";
9 cin >> TempFer;
10 TempCel = Convert(TempFer);
11 cout << "\nHere's the temperature in Celsius: "
12 cout << TempCel << endl;
13 return 0;
14 }
15 float Convert(float Fer)
16 {
17 float Cel;
18 Cel = ((Fer - 32) 5) / 9;
19 return Cel;
20 }
Odatda, funksiyalarda o'zgaruvchilardan foydalanish, agar siz nom
berishga mas'uliyat bilan yondashsangiz va bitta funksiya ichida bir xil
nomdagi o'zgaruvchilar ishlatilmasligiga ishonch hosil qilsangiz,
muammolarga yuzaga kelmaydi.
GLOBAL O'ZGARUVCHILAR
Har qanday funksiya tanasidan tashqarida aniqlangan
o'zgaruvchilar miqyosga ega va dasturdagi har qanday
funksiyadan, shu bilan birga main () dan foydalanish mumkin.
Nomlari global o'zgaruvchilar nomlari bilan bir xil bo'lgan local
o'zgaruvchilar ikkinchisining qiymatlarini o'zgartirmaydi. Biroq,
bunday local o'zgaruvchi global o'zgaruvchini yashiradi. Agar
funksiyada global bilan bir xil nomdagi o'zgaruvchi bo'lsa, u holda
funksiya ichida ishlatilganda bu nom global emas, balki local
o'zgaruvchiga ishora qiladi.
Listing 10.6. Global va lokal o'zgaruvchilardan foydalanish
1 #include <iostream>
2 using namespace std;
3 void myFunction(): // prototip

126
4 int x = 5, y = 7; // global o'zgaruvchilar
5 int main()
6{
7 cout << "x from main: " << x << "\n";
8 cout << "y from main: " << y << "\n\n";
9 myFunction():
10 cout << "Back from myFunction!\n\n";
11 cout << "x from main: "<<x<<”/n”;
12 cout << "y from main: "<<y<<”/n”;
13 return 0;
14 }
15 void myFunction()
16 {
17 int y = 10;
18 cout << "x from myFunction: " << x << "\n";
19 cout << "y from myFunction: " << y << "\n\n";
20 }
Natija:
x from main: 5
y from main: 7
x from myFunction: 5
y from myFunction: 10
Back from myFunction!
x from main: 5
y from main: 7
Tahlil:
Ushbu oddiy dastur lokal va global o'zgaruvchilardan foydalanish
bilan bog'liq bir nechta muhim fikrlarni aks ettiradi, bu yerda yangi
dasturchilar tez-tez adashishadi. 4 - qatorda ikkita global o'zgaruvchi
e'lon qilinadi: x va y. Global o'zgaruvchi x 5 qiymati, global o'zgaruvchi
y 7 qiymati berilgan.
Main () funksiyasidagi 7 va 8-qatorlarda bu qiymatlar ekranda
ko'rsatiladi. E'tibor bering, ushbu o'zgaruvchilar main () funksiyasida
e'lon qilinmagan bo‘lsada, ular global bo'lib, allaqachon mavjud.
MyFunction () funksiyasining 9-qatoriga murojaat qilganda,
dasturning bajarilishi 15-qatordan davom etadi va 17-qatorda 10-
qiymat bilan boshlanadigan y local o'zgaruvchisi e'lon qilinadi. 18-
qatorda myFunction () funksiyasi x o'zgaruvchining qiymatini
ko'rsatadi. Bu yerda x global o'zgaruvchidan foydalanadi. Biroq, 19-
qatorda y o'zgaruvchiga murojaat qilganda y lokal o'zgaruvchining
qiymati ko'rsatiladi, xuddi shu nomdagi global o'zgaruvchi yashirin
bo'lib chiqadi.
Funksiya tanasi tugagandan so'ng, dasturni boshqarish main ()
funksiyasini qaytaradi, u yana bir xil global o'zgaruvchilarni aniqlash
127
uchun ekranga chiqadi. E'tibor bering, y global o'zgaruvchiga
myFunction () funksiyasida lokal o'zgaruvchiga qiymat berish umuman
ta'sir qilmagan.
GLOBAL O'ZGARUVCHILAR
Shuni ta'kidlash kerakki, C++ da global o'zgaruvchilar deyarli hech
qachon ishlatilmaydi. C++ tili C tilidan kelib chiqdi, bu yerda global
o'zgaruvchilardan foydalanish har doim xatolarning paydo bo‘lishi
bilan to'la edi. Global o'zgaruvchilar dasturchi ko'plab funksiyalar
uchun ma'lumotlarni taqdim etishi kerak bo'lgan va parametr sifatida
funksiyadan funksiyaga ma'lumotlarni uzatish muammoli bo'lgan
hollarda talab qilinadi.
Global o'zgaruvchilardan foydalanish xavfi ularning umumiy
mavjudligidan kelib chiqadi, natijada bitta funksiya o'zgaruvchining
qiymatini boshqa funksiya sezmagan holda o'zgartirishi mumkin.
Bunday vaziyatlarda aniqlash juda qiyin bo'lgan xatolar paydo bo‘lishi
mumkin.
LOKAL O’ZGARUVCHILAR HAQIDA KO'PROQ
MA'LUMOT
Funksiya ichida e'lon qilingan o'zgaruvchilar local doiraga ega
ekanligi aytiladi. Bu shuni anglatadiki, yuqorida aytib o'tilganidek, ular
ko'rinadigan va faqat belgilangan funksiya doirasida foydalanish
mumkin. Aslida, C++ da o'zgaruvchilarni faqat boshida emas, balki
funksiyaning istalgan joyida aniqlash mumkin. O'zgaruvchining
ko'lami u aniqlangan blokdir. Shunday qilib, agar funksiya tanasida bir
juft figurali qavs bilan ajratilgan blok bo'lsa va ushbu blokda
o'zgaruvchi e'lon qilinsa, u Listing 10.7 da ko'rsatilganidek, butun
funksiyada emas, balki faqat blok ichida mavjud bo'ladi.
Listing 10.7. Lokal o’zgaruvchilarning ko'rinishi
1 #include <iostream>
2 using namespace std;
3 void myFunc();
4 int main()
5{
6 int x = 5;
7 cout << "\nIn main x is: " << x;
8 myFunc();
9 cout << "\nBack in main, x is: " << x;
10 return 0;
11 }
12 void myFunc()
13 {

128
14 int x = 8;
15 cout << "\nIn myFunc, local x: " << x << endl;
16 {
17 cout << "\nIn blok in myFunc, x is: " << x;
18 int x = 9;
19 cout << "\nVery local x: " << x;
20 }
21 cout << "\n0ut of blok, in myFunc, x: " << x << end1;
22 }
Natija:
In main x is: 5
In myFunc, local x: 8
In blok in myFunc, x is: 8
Very local x: 9
Out of blok, in myFunc, x: 8
Back in main, x is: 5
Tahlil:
Ushbu dastur main () funksiyasida lokalo'zgaruvchini ishga
tushirish bilan boshlanadi (6-qator). 8-qatorda ko'rsatilgan x
o'zgaruvchining qiymati x o'zgaruvchining rostan ham 5 soni bilan
boshlanganligini tekshirishga imkon beradi. Keyin dasturda myFunc ()
funksiyasi chaqiriladi, uning tanasida 16-qatorda bir xil x nomli lokal
o'zgaruvchi e'lon qilinadi va 8 qiymati bilan ishga tushiriladi. Ushbu
qiymat 17-qatorda ko'rsatiladi.
Blok 18-qatordan boshlanadi va 19-qatorda x local o'zgaruvchining
qiymati yana ko'rsatiladi. Ammo 20-qatorda xuddi shu nomdagi yangi
o'zgaruvchi yaratiladi x, bu berilgan blokga nisbatan lokal hisoblanadi.
Ushbu o'zgaruvchi darhol 9 qiymati bilan ishga tushiriladi.
Yaratilgan oxirgi o'zgaruvchining qiymati x ekranda 21-qatorda
ko'rsatiladi. Lokal blok 22-qator bilan tugaydi va 20-qatorda yaratilgan
o'zgaruvchi ko'rinmaydi va xotiradan o'chiriladi.
23-qatorda 16-qatorda e'lon qilingan x o'zgaruvchining qiymati
ko'rsatiladi. 23-qatorda yangi x o'zgaruvchining ta'rifi unga hech
qanday ta'sir ko'rsatmadi va uning qiymati hali ham 8 ga teng.
24-qatorda myFunc () funksiyasining ko'lami tugaydi va uning
local o'zgaruvchisi x mavjud bo'lmaydi. Dasturni boshqarish 11-
qatorga qaytadi, unda 8-qatorda yaratilgan lokal x o'zgaruvchisining
qiymati ko'rsatiladi. myFunc () funksiyasida belgilangan bir xil
nomdagi o'zgaruvchilardan hech biri unga ta'sir qilmasligiga o'zingiz
ishonch hosil qilishingiz mumkin.

129
FUNKSIYALARDA ISHLATILADIGAN OPERATORLAR
Aslida, funksiyalarda ishlatiladigan operatorlarning soni yoki
turlariga hech qanday cheklovlar qo'yilmaydi. Shuningdek, funksiya
ichida boshqa funksiyani aniqlash mumkin bo'lmasa-da, lekin bitta
funksiyadan siz xohlagancha boshqa funksiyalarni chaqirishingiz
mumkin; deyarli har bir C++dasturida main() funksiyasi aynan shunday
qiladi. Bundan tashqari, funksiyalar hatto o'zlarini ham chaqirishi
mumkin (bu holat rekursiya bo'limida ko'rib chiqiladi).
C++ da funksiya hajmi ham cheklanmagan bo‘lsada, funksiya
tanasi cheksiz miqyosga o'smasligi yaxshiroqdir. Ko'pgina
mutaxassislar ekranning bitta sahifasini egallagan funksiyalarning
kichik hajmini saqlashni maslahat berishadi va shu bilan butun
funksiyani to'liq ko'rishga imkon beradi. Ammo, funksiya qanchalik
kichik bo'lsa, tushunish va keyingi o‘zgartirish osonroq bo'ladi.
Har bir funksiya tushunish oson bo'lgan bitta vazifani bajarishi
kerak. Agar funksiya kengayishni boshlaganini sezsangiz, yangi
funksiyani yaratish vaqti keldimi yoki yo'qligini o'ylab ko'ring.
Funksiya argumentlari har xil bo‘lishi mumkin. Masalan, bitta int
tipidagi qiymatni, ikkita long tipdagi qiymatlarni va bitta belgi
argumentini o'z argumentlari sifatida qabul qiladigan funksiyani yozish
juda maqbuldir.
Funksiya argumenti har qanday C++ ifodasi bo‘lishi mumkin,
masalan, konstantalar, matematik va mantiqiy ifodalar va ba'zi
qiymatlarni qaytaradigan boshqa funksiyalarni olish mumkin.
Bitta funksiya uchun ma'lum bir qiymatni qaytaradigan parametr
sifatida ikkinchi funksiyani olish juda mumkin bo‘lishiga qaramay,
ushbu dasturlash usuli dasturni o'qishni va uni disk raskadrovka qilishni
qiyinlashtiradi.
Misol tariqasida, y sizda ba'zi qiymatlarni qaytaradigan double(),
triple(), square() va cube () funksiyalari mavjud deb taxmin qiling. Siz
quyidagi ko'rsatmalarni yozishingiz mumkin:
Answer = (double(triple(square(cube(myValue)))));
Ushbu ko'rsatma myValue o'zgaruvchisini oladi va uni cube ()
funksiyasiga argument sifatida uzatadi, uning qaytish qiymati (son
kubi) square () funksiyasiga argument sifatida uzatiladi. Shundan so'ng,
square () funksiyasining qaytish qiymati (sonning kvadrati) o'z
navbatida triple () funksiyasining argumenti sifatida uzatiladi. Keyin
triple () funksiyasining qaytish qiymati (uch baravar) double ()
130
funksiyasining argumenti sifatida uzatiladi. Nihoyat, double ()
funksiyasining qaytish qiymati (ikki baravar) Answer o'zgaruvchisiga
beriladi.
Ushbu ifoda qanday muammoni hal qilishi haqida to'liq ishonch
bilan gapirish qiyin (kvadratni hisoblashdan oldin yoki keyin qiymat
uch baravar oshirilganmi?); bundan tashqari, noto'g'ri natija bo'lsa,
"aybdor" funksiyani aniqlash juda qiyin bo'ladi. Muqobil variant
sifatida har bir oraliq hisoblash natijasi oraliq o'zgaruvchiga
tayinlanishi mumkin:
unsigned long myValue = 2;
unsigned long cubed = cube(myValue); // 2 kubda = 8
unsigned long squared = square (cubed); / / 8 kvadrat = 64
unsigned long tripled = triple(squared); // 64 * 3 = 192
unsigned long Answer = double(tripled); // 192 * 2 = 384
Endi siz har bir oraliq natijani osongina tekshirishingiz mumkin va
shu bilan birga barcha hisob-kitoblarni bajarish tartibi aniq.
Funksiyaga berilgan argumentlar berilgan funksiyaga nisbatan
lokaldir. Funksiyani bajarish paytida argumentlarga kiritilgan
o'zgarishlar funksiyaga o'tkaziladigan o'zgaruvchilarga ta'sir qilmaydi.
Parametrlarni uzatishning bu usuli qiymat sifatida uzatish deb
nomlanadi, ya'ni har bir argumentning local nusxasi funksiyaning o'zida
yaratiladi. Tashqi o'zgaruvchilarning bunday local nusxalari boshqa har
qanday lokal funksiya o'zgaruvchilari kabi qayta ishlanadi.
Listing 10.8 Parametrlarni qiymat sifatida uzatish
1 #include <iostream>
2 using namespace std;
3 void swap(int x, int y);
4 int main()
5{
6 int x = 5, y = 10;
7 cout << "Main. Before swap, x: " << x << " y: " << y << "/n”;
8 swap(x,y);
9 cout << "Main. After swap, x: " << x << " y: " << y << "/n”;
10 return 0;
11 }
12 void swap (int x, int y)
13 {
14 int temp;
15 cout << "Swap. Before swap, x: " << x << " y: " << y << "\n";
16 temp = x;
17 x=y;
18 y = temp;
19 cout << "Swap. After swap, x: " << x << " y: " << y << "n";
20 }

131
Natija:
Main. Before swap, x: 5 y: 10
Swap. Before swap, x: 5 y: 10
Swap. After swap, x: 10 y: 5
Main. After swap, x: 5 y: 10
Tahlil:
Dastur main () funksiyasidagi ikkita o'zgaruvchini ishga tushiradi
va keyin ularning qiymatlari swap () funksiyasiga o'tkaziladi, bu
ularning qiymatlarini o'zgartirishi kerak. Biroq, ushbu o'zgaruvchilarni
main () funksiyasida qayta tekshirgandan so'ng, ular o'zgarmaganligi
ma'lum bo'ldi.
Ushbu o'zgaruvchilar 7-qatorda ishga tushiriladi va ularning
qiymatlari ekranda 8-qatorda ko'rsatiladi. Keyin swap () funksiyasi
chaqiriladi va bu o'zgaruvchilar unga argument sifatida uzatiladi.
Dasturning bajarilishi swap () funksiyasiga o'tkaziladi, bu yerda
20-qatorda bizga tanish bo'lgan o'zgaruvchilarning qiymatlari yana
ko'rsatiladi. Kutilganidek, ularning funksiyadan funksiyaga o'tish
qiymatlari o'zgarmadi. 17-19-qatorlarda o'zgaruvchilar o'z qiymatlari
bilan o'zgaradi, bu 20-qatorda keyingi tekshirish bilan tasdiqlanadi.
Ammo bu pozitsiya faqat dastur swap () funksiyasidan chiqmaguncha
davom etadi.
Keyin dasturni boshqarish qiymatlarini qaytarib olganligini va
funksiyada sodir bo'lgan barcha o'zgarishlar bekor qilinganligini
ko'rsatadi.
Eslatib o'tamiz, bu holda o'zgaruvchilar swap() funksiyasiga
qiymat sifatida uzatiladi, ya'ni swap() funksiyasi ushbu funksiyaga
nisbatan local bo'lgan ushbu qiymatlarning nusxalarini yaratdi. 17-19-
qatorlarda bajarilgan qiymat almashinuvi ushbu lokal o'zgaruvchilarda
amalga oshirildi, ammo bu main () funksiyasida qolgan
o'zgaruvchilarga hech qanday ta'sir ko'rsatmadi.
RETURN QIYMATLAR HAQIDA KO'PROQ MA'LUMOT
Funksiyalar haqiqiy qiymatni yoki void tipidagi qiymatni
qaytaradi, bu kompilyator uchun hech qanday qiymat qaytarilmasligi
uchun signal bo'lib xizmat qiladi.
Funksiyadan qiymatni qaytarishni ta'minlash uchun return kalit
so'zini va undan so‘ng qaytarilishi kerak bo'lgan qiymatni yozing.
Qaytish sifatida siz o‘zgarmas qiymatlarni ham, butun ifodalarni ham
o‘zlashtirishingiz mumkin, masalan:

132
return 5;
return (x > 5);
return (MyFunction());
Agar MyFunction() funksiyasi faqat ma'lum bir qiymatni
qaytarishi kerak bo‘lsa, funksiyalarni qaytarish uchun 1-ifodadan
foydalaniladi. Ikkinchi ifoda, return (x > 5), agar x 5 dan katta bo'lmasa,
= yoki <= 5 dan bo'lsa, noto'g'ri bo'ladi. Shunday qilib, agar qaytarishda
mantiqiy ifoda berilgan bo'lsa, u holda x o'zgaruvchisining qiymatlari
emas, balki false yoki true (noto'g'ri yoki rost) mantiqiy qiymatlari
qaytariladi.
Funksiyada return kalit so'zi paydo bo'lgandan so'ng ushbu kalit
so'z ortidagi ifoda bajariladi va uning natijasi funksiya chaqiriladigan
joyda asosiy dasturga qaytariladi. Qaytish operatorini bajargandan
so'ng dastur darhol funksiyani chaqirgandan so'ng keyingi qatorga
o'tadi va return kalit so'zidan keyin funksiya tanasida turgan har qanday
ifodalar bajarilmaydi.
Biroq, funksiya bir nechta return operatorlarini o'z ichiga olishi
mumkin.
Listing 10.9. Bir nechta return operatorlaridan foydalanish
1 #include <iostream>
2 using namespace std;
3 int Doubler(int AmountToDouble);
4 int main()
5{
6 int result = 0;
7 int input;
8 cout << "Enter a number between 0 and 10,000 to double: ";
9 cin >> input;
10 cout << "\nBefore doubler is called…";
11 cout << "\ninput: " << input << " doubled: " << result << "\n";
12 result = Doubler(input);
13 cout << "\nBack from Doubler…\n";
14 cout << "\ninput: " << input << " doubled: " << result << "\n";
15 return 0:
16 }
17 int Doubler(int original)
18 {
19 if (original <= 10000)
20 return original * 2;
21 else
22 return -1;
23 cout << "You can't get here!\n"
24 }
Natija:
Enter a number between 0 and 10,000 to double: 9000
Before doubler is called…
input: 9000 doubled: 0

133
Back from doubler…
input: 9000 doubled: 18000
Enter a number between 0 and 10,000 to double: 11000
Before doubler is called…
input: 11000 doubled: 0
Back from doubler…
input: 11000 doubled: -1
Tahlil:
11-qatorda dastur foydalanuvchiga sonni kiritishni taklif qiladi va
uni input o'zgaruvchisida saqlaydi. 13-qatorda siz kiritgan son local
result o'zgaruvchisining qiymati bilan birga ko'rsatiladi. 14-qatorda
Doubler () funksiyasi chaqiriladi va kiritilgan qiymat unga parametr
sifatida uzatiladi. Funksiya natijasi local result o'zgaruvchisiga beriladi
va 16-qatorda ushbu o'zgaruvchilarning qiymatlari yana ko'rsatiladi.
Doubler () funksiyasiga tegishli 21-qatorda o'tkazilgan parametr
qiymati 10000 soni bilan taqqoslanadi. Agar u 10000 dan oshmasa,
funksiya asl sonning ikki baravar qiymatini qaytaradi. Agar u 10000
dan katta bo'lsa, funksiya xato xabari sifatida -1 sonini qaytaradi.
25-qatordagi ifodaga hech qachon o‘tmaydi, chunki uzatilgan
parametrning har qanday qiymati uchun (10 000 dan katta yoki yo'q)
funksiyadan qaytish 22-qatorda yoki 24-qatorda amalga oshiriladi,
ammo har qanday holatda ham 25-qatorga o‘tmaydi.
STANDART PARAMETR QIYMATLARI
Prototip va funksiya ta'rifida e'lon qilingan har bir parametr uchun
funksiya chaqiruvida tegishli qiymat o'tkazilishi kerak. O'tkazilgan
qiymat e'lon qilingan tipga ega bo‘lishi kerak. Agar e'lon qilingan
parametr turi uzatilgan argument tipiga to'g'ri kelmasa, kompilyator
xato haqida xabar beradi.
long myFunction (int x = 50);
Ushbu prototipni quyidagicha tushunish kerak. MyFunction
funksiyasi long tipdagi qiymatni qaytaradi va int tipidagi parametrni
oladi. Agar ushbu funksiyani chaqirganda argument berilmasa, uning
o'rniga 50 sonidan foydalaniladi. Shuningdek, funksiyalarning
prototiplarida parametr nomlari talab qilinmaganligi sababli, funksiya
e`lonning oxirgi versiyasi boshqacha tarzda ham yozilishi mumkin:
long myFunction (int = 50);
Standart parametr qiymati e'lon qilinganda funksiya ta'rifi
o'zgarmaydi. Shuning uchun ushbu funksiyaning sarlavhasi avvalgidek
bo‘ladi:

134
long myFunction (int x);
Agar ushbu funksiyani chaqirganda argument o'rnatilmagan bo'lsa,
u holda kompilyator x o'zgaruvchisiga 50 qiymatini beradi. Prototipda
standart qiymat o'rnatilgan parametr nomi funksiya sarlavhasida
ko'rsatilgan parametr nomiga mos kelmasligi mumkin: avtomatik
berilgan qiymat nom bilan emas, balki pozitsiya bilan belgilanadi.
Standart qiymatlarni bir yoki barcha funksiya parametrlariga
o‘zlashtirish mumkin. Ammo bitta cheklov amal qiladi: agar biror bir
parametr standart qiymatga ega bo'lmasa, unga nisbatan oldingi
parametrlarning hech biri standart qiymatga ega bo'lmaydi.
Funksiya prototipining ko‘rinishi quyidagicha:
long myFunction (int Param1, int Param2, int Param3);
keyin Param2 parametriga standart qiymat berilishi mumkin, agar
standart qiymat Param3 parametriga o‘zlashtiringan bo'lsa. Param1
parametriga faqat Param2 parametriga ham, Param3 parametriga ham
standart qiymatlar o‘zlashtiringan taqdirdagina standart qiymat berilishi
mumkin.
Listing 10.10. Funksiya parametrlari
1 #include <iostream>
2 using namespace std;
3 int VolumeCube(int length, int width = 25, int height = 1);
4 int main(){
5 int length = 100;
6 int width = 50;
7 int height = 2;
8 int volume;
9 volume = VolumeCube(length, width, height);
10 cout << "First volume equals: " << volume << "\n";
11 volume = VolumeCube(length, width);
12 cout << "Second time volume equals: " << volume << "\n";
13 volume = VolumeCube(length);
14 cout << "Third time volume equals: " << volume << "\n";
15 return 0;}
16 VolumeCube(int length, int width, int height){
17 return (length width height);}
Natija:
First volume equals: 10000
Second time volume equals: 5000
Third time volume equals: 2500
Tahlil:
5-qatorda VolumeCube () funksiyasining prototipi funksiya uchta
parametrni qabul qilishini e'lon qiladi, oxirgi ikkitasi sukut bo'yicha
o'rnatiladi.
135
Ushbu funksiya uzatilgan o'lchamlarga asoslanib parallelepiped
hajmini hisoblab chiqadi. Agar kenglik qiymati o'tkazilmasa, u holda
kenglik 25 ga, balandlik esa 1 ga teng bo‘ladi. Agar kenglik qiymati
uzatilsa va balandlik qiymati bo'lmasa, u holda faqat balandlik qiymati
sukut bo'yicha o'rnatiladi. Ammo kenglik qiymatini uzatmasdan
balandlik qiymatini funksiyaga o'tkazish mumkin emas.
7-9-qatorlarda parallelepiped o'lchamlarini uzunligi, kengligi va
balandligi bo'yicha saqlash uchun mo'ljallangan o'zgaruvchilar ishga
tushiriladi. Ushbu qiymatlar 11-qatorda VolumeCube() funksiyasiga
o'tkaziladi. Parallelepiped hajmini hisoblab chiqqandan so'ng, natija 12-
qatorda ko'rsatiladi.
13-qatorda VolumeCube () funksiyasi yana chaqiriladi, lekin
balandlik uchun qiymati berilmaydi. Bunday holda, parallelepiped
hajmini hisoblash uchun sukut bo'yicha berilgan balandlik qiymati
ishlatiladi va natijada 14-qatorda ko'rsatiladi. VolumeCube ()
funksiyasining uchinchi chaqiruvida (15-qator) kenglik qiymati ham,
balandlik qiymati ham o'tkazilmaydi. Shuning uchun ularning o'rniga
sukut bo'yicha belgilangan qiymatlar ishlatiladi va natijada 16-qatorda
ko'rsatiladi.
Tavsiya etiladi!
 Esda tutingki, funksiya parametrlari uning ichida local
o'zgaruvchilar kabi ishlaydi.
Tavsiya etilmaydi!
 Agar ikkinchi parametr uchun sukut bo'yicha ishlatiladigan qiymat
berilmagan bo'lsa, birinchi parametr uchun standart qiymatni
o'rnatmang.
 Funksiyaga qiymat sifatida berilgan argumentlar funksiyani
chaqirishda ishlatiladigan o'zgaruvchilarga ta'sir qila olmasligini
unutmang.
 Shuni unutmangki, bitta funksiyadagi global o'zgaruvchiga
kiritilgan o'zgarishlar ushbu o'zgaruvchining barcha funksiyalar uchun
qiymatini o'zgartiradi.
C++ tilida bir xil nomdagi bir nechta funksiyalarni yaratish
imkoniyati mavjud. Bunga
deyiladi. Qo‘shimcha yuklangan funksiyalar parametrlar ro‘yxati bilan
bir-biridan farq qilishi kerak, ya`ni bir yoki bir nechta parametrlarning

136
tipi yoki har xil parametrlar soni yoki ikkalasi bir vaqtning o'zida.
Quyidagi misolni ko'rib chiqing:
int myFunction (int, int);
int myFunction (long, long);
int myFunction (long);
myFunction () funksiyasi uch xil parametrlar ro‘yxati bilan qo‘shimcha
yuklangan. Birinchi va ikkinchi versiyalar parametr tiplari bilan,
uchinchisi esa ularning soni bilan farq qiladi.
Qo‘shimcha yuklangan funksiyalarning qaytish qiymatlari tiplari
bir xil yoki har xil bo‘lishi mumkin.
Funksiyalarning qo‘shimcha yuklanishi deb
ham ataladi. Poli - ko'p, morfe – ko‘rinish, ya'ni polimorfik funksiya-
bu ko‘rinishilarning xilma-xilligi bilan ajralib turadigan funksiya.
Funksiyaning polimorfizmi deganda dasturda turli maqsadlarga ega
bo'lgan funksiyaning bir nechta qo‘shimcha yuklangan versiyalari
mavjudligi tushuniladi. Parametrlar sonini yoki tipini o'zgartirib, ikki
yoki undan ortiq funksiyaga bir xil nom berilishi mumkin.
Aytaylik, siz unga berilgan har qanday qiymatni ikki baravar
oshiradigan funksiyani yaratyapsiz. Shu bilan birga, siz unga int, long,
float yoki double kabi tiplarni berishni xohlaysiz. Funksiyalarni
qo‘shimcha yuklamasdan, siz to'rt xil funksiyani yaratishingiz kerak
bo'ladi:
int DoubleInt(int);
long DoubleLong(long);
float DoubleFloat(float);
double DoubleDouble(double);
Funksiyalarni qo‘shimcha yuklash orqali quyidagi e`lonlardan
foydalanish mumkin:
int Double(int);
long Double(long);
float Double(float);
double Double(double);
Qo‘shimcha yuklangan funksiyalardan foydalangan holda,
dasturda uzatiladigan o'zgaruvchilar tipiga mos keladigan kerakli
funksiyani chaqirish haqida tashvishlanishning hojati yo'q. Qo‘shimcha
yuklangan funksiyani chaqirganda, kompilyator avtomatik ravishda
qaysi funksiya variantidan foydalanish kerakligini aniqlaydi.
Funksiyaning haddan tashqari yuklanishi Listing 10.11 da ko'rsatilgan.
Listing 10.11 Funksiyalarning polimorfizmi
1 #include <iostream>
2 using namespace std;

137
3 int Double(int);
4 long Double(long);
5 float Double(float);
6 double Double(double);
7 int main()
8{
9 int myInt = 6500;
10 long myLong = 65000;
11 float myFloat = 6.5F;
12 double myDouble = 6.5e20;
13 int doubledInt;
14 long doubledLong;
15 float doubledFloat;
16 double doubledDouble;
17 cout << "myInt: " << myInt << "\n";
18 cout << "myLong: " << myLong << " n";
19 cout << "myFloat: " << myFloat << "\n";
20 cout << "myDouble: " << myDouble << "\n";
21 doubledInt = Double(myInt);
22 doubledLong = Double(myLong);
23 doubledFloat = Double(myFloat):
24 doubledDouble = Double(myDouble);
25 cout << "doubledInt: " << doubledInt << "\n";
26 cout << "doubledLong: " << doubledLong << "\n";
27 cout << "doubledFloat: " << doubledFloat << "\n";
28 cout << "doubledDouble: " << doubledDouble << " n";
29 return 0;
30 }
31 int Double(int original)
32 {
33 cout << "In Double(int)\n";
34 return 2 * original;
35 }
36 long Double(long original)
37 {
38 cout << "In Double(long)\n";
39 return 2 original;
40 }
41 float Double(float original)
42 {
43 cout << "In Double(float)\n";
44 return 2 + original;
45 }
46 double Double(double original)
47 {
48 cout << "In Double(double)\n";
49 return 2 + original;
50 }
Natija:
myInt: 6500

138
myLong: 65000
myFloat: 6.5
myDouble: 6.5e+20
In Double(int)
In Double(long)
In Double(float)
In Double(double)
DoubledInt: 13000
DoubledLong: 130000
DoubledFloat: 13
DoubledDouble: 1. 3e+21
Tahlil:
Double () funksiyasi to'rt tipdagi parametrlarni qabul qilish uchun
qo‘shimcha yuklanadi: int, long, float va double. Funksiyalarning
prototiplari 3-6 qatorlarni, ta'riflar esa 31-50 qatorlarni egallaydi.
Asosiy dastur tanasida 8 ta lokal o'zgaruvchilar e'lon qilinadi. 17-
20-qatorlarda dastlabki to'rtta o'zgaruvchi ishga tushiriladi va 25-28-
qatorlarda qolgan to'rtta o'zgaruvchiga Double() funksiyasining
dastlabki to'rtta o'zgaruvchisining qiymatlarini uzatish natijalari
beriladi. E'tibor bering, murojaat turi bo'yicha bu funksiyalar bir-
biridan farq qilmaydi.
Nazorat savollari va topshiriqlar:
1. Funksiya prototipini e'lon qilish va funksiyani aniqlash o'rtasidagi
farq nima?
2. Prototipda ko'rsatilgan parametr nomlari, funksiya ta'rifi va chaqiruvi
bir-biriga mos kelishi kerakmi?
3. Agar funksiya qiymatni qaytarmasa, qanday qilib bunday funksiyani
e'lon qilish kerak?
4. Lokal o'zgaruvchi nima? Rekursiya nima?
5. Global o'zgaruvchilardan qachon foydalanish kerak?
6. Perimetr funksiyasining ta'rifini 1-mashqdagi e'longa muvofiq
yozing. U qabul qilgan ikkita parametr to'rtburchakning uzunligi,
kengligini anglatadi va funksiya uning perimetrini qaytaradi.
7. Xatolar: bu funksiyada nima noto'g'ri?
#include <iostream>
using namespace std;
void myFunc(unsigned short int x);
int main()
{
unsigned short int x, y;
y = myFunc(int);
cout << "x: " << x << " y: " << y << "\n";
}
void myFunc(unsigned short int x)

139
{
return (4*x);
}
8. a haqiqiy va n butun sonlari berilgan(n>0). a n = a ⋅ a ⋅ ... ⋅ a. (a, n
marta ko‘paytirilgan) a ning n- darajasi hisoblansin.
1,5 2 2,25
9. Sonlar o‘qida 2 ta haqiqiy a, b (a<b) sonlar va n butun son (n>1)
berilgan. [a,b] kesma n ta teng kesmaga bo‘lingan. Kesmachalar
uzunligi h ni hamda (a,a+h, a+2h, …, b). [a,b] kesmani bo‘lishdan hosil
bo‘lgan nuqtalar soni chiqarilsin.
1.0 3.0 5 0.4 1 1.4 1.8 2.2 2.6 3.0

140
11-MAVZU. FUNKSIYANING MASSIVLI
PARAMETRLARI.
 Argumentlarni qiymat va havola orqali yuborish
 Constant havolalar (o‘zgarmas havolalar)
 Funksiya parametrida massiv
Siz massivlarni funksiyaga o'tkazishingiz mumkin: Misolda
funksiya (myFunction) parametr sifatida massivni oladi (int
myNumbers[5]). Funksiyani chaqirganda, uni argument sifatida
o'tkazishda faqat massiv nomidan foydalanish kerak
myFunction(myNumbers). Biroq, massiv to'liq e`lon qilinishi uchun
parametr sifatida massiv o‘lchami berilishi zarur (int myNumbers[5]).
void myFunction(int myNumbers[5]) {
for (int i = 0; i < 5; i++) {
cout << myNumbers[i] << "\n";
}
}
int main() {
int myNumbers[5] = {10, 20, 30, 40, 50};
myFunction(myNumbers);
return 0;
}
C++ butun massivni funksiyaga argument sifatida o'tkazishga
ruxsat bermaydi. Biroq, siz indekssiz massiv nomini ko'rsatib,
ko'rsatgichni massivga o'tkazishingiz mumkin. Agar siz bitta o'lchovli
massivni funktsiyadagi argument sifatida o'tkazmoqchi bo'lsangiz,
funksiyani quyidagi uchta usuldan birida e'lon qilishingiz kerak bo'ladi:

Formal parametrlar quyidagicha ko'rsatgich sifatida:


void myFunction(int *param) { . }

Formal parametrlar quyidagicha massiv sifatida:


void myFunction(int param[10]) { . }

Rasmiy parametrlar quyidagicha o'lchamsiz qator sifatida:


void myFunction(int param[]) { . }
Quyidagi dastur bilan tanishamiz:
double getAverage(int arr[], int size) {
int i, sum = 0;
double avg;
for (i = 0; i < size; ++i) {
sum += arr[i];
}
141
avg = double(sum) / size;
return avg;
}
yuqoridagi funksiyani quyidagicha chaqiramiz.
Listing 11.1.
#include <iostream>
using namespace std;
double getAverage(int arr[], int size);
int main () {
int balance[5] = {1000, 2, 3, 17, 50};
double avg;
avg = getAverage( balance, 5 ) ;
cout << "Average value is: " << avg << endl;
return 0;
}
Yuqoridagi kod birgalikda tuzilganda va bajarilganda, u quyidagi
natijani beradi.
Average value is: 214.4
Argumentlar funksiyaga qiymat bo'yicha va havolalar bo'yicha
yuborilishi mumkin. Argumentlarni qiymat bo'yicha uzatishda
funksiyaga argument sifatida uzatiladigan tashqi obyektni ushbu
funksiyada o'zgartirish mumkin emas. Ushbu obyektning qiymati
funksiyaga uzatiladi.
Listing 11.2.
1 #include <iostream>
2 using namespace std;
3 void square(int, int);
4 int main()
5{
6 int a = 4;
7 int b = 5;
8 cout << "Before: a = " << a << "\tb=" << b << endl;
9 square(a, b);
10 cout << "After: a = " << a << "\tb=" << b << endl;
11 return 0;
12 }
13 void square(int a, int b)
14 {
15 a = a * a;
16 b = b * b;
17 cout << "In square: a = " << a << "\tb=" << b << endl;
18 }
Kvadrat funksiyadagi argumentlarning o'zgarishi faqat shu
funksiya doirasida o‘zgarishini ko'ramiz. Uning qiymatidan tashqarida
a va b o'zgaruvchilari o'zgarishsiz qoladi:

142
Funksiyani kompilyatsiya qilishda uning parametrlari uchun
alohida xotira bo'limlari ajratiladi. Funksiya chaqirilganda, parametrlar
o'rniga uzatiladigan argumentlarning qiymatlari hisoblanadi. Keyin
argumentlarning qiymatlari ushbu xotira bo'limlariga kiritiladi. Ya'ni,
funksiya obyektlarning o'zlarini emas, balki obyektlar qiymatlarining
nusxalarini boshqaradi.
Parametrlarni havola orqali uzatishda obyektga havola uzatiladi,
bu orqali biz uning qiymatini emas, balki obyektlarning o'zini
boshqarishimiz mumkin. Shunday qilib, avvalgi misolni havola orqali
uzatish yordamida qayta yozamiz:
Listing 11.3.
#include <iostream>
using namespace std;
void square(int &, int &);
int main()
{
int a = 4;
int b = 5;
cout << "Before square: a = " << a << "\tb="<< b << endl;
square(a, b);
cout << "After square: a = " << a <<"\tb=" << b << endl;
return 0;
}
void square(int &a, int &b)
{
a = a * a;
b = b * b;
cout << "In square: a = " << a <<"\tb=" << b << endl;
}
Havola orqali uzatish funksiyadan bir vaqtning o'zida bir nechta
qiymatlarni qaytarishga imkon beradi. Shuningdek, parametrlarni
havola orqali uzatish juda katta obyektlarni uzatishda samaraliroq.
Chunki bu holda qiymatlarni nusxalash sodir bo'lmaydi va funksiya
obyektning o'zi emas, balki uning qiymatidan foydalanadi.
Listing 11.4. Argumentlarni havola orqali uzatishdan, havolalarni
argument sifatida uzatishni farqlash kerak:

143
#include <iostream>
1
using namespace std;
2
void square(int, int);
3
int main()
4
{
5
int a = 4;
6
int b = 5;
7
int &aRef = a;
8
int &bRef = b;
9
cout << "Before square: a = " << a << "\tb="<< b <<
10
endl;
11
square(aRef, bRef);
12
cout << "After square: a = " << a <<"\tb=" << b << endl;
13
return 0;
14
}
15
void square(int a, int b)
16
{
17
a = a * a;
18
b = b * b;
19
cout << "In square: a = " << a <<"\tb=" << b << endl;
20
}
Agar funksiya qiymat bo'yicha argumentlarni qabul qilsa, u holda
funksiya ichidagi parametrlarning o'zgarishi tashqi obyektlarga ham
ta'sir qilmaydi, hatto funksiya chaqirilganda obyektlarga havolalar unga
o'tkazilsa ham.
Parametrlarni qiymat bo'yicha uzatish kichik obyektlarni
funksiyaga o'tkazish uchun ko'proq mos keladi, ularning qiymatlari
keyinchalik funksiya foydalanadigan xotiraning ma'lum qismlariga
ko'chiriladi.
Parametrlarni havola orqali uzatish katta obyektlarni funksiyaga
o'tkazish uchun ko'proq mos keladi, bu holda siz obyektning barcha
tarkibini xotira maydoniga nusxalashingiz shart emas, buning natijasida
dasturning ishlashi oshadi.
Agar funksiya mos havolalar bo'yicha argumentlarni qabul qilsa, u
holda funksiyaga o‘zgarmasni(constant) o'tkazish uchun parametrlar
ham o‘zgarmasga havolani ko'rsatishi kerak.
FUNKSIYA PARAMETRIDA MASSIV
Agar funksiya massivni parametr sifatida qabul qilsa, aslida
ko'rsatgich massivning birinchi elementiga ushbu funksiyaga
o'tkaziladi. Ya'ni, ko'rsatgichlarda bo'lgani kabi, biz qiymatlarni
o'zgartirishimiz mumkin bo'lgan manzilga egamiz. Shuning uchun
quyidagi funksiya e`lonlari teng kuchli:
void print(int numbers[]);
144
void print(int *numbers);
Listing 11.5.
1 #include <iostream>
2 void print(int []);
3 int main()
4{
5 int nums[] = {1, 2, 3, 4, 5};
6 print(nums);
7 return 0;
8}
9
10 void print(int numbers[])
11 {
12 for(int i=0;i<5;i++ )
13 {
14 std::cout << i<<" number: " << numbers[i] << std::endl;}
15 }
Massiv sifatida aniqlangan parametr birinchi elementga ko'rsatgich
sifatida aniq ko'rib chiqilganligi sababli, biz massiv uzunligini to'g'ri
ololmaymiz, masalan, quyidagicha:
Listing 11.6.
#include <iostream>
1
void print(int *);
2
int main()
3
{
4
int nums[] = {1, 2, 3, 4, 5};
5
print(nums);
6
return 0;
7
}
8
9
void print(int *numbers)
10
{
11
std::cout << "First number: " << *numbers <<
12
std::endl;
13
}

Massivning oxirini to'g'ri aniqlash, massiv elementlarini saralash


uchun massivning tugashini bildiradigan maxsus markerdan
foydalanish kerak. Buning uchun turli xil yondashuvlardan foydalanish
mumkin.
Birinchi yondashuv massiv elementlaridan biri uning tugashini
bildirishi kerak. Masalan, belgilar qatori "\0" nol belgisi bilan
tugaydigan belgilar majmuasini ifodalashi mumkin.

145
Nazorat savollari va topshiriqlar:
1. C++ da havolalar qanday hosil qilinadi?
2. C++ da havolalar qanday ishlatish mumkin?
3. C++ da havola va ko‘rsatkich orasidagi farq nimadan iborat?
4. Ko‘rsatkich va havolalar yana qayerda uchratish mumkin?
5. Berilgan x va y o‘zgaruvchilardagi qiymatlarning kichigini x ga
kattasini y ga yozadigan Minmax(x,y) protsedurasi tasvirlansin(x,y
haqiqiy parametrli bir vaqtning o‘zida kiruvchi va chiquvchi). Bu
protsedura 4 marta chaqirilib, berilgan a b c d sonlarining eng kattasi va
eng kichigi aniqlansin.
4319 91
6. MonthDays(m,y) funksiyasidan foydalanib berilgan, to‘g‘ri
(d,m,y) kun, oy, yil formatdagi sanadan oldingi kun sanasini
hisoblovchi PrevDate(d,m,y) prosedurasi tasvirlansin. Prosedurani
qo‘llab berilgan 3 ta sanadan oldingi sanalar topilsin.
1 3 2004 29 2 2004
1 1 2007 31 12 2006
1 9 2008 31 8 2008

146
12-MAVZU. REKURSIV VA QAYTA YUKLANUVCHI
FUNKSIYALAR
 O'rnatilgan inline funksiyalari
 Rekursiya
 Rekursiv funksiyalar
Dasturchiga beminnat xizmat ko'rsatadigan maxsus mavzular
qatoriga kiritilgan inline funksiyalari va funksiyalarning rekursiyasi
kiradi. Rekursiyaga kelsak, dasturchilarning ushbu ajoyib ixtirosi bilan
boshqa yo'llar bilan hal qilinmaydigan ba`zi muammolarni hal qilishga
imkon beradi.
INLINE FUNKSIYALARI
Odatda, funksiyani o‘zlashtirishda kompilyator funksiya
operatorlarini saqlash uchun xotirada faqat bitta katakcha blokini
saqlaydi. Funksiya chaqirilgandan so'ng, dasturni boshqarish ushbu
operatorlarga o'tkaziladi va funksiyadan qaytgach, dastur
chaqirilgandan keyingi qatordan dasturning bajarilishi davom etadi.
Agar siz ushbu funksiyani 10 marta chaqirsangiz, unda har safar sizning
dasturingiz bir xil buyruqlar to'plamini ishlab chiqadi. Bu shuni
anglatadiki, funksiyaning 10 emas, balki faqat bitta nusxasi mavjud.
Ammo funksiya operatorlarini o'z ichiga olgan xotira maydoniga
har bir o'tish dasturning bajarilishini sekinlashtiradi. Agar funksiya
hajmi kichik bo'lsa (bitta yoki ikkita satrdan iborat bo'lsa), dasturdan
funksiyaga va orqaga o'tish o'rniga, kompilyatorga funksiya kodini
to'g'ridan-to'g'ri dasturga kiritish buyrug'ini bersangiz, samaradorlikda
ba'zi yutuqlarni olishingiz mumkin. Samaradorlik deganda, odatda
dasturni bajarish tezligi tushuniladi.
Agar funksiya inline kalit so'zi bilan e'lon qilingan bo'lsa,
kompilyator kompyuter xotirasida funksiyani yaratmaydi, balki uning
satrlarini to'g'ridan-to'g'ri dastur kodiga ko'chiradi.
Inline funksiyadan foydalanish Listing 12.1 da ko'rsatilgan.
Listing 12.1. Inline funksiyalaridan foydalanish
1 #include <iostream>
2 using namespace std;
3 inline int Double(int);
4 int main()
5 int target;
6 cout << "Enter a number to work with:
7 cin >> target;
8 cout << " n";
9 target = Double(target);

147
10 cout << "Target: " << target << endl;
11 target = Double(target);
12 cout << "Target: " << target << endl;
13 target = Double(target);
14 cout << "Target: " << target << endl;
15 return 0;
16 }
17 int Double(int target)
18 {
19 return 2•target;
20 }
Natija:
Enter a number to work with: 20
Target: 40
Target: 80
Target: 160
Tahlil:
3-qatorda int tipidagi parametrni qabul qiladigan va int tipidagi
qiymatni qaytaradigan o'rnini bosuvchi double () funksiyasi e'lon
qilinadi. Ushbu e'lon boshqa har qanday prototipga o'xshaydi, faqat
qaytish tipidan oldin inline kalit so'zi mavjud.
Ushbu prototipni kompilyatsiya qilish natijasi dasturdagi satrlarni
almashtirishga teng:
target = 2 * target;
double()funksiyasini chaqirish:
target = Double(target);
ESLATMA: Inline kalit so'zi kompilyator uchun funksiya kodini
chaqiruv joyidagi dasturga nusxalash uchun xizmat qiladi.
Funksiya o'zini o'zi chaqirishi to'g'ridan-to'g'ri yoki bilvosita
bo‘lishi mumkin. Bu jarayonga deb ataladi. Agar funksiya
o'zini o'zi chaqirsa deb ataladi. Agar funksiya boshqa
funksiyani chaqirsa, u holda birinchisini keltirib chiqaradigan bo'lsa,
unda bu holda sodir bo'ladi.
Ba'zi muammolar rekursiya yordamida osongina hal qilinadi.
Shunday qilib, rekursiya ma'lumotlar bo'yicha ma'lum bir funksiya
bajarilgan va keyin olingan natijalar bo'yicha xuddi shu funksiya
bajarilgan hollarda foydalidir.
Rekursiyaning ikkala turi (to'g'ridan-to'g'ri va bilvosita) ikkita
rolda paydo bo'ladi: ba'zilari oxir-oqibat tugaydi va qaytib keladi,
boshqalari esa hech qachon tugamaydi va ish vaqti xatosini keltirib
chiqaradi.

148
Shuni ta'kidlash kerakki, funksiya o'zini o'zi chaqirganda, ushbu
funksiyaning yangi nusxasi bajariladi. Bunday holda, ikkinchi xil
rekursiyada lokal o'zgaruvchilar birinchisidagi lokal o'zgaruvchilardan
mustaqil bo'lib, bir-biriga bevosita ta'sir o'tkaza olmaydi, hech
bo'lmaganda main() funksiyasidagi lokal o'zgaruvchilar har qanday
boshqa funksiyadagi lokal o'zgaruvchilarga ta'sir qilishi mumkin.
Misolni ko'rsatish uchun rekursiya yordamida muammoni hal
qilish, Fibonachchi seriyasini ko'rib chiqing:
1, 1, 2, 3,5, 8, 13, 21, 34…
Qatorning har bir soni undan oldingi ikkita sonning yig'indisidir.
Masalan, Fibonachchi seriyasining 12-sonini aniqlash kerak bo‘lsin.
Ushbu muammoni hal qilishning bir usuli bu qatorni tahlil
qilishdir. Birinchi ikkita son 1 ga teng. Har bir keyingi son oldingi
ikkitasining yig'indisiga teng. Shunday qilib, o'n yettinchi son o'n
oltinchi va o'n beshinchi son yig'indisiga teng. Umumiy holda, n - son
(n-2)-chi va (n-1)-chi yig'indisiga teng, agar n>2 bo'lsa.
Rekursiv funksiyalar uchun rekursiyani tugatish shartini
o‘zlashtirish kerak. Dasturda rekursiyani to'xtatishga majbur qiladigan
shart bo‘lishi kerak yoki u hech qachon tugamaydi. Fibonachchi
qatorida to'xtash sharti n < 3 ifodasidir.
Bu quyidagi algoritmdan foydalanadi:
1. Biz foydalanuvchiga Fibonachchi qatoridagi qaysi atamani
hisoblash kerakligini ko'rsatishni taklif qilamiz.
2. Biz fib () funksiyasini chaqiramiz, argument sifatida
foydalanuvchi tomonidan belgilangan Fibonachchi qatoridagi sonlarni
uzatamiz.
3. fib () funksiyasida argument tahlili (n) amalga oshiriladi. Agar n
< 3 bo'lsa, funksiya 1 qiymatini qaytaradi; aks holda fib () funksiyasi n-
2 qiymatini argument sifatida o'tkazib, o'zini o'zi chaqiradi (rekursiv),
n-1 qiymatini argument sifatida uzatadi va keyin yig'indini qaytaradi.
Agar siz fib (1) funksiyasini chaqirsangiz, u 1 ni qaytaradi. Agar
siz fib (2) funksiyasini chaqirsangiz, u ham 1 ni qaytaradi. Agar siz fib
(3) funksiyasini chaqirsangiz, u fib (2) va fib (1) funksiyalari tomonidan
qaytarilgan qiymatlar yig'indisini qaytaradi. fib (2) funksiyasini
chaqirish 1 qiymatini va fib (1) funksiyasini chaqirish 1 qiymatini
qaytarganligi sababli, fib (3) funksiyasi 2 qiymatini qaytaradi.
Agar siz fib (4) funksiyasini chaqirsangiz, u fib (3) va fib (2)
funksiyalari tomonidan qaytarilgan qiymatlar yig'indisini qaytaradi. Biz
149
allaqachon fib (3) funksiyasi 2 qiymatini qaytarishini va fib (2)
funksiyasi 1 qiymatini qaytarishini aniqladik, shuning uchun fib (4)
funksiyasi bu sonlarni qo‘shadi va Fibonachchi qatorining to'rtinchi
elementi 3 qiymatini qaytaradi.
Keling, keyingi qadamni ko‘ramiz. Agar siz fib(5) funksiyasini
chaqirsangiz, u fib (4) va fib (3) funksiyalari tomonidan qaytarilgan
qiymatlar yig'indisini qaytaradi. fib(4) funksiyasi 3 qiymatini va fib (3)
funksiyasi 2 qiymatini qaytaradi, shuning uchun yig`indi 5 soniga teng
bo'ladi.
Ushbu usul bu muammoni hal qilishning eng samarali usuli emas.
Masalan, fib(20) funksiyasini chaqirganda, fib() funksiyasi 13529
marta chaqiriladi. Agar siz Fibonachchi qatorining ko'p elementlarini
chaqirsangiz, sizda yetarli xotira bo'lmasligi mumkin. Har bir fib()
funksiyasi chaqirilganda, ma'lum bir xotira maydoni saqlanadi.
Funksiyadan qaytgach, xotira bo'shatiladi. Ammo rekursiv murojaatlar
bilan xotiraning barcha yangi sohalari zaxiralanadi va ushbu yondashuv
bilan tizim xotirasi juda tez tugashi mumkin. fib() funksiyasini amalga
oshirish Listing 12.2 da ko'rsatilgan.
Listing 12.2 da keltirilgan dasturni ishga tushirganda, Fibonachchi
qatorining kichik elementlarini (15 dan kam) o'rnating. Ushbu dastur
rekursiyadan foydalanganligi sababli katta xotira ishlatishi mumkin.
Listing 12.2. Fibonachchi sonini topish
1 #include <iostream>
2 using namespace std;
3 int fib (int n);
4 int main()
5{
6 int n, answer;
7 cout << "Enter number to find: "; cin >> n;
8 cout << "\n\n";
9 answer = fib(n);
10 cout << answer << " is the " << n << "Fibonacci number\n";
11 return 0;
12 }
13 int fib (int n)
14 {
15 cout << "Processing fib(" << n << ")… ";
16 if (n < 3 )
17 {
18 cout << "Return 1!\n";
19 return (1);
20 }
21 else

150
22 {
23 cout << "Call fib(" << n-2 << ") and fib(" << n-1 <<
24 ").\n";
25 return( fib(n-2) + fib(n-1));
26 }
}

Natija:
Enter number to find: 6
Processing fib(6)… Call fib(4) and fib(5).
Processing fib(4)… Call fib(2) and fib(3).
Processing fib(2)… Return 1!
Processing fib(3)… Call fib(1) and fib(2).
Processing fib(1)… Return 1!
Processing fib(2)… Return 1!
Processing fib(5)… Call fib(3) and fib(4).
Processing fib(3)… Call fib(1) and fib(2).
Processing fib(1)… Return 1!
Processing fib(2)… Return 1!
Processing fib(4)… Call fib(2) and fib(3).
Processing fib(2)… Return 1!
Processing fib(3)… Call fib(1) and fib(2).
Processing fib(1)… Return 1!
Processing fib(2)… Return 1!
8 is the 6th Fibonacci number
Tahlil:
ESLATMA: Ba'zi kompilyatorlar cout obyekti bilan ifodalardagi
operatorlardan foydalanishda qiyinchiliklarga duch kelishadi. Agar siz
23-qatorda ogohlantirish olsangiz, 23-qator uchun ayirish amalini qavs
ichiga yozing:
cout << "Call fib(" << (n-2) << ") and fib(" << n-1 << ").\n";

7-qatorda dastur kerakli qator elementining sonini kiritishni taklif


qiladi va uni n o'zgaruvchiga o‘zlashtiradi, keyin fib() funksiyasi n
argumenti bilan chaqiriladi. Dasturning bajarilishi fib() funksiyasiga
o'tadi, bu yerda 15-qatorda ushbu argument ekranda ko'rsatiladi.
16-qatorda argument 3 sonidan kichik emasligi tekshiriladi va agar
shunday bo'lsa, fib() funksiyasi 1 qiymatini qaytaradi. Aks holda, n-2
va n-1 argumentlari bilan fib() funksiyasini chaqirganda qaytarilgan
qiymatlar yig'indisi olinadi. Shunday qilib, ushbu dastur fib()
funksiyasining takrorlashi sifatida ifodalanishi mumkin. Qiymatlarni
darhol qaytaradigan yagona murojaatlar fib (1) va fib(2) funksiyalariga
murojaat qilishdir.

151
Ushbu misolda n o'zgaruvchisi 6 qiymatiga teng, shuning uchun fib
(6) funksiyasi main () funksiyasidan chaqiriladi. Dasturning bajarilishi
fib() funksiyasining tanasiga o'tadi va 16-qatorda uzatilgan
argumentning qiymati 3 soni bilan taqqoslanadi. 6 soni 3 sonidan katta
bo'lgani uchun, fib(6) funksiyasi fib(4) va fib(5) funksiyalari tomonidan
qaytarilgan qiymatlar yig'indisini qaytaradi:
return( fib(n-2) + fib(n-1));

Bu shuni anglatadiki, fib(4) va fib(5) funksiyalariga kirish amalga


oshiriladi (chunki n o'zgaruvchisi 6 soniga teng, fib(n-2)=fib(4), fib(n
- 1) esa fib(5) ga teng). Shundan so'ng, hozirda dastur boshqaruvi
berilgan fib(6) funksiyasi murojaatlar qanday qaytarilishini kutadi.
Qiymatlarning qaytishini kutgandan so'ng, bu funksiya ushbu ikki
qiymatning yig'indisi natijasini qaytaradi.

12.1-rasm
fib(5) funksiyasi chaqirilganda, 3 sonidan kichik bo'lmagan
argument o'tkazilganligi sababli, fib() funksiyasi yana chaqiriladi, bu
safar 4 va 3 argumentlar bilan chaqiriladi. fib (4) funksiyasi o'z
navbatida fib(3) va fib(2) funksiyalarini chaqiradi.
Listing 12.2 da keltirilgan dasturning natijalari va oraliq
bosqichlari ekranda ko'rsatiladi. Avval 1, keyin 2, 3 sonlarini kiritib,
ushbu dasturni kompilyatsiya qiling va bajaring va ko'rsatilgan
ma'lumotlarni diqqat bilan kuzatib, 6 sonigacha yetib boring. fib()
funksiyasining har bir rekursiv chaqiruvida n o'zgaruvchining qiymati
o‘zgarib boradi. C++ dasturlashda rekursiya tez-tez uchratish mumkin,

152
lekin ba'zi hollarda u kuchli vositadir. Shuni ta`kidlash kerakki,
rekursiya dasturlashning eng qiyin mavzularidan biridir.

Nazorat savollari va topshiriqlar:


1. Rekursiv funksiya nima?
2. Rekursiv funksiyaning afzalliklarini sanab bering.
3. Rekursiya qaysi hollarda kerak bo‘ladi deb o‘ylaysiz?
4. Nima afzal deb o‘ylaysiz, rekursiyami yoki takrorlashmi?
5. Sonning faktorialini va n gacha bo‘lgan sonlarning yig`indisini
rekursiya orqali toping.

153
13-MAVZU. C++ DA FAYL TUSHUNCHASI. FAYLDAN
O’QISH VA YOZISH FUNKSIYALARI. FAYLLAR USTIDA
AMALLAR.
 Fayl yaratish
 Faylga yozish va fayldan o’qish
 Get va getline funksiyalari

Agar dasturda juda ko'p kod mavjud bo'lsa, unda kodning alohida
qismlarini alohida fayllarga yozish yanada maqbul bo'ladi. Masalan,
ba'zi funksiyalar bitta dastur kodi faylida, boshqa funksiyalar boshqa
faylda saqlanishi mumkin.
Masalan, quyidagi kodga ega bo'lgan faktorial cpp faylini
aniqlaymiz.
Bu faktorialni hisoblash funksiyasi. Boshqa faktorial funksiyani
e`lon qilishni o'z ichiga olgan faktorial faylini qo'shamiz.
factorial.cpp:
1 int factorial(int);
2 int factorial(int n)
3{
4 if (n > 1)
5 return n * factorial(n - 1);
6 return 1;
7}
sum.cpp:
1 int sum(int a)
2{
3 if(a>0)
4 return (1+a)*a/2.0-a;
5 return 0;
6}
Listing 13.1.
1 #include "iostream"
2 #include "factorial.cpp"
3 #include "sum.cpp"
4 int main()
5{
6 int result = factorial(7);
7 std::cout << "result = " << result <<
8 std::endl;
9 std::cout<<sum(6);
10 return 0;
11 }

154
Asosiy funksiya sonning faktorialini hisoblash uchun faktorial
funksiyasini chaqiradi. Ammo boshqa faylda aniqlangan funksiyadan
foydalanish uchun siz uning e`lonini qo'shishingiz kerak.
Funksiya e`loni to'g'ridan-to'g'ri dasturning asosiy fayliga qo'shildi.
Ammo, agar funksiyalar alohida fayllarda aniqlangan bo'lsa, unda
funksiya e`lonini maxsus sarlavha fayllariga joylashtirish va keyin
ushbu fayllarni ulash maqbuldir.
Faktorial faylini cpp. fayliga ulash mumkin. Ammo funksiyani
o'zgartirganda, uning e`lonini o'zgartirish kerak bo‘lishi mumkin. Agar
faktorial funksiyasi bir nechta fayllarda ishlatilsa, unda ushbu
fayllarning har birida siz uning e`lonini o'zgartirishingiz kerak bo'ladi.
Bunday holda, funksiya e`lonini bitta faylda o'zgartirish kifoya -
faktorial.cpp.
Ko'pgina kompyuter dasturlari fayllar bilan ishlaydi va shuning
uchun fayllarni yaratish, o'chirish, yozish, o'qish, ochish kerak bo'ladi.
Fayl nima? -ma'lum bir diskda saqlanishi mumkin bo'lgan
baytlarning nomlangan to'plami. Shuningdek, fayl .txt kabi o'ziga xos,
noyob nomga ega bo'lgan ba'zi baytlar ketma-ketligini anglatishi aniq.
Xuddi shu katalogda bir xil nomdagi fayllar bo‘lishi mumkin emas.
Fayl nomi nafaqat uning nomini, balki kengaytmani ham anglatadi,
masalan: fayl.txt va fayl.dat - turli xil fayllar, garchi ular bir xil
nomlarga ega bo'lsa ham. To'liq fayl nomi esa fayl nomi ko'rsatilgan
fayl katalogiga to'liq manzil, masalan: D:\docs\file.txt. Ushbu asosiy
tushunchalarni tushunish juda muhim, aks holda fayllar bilan ishlash
qiyin bo'ladi.
Fayllar bilan ishlash uchun siz <fstream> sarlavha faylini
ulashingiz kerak. bu fayllarni o'qish va yozish uchun asosiy turlarni
belgilaydi.
Xususan, bu:
 ifstream: fayldan o'qish uchun
 ofstream: faylga yozish uchun
 fstream: yozish va o'qishni birlashtiradi.
Faylga kirish / chiqish konsolga kirish/chiqishga o'xshaydi, yagona
farq shundaki, kirish/chiqish ekranda emas, balki faylda amalga
oshiriladi. Agar standart qurilmalarga kirish/chiqish cin va cout
obyektlari yordamida amalga oshirilsa, u holda fayl kirish/chiqishni

155
tashkil qilish uchun cin va cout operatorlariga o'xshash ishlatilishi
mumkin bo'lgan maxsus obyektlarni yaratish kifoya.
Masalan, siz matnli fayl yaratishingiz va unga C++ da fayllar bilan
ishlash uchun dastur kodlarini yozishingiz kerak. Buning uchun siz
quyidagi amallarni bajarishingiz kerak:
 ofstream sinf obyektini yarating;
 sinf obyektini yozish amalga oshiriladigan fayl bilan
bog'lang;
 faylga satr yozing;
 faylni yoping.
Nima uchun ifstream sinfini emas, balki ofstream sinf obyektini
yaratish kerak? Chunki siz faylga yozishingiz kerak va agar siz fayldan
ma'lumotlarni o‘qishingiz kerak bo'lsa, unda ifstream sinfining obyekti
yaratiladi.
ofstream /*obyekt nomi*/;
Keling, obyektni – fout deb ataymiz.
ofstream fout;
Faylga yozishni amalga oshirish uchun obyekt kerak.
fout.open("cppstudio.txt"); // obyektni faylga ulash
Nuqta amali orqali biz open () sinf funksiyasiga kiramiz, uning
qavslarida fayl nomini ko'rsatamiz. Belgilangan fayl dastur bilan joriy
katalogda yaratiladi. Agar ushbu nomdagi fayl mavjud bo'lsa, unda
mavjud fayl yangisi bilan almashtiriladi. Shunday qilib, faylga satrni
yozish qoladi. Bu shunday amalga oshiriladi:
fout << "C++ da fayl bilan ishlash"; // faylga satr yozish
fout obyekti bilan birgalikda oqimga o'tkazish amalidan
foydalanib, C++ da fayllar bilan ishlash satri faylga yoziladi. Fayl
tarkibini o'zgartirishning hojati yo'qligi sababli, uni yopish kerak.
fout.close(); // faylni yopish
1 va 2-bosqichlarni birlashtirish mumkin, ya'ni bitta satrda obyekt
yaratish va uni fayl bilan bog'lash mumkin. Bu quyidagicha amalga
oshiriladi:
ofstream fout("cppstudio.txt");
Biz barcha kodni birlashtiramiz va quyidagi dasturni olamiz.
Listing 13.2.
1 #include <fstream>
2 using namespace std;
3

156
4 int main(int argc, char* argv[])
5{
6 ofstream fout("cppstudio.txt");
7 fout << "C++ da fayl bilan ishlash";
8 fout.close();
9 return 0;
10 }

Dasturning to'g'ri ishlashini tekshirish qoladi va buning uchun


“cppstudio.txt” faylini oching va uning tarkibiga qarang. Faylni o'qish
uchun siz faylga yozish bilan bir xil amallarni bajarishingiz kerak
bo'ladi:
 ifstream sinf obyektini yarating va uni matnli fayl bilan bog'lang;
 faylni o'qing;
 faylni yoping.
Listing 13.3.
1 #include <fstream>
2 #include <iostream>
3 using namespace std;
4
5 int main(int argc, char* argv[])
6{
7 char buff[50];
8 ifstream fin("cppstudio.txt"); // faylni oqish uchun ochish
9
10 fin >> buff; // fayldagi 1-so‘zni o‘qish
11 cout << buff << endl; // sozni chop etish
12
13 fin.getline(buff, 50); // fayldagi satrlarni oqish
14 fin.close(); // faylni yopish
15 cout << buff << endl; // qatorni chop etish
16 return 0;
17 }
Dastur fayldan o'qishning ikkita usulini ko'rsatadi, birinchisi-
oqimga o'tkazish amalidan foydalanish, ikkinchisi-getline ()
funksiyasidan foydalanish. Birinchi holda, faqat birinchi so'z o'qiladi,
ikkinchi holatda esa 50 belgidan iborat satr o'qiladi. Ammo faylda 50
dan kam belgi bo‘lganligi sababli, belgilar oxirigacha o'qiladi.

13.1-rasm. Dasturning natijasi

157
Dastur to'g'ri ishladi, lekin har doim ham shunday bo'lmaydi, hatto
kod to‘g`ri yozilgan bo'lsa ham.
Shunday qilib, C++ da barcha kodlar juda aniq bo‘lishi uchun
butun qiymatlarni qaytaradigan — is_open () funksiyasi taqdim etiladi:
1 — agar fayl muvaffaqiyatli ochilgan bo'lsa, 0 — agar fayl ochilmagan
bo'lsa. Agar fayl ochilmasa, tegishli xabar ko'rsatiladi.
Listing 13.4.

1 #include <fstream>
2 #include <iostream>
3 using namespace std;
4
5 int main(int argc, char* argv[])
6{
7 char buff[50]; // satrni saqlash uchun massiv
8 ifstream fin("cppstudio.doc"); // fayl nomi notogri
9
10 if (!fin.is_open())
11 cout << "Faylni ochib bo‘lmaydi!\n";
12 else
13 {
14 fin >> buff; // fayldan 1-so'zni oqib olish
15 cout << buff << endl; // shu so'zni chop etish
16
17 fin.getline(buff, 50); // fayldan satrni o'qib olish
18 fin.close(); // faylni yopish
19 cout << buff << endl; // satrni chop etish
20 }
21 return 0;
22 }

13.2-rasm
13.2-rasmdan ko'rinib turibdiki, dastur faylni ochib bo‘lmasligi
haqida xabar berdi. Shuning uchun, agar dastur fayllar bilan ishlayotgan
bo'lsa, fayl mavjudligiga amin bo'lsangiz ham is_open () funksiyadan
foydalanish tavsiya etiladi.
Fayllarni ochish rejimlari fayllardan foydalanish xususiyatini
belgilaydi. ios_base sinfida rejimni o'rnatish uchun fayllarni ochish
rejimini belgilaydigan o‘zgarmaslar mavjud (13.1-jadvalga qarang).

158
Rejim Izoh
ios_base::in Faylni o‘qish uchun ochish
ios_base::out Faylni yozish uchun ochish
ios_base::ate Faylni ochishda ko‘rsatkichni fayl oxiriga
o‘tkazish
ios_base::app Fayl oxiriga yozish uchun faylni ochish
ios_base::trunc Fayl ma`lumotlarini o‘chirish (agar u mavjud
bo‘lsa)
ios_base::binary Faylni ikkilik rejimda ochish
13.1-jadval
Fayllarni ochish rejimlari to'g'ridan-to'g'ri obyekt yaratilganda yoki
open () funksiyasi chaqirilganda o'rnatilishi mumkin.
ofstream fout("cppstudio.txt", ios_base::app);
fout.open("cppstudio.txt", ios_base::app);
Fayllarni ochish rejimlari mantiqiy operatorlar yoki | yordamida
birlashtirilishi mumkin, masalan: ios_base:: out | ios_base:: trunc —
faylni avval tozalash orqali yozib olish uchun ochish.
Ofstream sinfidagi obyektlar sukut bo'yicha fayllar bilan
bog'langanda ios_base::out | ios_base::trunc fayllarini ochish
rejimlarini o'z ichiga oladi. Ya'ni, agar mavjud bo'lmasa, fayl yaratiladi.
Agar fayl mavjud bo'lsa, unda uning tarkibi o'chiriladi va faylning o'zi
yozishga tayyor bo'ladi.
Ifstream sinfidagi obyektlar fayl bilan bog'lanib, sukut bo'yicha
ios_base::in faylini ochish rejimiga ega. Shuni esda tutingki, ate va app
rejimlari tavsifga ko'ra juda o'xshash, ikkalasi ham ko'rsatgichni
faylning oxiriga ko'chiradi, lekin app rejimi faqat faylning oxiriga
yozishga imkon beradi va ate rejimi shunchaki bayroqni faylning
oxiriga o'zgartiradi va yozish joylarini cheklamaydi. Biz sizeof ()
amalidan foydalanib, C++ da asosiy ma'lumotlar tiplarining
xususiyatlarini hisoblaydigan va ularni faylga yozadigan dasturni ishlab
chiqamiz.
Faylga yozish ushbu formatda amalga oshirilishi kerak:

159
/* data type byte max value
bool = 1 255.00
char = 1 255.00
short int = 2 32767.00
unsigned short int = 2 65535.00
int = 4 2147483647.00
unsigned int = 4 4294967295.00
long int = 4 2147483647.00
unsigned long int = 4 4294967295.00
float = 4 2147483647.00
long float = 8 9223372036854775800.00
double = 8 9223372036854775800.00 */
Listing 13.5.
#include <iostream>
#include <fstream> // fayllar bilan ishlash
#include <iomanip> // kiritish/chiqarish manipulyatori
#include <math.h>
using namespace std;
int main(int argc, char* argv[])
{
ofstream fout("data_types.txt", ios_base::out |
ios_base::trunc);

if (!fout.is_open()) // agar fayl ochilmagan bolsa


{
cout << "Faylni ochib bo‘lmaydi yoki yaratilmagan\n";
return 1; // dasturdan chiqish
}

fout << " data type " << "byte"


<< " " << " max value " << endl
<< "bool = " << sizeof(bool)
<< " " << fixed << setprecision(2)
/*bool*/ << (pow(2,sizeof(bool) *
8.0) - 1) << endl
<< "char = " << sizeof(char)
<< " " << fixed << setprecision(2)
/*char*/ << (pow(2,sizeof(char) *
8.0) - 1) << endl
<< "short int = " << sizeof(short int)
<< " " << fixed << setprecision(2)
/*short int*/ << (pow(2,sizeof(short int)
* 8.0 - 1) - 1) << endl
<< "unsigned short int = " << sizeof(unsigned
short int) << " " << fixed << setprecision(2)

160
/*unsigned short int*/ << (pow(2,sizeof(unsigned
short int) * 8.0) - 1) << endl
<< "int = " << sizeof(int)
<< " " << fixed << setprecision(2)
/*int*/ << (pow(2,sizeof(int) * 8.0
- 1) - 1) << endl
<< "unsigned int = " << sizeof(unsigned
int) << " " << fixed << setprecision(2)
/*int*/ << (pow(2,sizeof(unsigned int) *
8.0) - 1) << endl
<< "long int = " << sizeof(long int)
<< " " << fixed << setprecision(2)
/*long int*/ << (pow(2,sizeof(long int)
* 8.0 - 1) - 1) << endl
<< "unsigned long int = " << sizeof(unsigned
long int) << " " << fixed << setprecision(2)
/*long int*/ << (pow(2,sizeof(unsigned long int)
* 8.0) - 1) << endl
<< "float = " << sizeof(float)
<< " " << fixed << setprecision(2)
/*float*/ << (pow(2,sizeof(float) *
8.0 - 1) - 1) << endl
<< "long float = " << sizeof(long)
<< " " << fixed << setprecision(2)
/*float*/ << (pow(2,sizeof(long) * 8.0 -
1) - 1) << endl
<< "double = " << sizeof(double)
<< " " << fixed << setprecision(2)
/*double*/ << (pow(2,sizeof(double) *
8.0 - 1) - 1) << endl;
fout.close(); // faylni yopish
cout << "Berilganlar data_types.txt ga muvaffaqiyatli
joylashtirildi\n";
return 0;
}

Nazorat savollari va topshiriqlar:


1.Fayl nima?
2.Fayl yaratish sintaksisi qanday?
3.Fayl yaratishda qaysi kutubxonadan foydalanish kerak?
4.Faylga yozish uchun qaysi funksiyadan foydalaniladi?
5.Fayldan o'qish uchun qaysi funksiyadan foydalaniladi?
6. get funksiyasi nima?
7. getline funksiyasi nima?
8. get va getline funksiyalarining bir-biridan farqi nimada?
9.Yuqorida berilgan dastur kodlaridan foydalanib "text.txt" faylini
yarating.
161
14-MAVZU. STANDART KUTUBXONA
FUNKSIYALARI.
 Qaysi funksiyalar sinflar nomi bilan chaqiriladi
 Ism maydonlari yaratilishi
 Ism maydonlari ishlatilishi
 Standart std nom maydoni ishlatilishi
Biz yangi standart kutubxonalarning sarlavhalaridan
foydalanamiz:
#include <iostream>
Eski kutubxonalar va yangi standartlar o'rtasidagi asosiy farq
iostream kutubxonasidan foydalanishdir. Ammo bu o'zgarishlar ham
ahamiyatsizligi sababli ushbu kitobdagi dasturlarga ta'sir qilmasligi
kerak. Bundan tashqari, ular yangi boshlanuvchilar uchun taqdim
etilgan mavzular doirasini muhokama qilishdan tashqariga chiqadilar.
NOMLAR MAYDONI
ANSI C++ standartiga qo'shimchalardan biri bu dasturchilar
tomonidan ko'plab kutubxonalar bilan ishlashda nomlarning
to'qnashuvidan qochish uchun nom bo‘sh joylaridan foydalanish
qobiliyatidir.
ANSI standartlari ushbu muammoni nomlar maydoni
(namespaces) yordamida hal qilish usulini taklif qiladi. Biroq, ehtiyot
bo‘lish kerak, chunki barcha kompilyatorlar ushbu vositani qo'llab-
quvvatlamaydi.
Nomlar maydoni global nom bo‘sh joylarini ajratish uchun
ishlatiladi, bu nom to'qnashuvlarini yo'q qilish yoki hech bo'lmaganda
kamaytirish uchun ishlatiladi.
Shunga ko'ra, funksiyalar nomlar ichida ham, tashqarisida ham
e'lon qilinishi mumkin. Ikkinchi holda, bunday funksiyani chaqirganda,
tegishli nom maydoni aniq ko'rsatilishi kerak.
FUNKSIYALAR VA SINFLAR NOMI BO'YICHA
CHAQIRISH
Dastur kodini tahlil qilish va funksiyalar va o'zgaruvchilar nomlari
Listingini yaratish jarayonida kompilyator dasturni nom ziddiyatlari
uchun tekshiradi. Kompilyatorning o'zi hal qila olmaydigan
ziddiyatlarni bog'lovchi hal qilishi mumkin.
Agar siz bir xil nomdagi va bir-biriga o'xshash ko'rinadigan
identifikatorlarni tasvirlashga harakat qilsangiz, xato xabar paydo

162
bo'ladi. Xato xabarni quyidagi dastur kodini kompilyatsiya qilish va
ulashga urinayotganda bog'lovchidan kelib chiqadi:
Listing 14.1
// birinchi fayl.cpp
int integerValue = 0 ;
int main( ) {
int integerValue = 0
//….
return 0 ;}
// ikkinchi fayl.cpp
int integerValue = 0 ;
// ikkinchi oxiri.cpp
Kompilyatordan bunday eslatma ham bo‘lishi mumkin: identifier
hiding (ID yashiringan). Uning mohiyati birinchi faylda.cpp
integerValue o'zgaruvchisini main () funksiyasida e'lon qilish xuddi shu
nomdagi global o'zgaruvchini yashiradi.
Main () funksiyasida main () dan tashqarida e'lon qilingan
integervaalue global o'zgaruvchisidan foydalanish uchun ko'rish
operatori (::) yordamida ushbu o'zgaruvchining globalligini aniq
ko'rsatish kerak. Shunday qilib, quyidagi misolda 10 qiymati
main()ichida e'lon qilingan bir xil nomdagi o'zgaruvchiga emas, balki
integervalue global o'zgaruvchisiga beriladi:
Listing 14.2
// birinchi fayl.cpp
int integerValue = 0 ;
int main( ){
int integerValue = 0 ;
:: integerValue=10; // global o'zgaruvchisini o‘zlashtirish
return 0 ;}
// ikkinchi fayl.cpp
int integerValue = 0 ;
// ikkinchi oxiri.cpp
O'zgaruvchi, sinf yoki funksiya bo‘lishi mumkin bo'lgan
obyektning ko'rinishi ostida ushbu obyekt ishlatilishi mumkin bo'lgan
dasturning qismi tushuniladi. Masalan, har qanday funksiyadan
tashqarida e'lon qilingan va aniqlangan o'zgaruvchi fayl yoki global
miqyosga ega. Uning ko'rinishi e`lon nuqtasidan faylning oxirigacha
tarqaladi. Modulli yoki lokal ko'lamga ega bo'lgan o'zgaruvchi dasturiy
modul ichida e'lon qilinadi. Ko'pincha lokal o'zgaruvchilar funksiya
tanasida e'lon qilinadi. Quyida turli xil ko'rish sohalariga ega bo'lgan
obyektlarning namunalari keltirilgan:

163
Listing 14.3
int globalScopeInt = 5 ;
void f( )
{ int localScopeInt = 10 ; }
int main( )
{ int localScopeInt = 15 ;
{ int anotherLocal = 20 ;
int localScopeInt = 30 ;}
return 0 ;}

globalScopeInt global o'zgaruvchisi f () va main () funksiyalarida


ko'rinadi. f () funksiyasining tanasida localScopeInt o'zgaruvchisi
prototipi mavjud. U esa lokal, ya'ni funksiya prototipini o'z ichiga olgan
modul chegaralari bilan cheklangan. Main() funksiyasi f ()
funksiyasining localScopeInt o'zgaruvchisiga kira olmaydi.
F() funksiyasini bajarish tugagandan so'ng, localScopeInt
o'zgaruvchisi kompyuter xotirasidan o'chiriladi, localScopeInt deb
nomlangan uchinchi o'zgaruvchining prototipi main () funksiyasining
tanasida joylashgan. U ham lokal o‘zgaruvchidir.
E'tibor bering: main() funksiyasining localScopeInt o'zgaruvchisi
f() funksiyasining bir xil o'zgaruvchisiga zid kelmaydi. Quyidagi ikkita
o'zgaruvchining ko'rinishi-anotherLocal va localScopeInt - modul
maydoni bilan ham cheklangan. Boshqacha qilib aytganda, ushbu
o'zgaruvchilar e'lon qilingan joydan ushbu funksiya e'lon qilingan
modul tanasini cheklaydigan yopiq figurali qavsgacha ko'rinadi.
Ismlar ichki yoki tashqi aloqaga ega bo‘lishi mumkin. Ushbu
ikkala atama ham bir nechta yoki bitta dasturiy ta'minot birligida
ismning ishlatilishi yoki mavjudligini anglatadi. Tashqi aloqaga ega
bo'lgan har qanday nomga faqat uni belgilaydigan birlik doirasida
murojaat qilish mumkin.
Masalan, ichki aloqaga ega bo'lgan o'zgaruvchidan faqat ushbu
o'zgaruvchi e'lon qilingan dastur blokidagi funksiyalar foydalanishi
mumkin. Tashqi aloqalarga ega nomlar boshqa bloklardan
xususiyatlarga ega. Ichki va tashqi aloqalarga misollar quyidagi kodni
ko'rsatadi.
Listing 14.4
// fayl: birinchi.cpp
int externalInt = 5 ;
const int j = 10 ;
int main()
return 0 ;

164
// fayl: ikkinchi.cpp
extern int externalInt ;
int anExternalInt = 10 ;
const int j = 10 ;
Birinchi .cpp faylda e'lon qilingan externalInt o'zgaruvchisi tashqi
aloqaga ega. Birinchi faylda e'lon qilinganiga qaramay .cpp ushbu
o'zgaruvchiga i.cpp kkinchi fayldan kirish mumkin. Ikkala faylda ham
sukut bo'yicha ichki aloqalarga ega bo'lgan j konstantalari mavjud.
Standart konstantalarning ichki aloqasini o'zgartirish uchun siz
quyidagi misolda bo'lgani kabi ularning globalligini aniq ko'rsatishingiz
kerak:
Listing 14.5
// fayl: birinchi.cpp
extern const int j = 10 ;
// fayl: ikkinchi.cpp
extern const int j ;
#include <iostream>
int main(){
std::cout << "j = " << j << std::endl ;
return 0;}
Coutdan oldin std nom maydoni belgisidan foydalanishga e'tibor
bering, bu sizga standart ANSI kutubxonasining barcha obyektlariga
murojaat qilish imkonini beradi. Ushbu kod bajarilgandan so'ng
ekranda qator paydo bo'ladi:
j = 10;
Standartlashtirish qo'mitasi quyidagi misolda bo'lgani kabi tashqi
o'zgaruvchining ko'lamini cheklash uchun statikdan foydalanishni
tavsiya etmaydi:
static int staticInt = 10 ;
int main()
{ //…
}
Agar hozirda statikdan bunday foydalanish shunchaki tavsiya
etilmasa, kelajakda bunday ifodani umuman noto'g'ri deb hisoblash
mumkin. Shuning uchun, endi statik o'rniga nomlar maydonidan
foydalanish yaxshiroqdir.
Tavsiya etiladi!
 Nomlar maydonidan foydalaning.

165
NOMLAR MAYDONINI YARATISH
Ism maydonini e'lon qilish sintaksisi tuzilmalar va sinflarni e'lon
qilish sintaksisiga o'xshaydi. Kalit so'zdan keyin pamesras mavjud
bo'lmasligi mumkin bo'lgan nom maydonining nomi, so'ngra
ochiladigan figurali qavs. Ism maydoni ifoda oxirida nuqta-vergulsiz
yopiladigan figurali qavs bilan yakunlanadi. Masalan,:
namespace Window
{
void move( int x, int y) ;}
Window nomi nomlar maydonini aniqlaydi. Bitta fayl ichida yoki
turli xil tarjima birliklarida joylashgan nomlangan nom maydonlarining
ko'plab nusxalarini yaratish mumkin. Bunga C++standart
kutubxonasining std nom maydoni misol bo'la oladi. Uning ishlatilishi
bu holatda standart kutubxona mantiqiy jihatdan yagona funksiyalar
guruhi ekanligi bilan asoslanadi.
Ism maydonlarining asosiy maqsadi dasturning nomlangan
hududida bog'langan elementlarni guruhlashdir. Quyida bir nechta
sarlavha fayllarini birlashtirgan nom maydonining misoli keltirilgan:
Listing 14.6
// header1. h
namespace Window
void move( int x, int y) ;
// header2. h
namespace Window
void resize( int x, int y ) ;
Nomlar maydoni ichida turlari va funksiyalarini e'lon qilish va
aniqlash mumkin. C++da dasturlashning strategik yondashuvlarini
muhokama qilmasdan qilolmaysiz. Dastur tuzilishining to'g'riligi dastur
interfeysi uning protsessual qismidan qanchalik aniq ajratilganligi bilan
belgilanadi. Ushbu prinsipga nafaqat sinflar bilan ishlashda, balki nom
maydonlarini yaratishda ham amal qilish kerak. Quyida yana bir misol
keltirilgan:
Listing 14.7
namespace Window {
// .boshqa prototiplar va o'zgaruvchan ta'riflar.
void move (int x, int y); / / e'lonlar
void resize( int x, int y ) ;
// . . . boshqa prototiplar va o'zgaruvchan ta'riflar.
void move( int x, int y )
if( x < MAX_SCREEN_X && x > 0 )
if( y < MAX_SCREEN_Y && y > 0 )

166
platform.move (x. ) // maxsus dastur
void resize( int x, int y )
if( x < MAX_SIZE_X && x > 0 )
if( y < MAX_SIZE_Y && y > 0 )
platform.resize (x, y ) ; // maxsus dastur
Ismlar maydoni qanchalik tez tartibli va tartibsiz bo‘lishini aniq
ko'rish mumkin! Bundan tashqari, ushbu misolda nomlar maydonini
e'lon qilish atigi 20 satrni tashkil etadi.
Nom maydonining funksiyalari nomlar maydoni tanasidan
tashqarida e'lon qilinishi kerak.
Bu sizga funksiyalar prototipini ularning bajarilishini aniqlashdan
nomlar maydonining tanasini buzmasdan aniq ajratish imkonini beradi.
Bundan tashqari, funksiya prototipini ayirish nom maydonini va uning
joriy qilingan e'lonlarini sarlavha fayliga joylashtirishga imkon beradi
va bajarilish ta'riflarini dasturning bajariladigan fayliga joylashtiradi.
Masalan:
Listing 14.8
// header fayli.h
namespace Window {
void move( int x, int y) ;
// boshqa e'lonlar
// file impl.cpp
void Window::move( int x, int y )
// Oynani ko'chirish kodi
}
YANGI A'ZOLARNI QO'SHISH
Ismlar maydoniga yangi a'zolarni qo'shish faqat nomlar maydoni
tanasida amalga oshiriladi. Kompilyator bunga xato xabari bilan javob
beradi. Bunday xatoning misoli quyida keltirilgan.
Listing 14.9
namespace Window {
// bir qator e'lonlar
// dastur kodi
int Window:: newIntegerInNamespace; / / xato
Oxirgi satr noto'g'ri va kompilyator bu haqida xabar beradi. Xatoni
tuzatish uchun newintegerinnamespace a'zo o'zgaruvchisi prototipini
nomlar maydoni tanasiga o'tkazing.
namespace Window {
private:
void move( int x, int y ) ;
}

167
Bir nom maydoni boshqa nom maydoniga joylashtirilishi mumkin.
Bunday investitsiya bitta nom maydonining bajarilishini aniqlashda
yangi makon prototipi bo‘lishi kerak bo'lgan hollarda qo'llaniladi.
Ichki nomlar maydonining a'zosiga murojaat qilish uchun ikkala
bo‘sh joyning nomlarini aniq ko'rsatish kerak. Shunday qilib, quyidagi
misolda bitta nomlangan bo‘sh joy boshqa nomlangan bo‘sh joy ichida
e'lon qilinadi:
namespace Window{
namespace Pane
void size( int x, int y ) ;
Windows nom maydonidan tashqarida size() funksiyasiga kirish
uchun siz chaqirilgan funksiya nomini u e'lon qilingan nom maydonlari
nomlari bilan to‘ldirishingiz kerak, masalan:
int main( )
Window::Pane::size( 10, 20 ) ;
return 0 ;
NOMLAR MAYDONIDAN FOYDALANISH
Endi nomlar maydoni va tegishli ko'rish operatoridan foydalanish
misolini ko'rib chiqing. Birinchidan, barcha turdagi va funksiyalar
Windows nom maydonida e'lon qilinadi, shundan so'ng a'zo
funksiyalarning ta'riflari undan keyin keladi. Ism maydonida e'lon
qilingan funksiyani aniqlash uchun, Listing 14.10 da bo'lgani kabi,
funksiya nomidan oldin nom maydoni nomi va ko'rish operatorini
o'rnatishingiz kerak.
Listing 14.10. Ism maydonidan foydalanish
1 #include <iostream>
2 using namespace std;
3 namespace Window
4{
5 const int MAX_X = 30 ;
6 const int MAX_Y = 40 ;
7 class Pane
8{
9 public:
10 Pane() ;
11 ~Pane();
12 void size( int x, int y ) ;
13 void move( int x, int y ) ;
14 void show( ) ;
15 private:
16 static int cnt ;
17 int x ;
18 int y ;
19 };

168
20 }
21 int Window::Pane::cnt = 0 ;
22 Window::Pane::Pane() : x(0), y(0) {}
23 Window::Pane::~Pane() {}
24 void Window::Pane::size( int x, int y )
25 {if( x < Window::MAX_X && x > 0 )
26 Pane::x = x;
27 if( y < Window::MAX_Y && y > 0 )
28 Pane::y = y ;}
29 void Window::Pane::move( int x, int y )
30 {if( x < Window::MAX_X && x > 0 )
31 Pane::x = x;
32 if( y < Window::MAX_Y && y > 0 )
33 Pane:: y = y;}
34 void Window:: Pane:: show( )
35 {cout << "x " << Pane::x ;
36 cout << " y " << Pane::y << std::endl ;}
37 int main(){
38 Window::Pane pane ;
39 pane. move( 20, 20 ) ;
40 pane. show( );
41 return 0 ;
42 }

Natija:
x 20 y 20
USING KALIT SO’ZI
Using kalit so'zi nom maydoni a'zolarini e'lon qilishda operator
sifatida ham, sifatida ham ishlatilishi mumkin, ammo
using foydalanish sintaksisi o'zgaradi.
Using kalit so'zi bilan nomlar maydonining barcha a'zolarining
ko'lami kengayadi. Keyinchalik, bu bo‘sh joyning tegishli nomini
ko'rsatmasdan, nomlar maydoni a'zolariga murojaat qilish imkonini
beradi. Foydalanish quyidagi misolda ko'rsatilgan:
Listing 14.11
1 namespace Window {
2 int value1 = 20;
3 int value = 40;
4 Window::value1 = 10 ;
5 using namespace Window ;
6 value2 = 30;}
Windows nom maydonining barcha a'zolari namespace Window-
dan foydalanish satridan boshlab ko'rinadi va tegishli dastur modulining
oxirigacha. E'tibor bering, agar dastur fragmentining yuqori qismidagi
value1 o'zgaruvchisiga kirish uchun nomlar maydoni ko'rsatilishi kerak
169
bo'lsa, value2 o'zgaruvchisiga kirishda bu kerak emas, chunki using
operatori Window nom maydonining barcha a'zolarini ko'rinadigan
qilib qo'ygan.
Using operatori har qanday modulda turli xil doiradagi
dasturlardan foydalanishi mumkin. Dasturning bajarilishi ushbu modul
doirasidan tashqariga chiqqanda, ushbu modulda ochilgan nom
maydonining barcha a'zolari avtomatik ravishda ko'rinmas bo'lib
qoladi. Buni quyidagi misol bilan tahlil qiling:
Listing 14.12
1 namespace Window {
2 int value1 = 20 ;
3 int value2 = 40 ;
4 //.
5 void f()
6 using namespace Window ;
7 value2 = 30 ;
8 value2 = 20; / / xato!
Funksiya kodining oxirgi qatori f () - value2 = 20-kompilyatsiya
vaqtida xatolikka olib keladi, chunki value2 o'zgaruvchisi bu joyda
ko'rinmaydi. Using operatori tomonidan berilgan ushbu
o'zgaruvchining ko'rinishi dasturning oldingi qatoridagi yopilish
qavslari orqasida tugadi.
Lokal o'zgaruvchilar moduli ichida e'lon qilingan taqdirda, ushbu
modulda ochilgan nom maydonining barcha bir xil nomdagi
o'zgaruvchilari yashirin bo'ladi. Bu global o'zgaruvchilarni, agar
ularning ko'lami bir-biriga to'g'ri kelsa, lokal o'zgaruvchilarni
yashirishga o'xshaydi. Nom maydonida e'lon qilingan o'zgaruvchi lokal
o'zgaruvchi e'lon qilinganidan keyin using yordamida ochilgan bo'lsa
ham, ikkinchisi hali ham ustuvor bo'ladi. Bu quyidagi misolda aniq
ko'rsatilgan:
Listing 14.13
namespace Window {
int value1 = 20 ;
int value2 = 40 ;
void f()
int value2 = 10 ;
using namespace Window ;
std::cout << value2 << std::endl;}

Ushbu funksiya bajarilganda, Windows nom maydonining value2


o'zgaruvchisi f () funksiyasining value2 o'zgaruvchisi tomonidan

170
yashirilganligini tasdiqlovchi 40 emas, balki 10 qiymati ekranda paydo
bo'ladi. Agar siz hali ham nom maydoni o'zgaruvchisidan
foydalanmoqchi bo'lsangiz, bo'sh joy nomini aniq ko'rsating.
Ulardan biri global deb e'lon qilingan, ikkinchisi esa nomlar
maydoni ichida bir xil nomdagi identifikatorlardan foydalanganda ham
noaniqlik paydo bo‘lishi mumkin. Bunga yo'l qo'ymaslik uchun,
dasturning keyingi qismida bo'lgani kabi, obyektni chaqirishda har
doim bo'sh joy nomini aniq ko'rsating:
Listing 14.14
namespace Window{
int value1 = 20 ;
using namespace Window ;
int value1 = 10 ;
void f( )
value1 = 10 ;
Ushbu misolda noaniqlik f () funksiyasi ichida paydo bo'ladi. Using
operatori Window::value1 o'zgaruvchisiga global ko'lamni bildiradi.
Biroq, dastur xuddi shu nomdagi boshqa global o'zgaruvchini e'lon
qiladi. F () funksiyasida qaysi biri ishlatiladi? E'tibor bering, xato xuddi
shu nomdagi global o'zgaruvchini e'lon qilish paytida emas, balki f ()
funksiyasining tanasida unga murojaat qilganda ko'rsatiladi.
Ushbu usul quyidagi misolda ko'rsatilganidek, nomlar maydonida
e'lon qilingan faqat bitta identifikator uchun ko'rinishni ochish uchun
ishlatiladi:
Listing 14.15
namespace Window {
int value1 = 20 ;
int value2 = 40
int value3 = 60 ;
Windows:: value2; / / value2ga kirishni ochish
Window:: value1 = 10; / / value1 uchun nom maydoni
value2 = 30 ;
Window:: value3 = 10: / / value3 uchun nom maydoni
Shunday qilib, using yordamida siz ushbu maydonda berilgan
boshqa identifikatorlarga ta'sir qilmasdan, alohida nom maydoni
identifikatoriga joriy doiraga kirishni ochishingiz mumkin. Oldingi
misolda value2 o'zgaruvchisi nom maydonini aniq ko'rsatmasdan
chaqiriladi, bu value1 va value3 ga kirishda mumkin emas. E'londa
usingdan foydalanish har bir nom maydoni identifikatorining
ko'rinishini qo'shimcha nazorat qilishni ta'minlaydi. Bu bir vaqtning

171
o'zida nom maydonining barcha identifikatorlariga kirishni ochadigan
operator sifatida foydalanishdan farq qiladi.
Agar nomlar maydonidan identifikator allaqachon e'lon qilingan
lokal maydonga bir xil nomdagi boshqa identifikator qo'shilsa, bu
kompilyatsiya xatosiga olib keladi. Shuningdek, xuddi shu nomdagi
boshqa identifikator mavjud bo'lgan hududdagi nomlar maydonidan
identifikatorni e'lon qilish bo'ladi. Bu quyidagi misolda ko'rsatilgan:
Listing 14.16
namespace Window{
int value1 = 20 ;
int value2 = 40 ;
void f()
int value2 = 10 ;
Windows:: value2; / / bir qator e'lonlar
std::cout << value2 << std::endl ;}
F () funksiyasining ikkinchi qatorini kompilyatsiya qilish xatoga
olib keladi, chunki ushbu blokda value2 deb nomlangan o'zgaruvchi
allaqachon e'lon qilingan. Agar lokal value2 o'zgaruvchisini e'lon
qilishdan oldin using bilan e'lon joylashtirilsa, xuddi shu natija olinadi.
Using yordamida lokalhududga kiritilgan nom maydoni
identifikatori ushbu hududdan tashqarida e'lon qilingan shunga
o'xshash identifikatorni yashiradi. Quyidagi misolni tahlil qiling:
Listing 14.17
namespace Window {
int value1 = 20;
int value2 = 40 :
int value2 = 10 ;
void f()
using Window:: value2 ;
std::cout << value2 << std::endl;}
Yuqorida ta'kidlab o'tilganidek, usingdan foydalanishning ushbu
usuli sizga alohida nomlar maydoni identifikatorlarining ko'lamini
qo'shimcha ravishda boshqarish imkonini beradi. Using operatori
nomlar maydonida e'lon qilingan barcha identifikatorlarga lokal
hududda kirish huquqini ochadi. Using operatoridan foydalanish faqat
nomlar maydonining barcha identifikatorlariga bir vaqtning o'zida
kirish huquqini ochish zarur bo'lganda oqlanadi.

ISMLAR MAYDONI
Ismlar maydoni nomlangan maydonning qo'shimcha nomini
yaratish uchun ishlatiladi. Quyidagi misolni ko'rib chiqing:

172
Listing 14.18
namespace the_software_company {
int value ;
the_software_company::value = 10 ;
namespace TSC = the_software_company ;
TSC::value = 20 ;
Ushbu usulning salbiy tomoni shundaki, bunday nom ko'rsatilgan
ko‘lamda mavjud bo‘lishi mumkin. Bunday holda, kompilyator xato
haqida xabar beradi va siz shunchaki nomlar maydonini
o'zgartirishingiz mumkin.
Bunday ismlar nomlari nomlanganlardan farq qiladi, chunki ular
nomga ega emaslar. Ular ko'pincha global ma'lumotlarni potensial nom
to'qnashuvlaridan himoya qilish uchun ishlatiladi. Bunday nom
maydonida e'lon qilingan barcha identifikatorlar hech qanday prefikssiz
oddiygina nom bilan chaqiriladi. Quyidagi kod ikki xil faylda
joylashgan ikkita nomlanmagan nomlar maydonining namunalarini
taqdim etadi.
Listing 14.19
// fayl: one. cpp
namespace
int value ;
char p( char ×p ) ;
//.
// fayl: ikki.cpp
namespace
int value :
char p( char •p ) ;
//.
int main( )
char c = p( ptr ) ;
Har bir faylda qiymat o'zgaruvchisi va p () funksiyasi e'lon qilinadi.
Har bir fayl uchun o'ziga xos nomlanmagan maydon berilganligi
sababli, bitta dastur fayllari ichidagi bir xil nomdagi identifikatorlarga
murojaat qilish nomlarning to'qnashuviga olib kelmaydi. Bu p()
funksiyasini chaqirganda aniq ko'rinadi. Nomlanmagan nomlar
maydonining ishlashi tashqi bog'langan statik obyektning ishiga
o'xshaydi, masalan
static int value = 10 ;
Shuni unutmangki, statik kalit so'zidan bunday foydalanish
standartlashtirish qo'mitasi tomonidan tavsiya etilmaydi. Bunday
muammolarni hal qilish uchun endi standart nomlar maydonlari
qo'llaniladi.

173
STD STANDART NOM MAYDONI
Standart nomlar maydonlari eng yaxshi namunasini C++ standart
kutubxonasida topish mumkin. Standart kutubxonaning barcha
funksiyalari, sinflari, obyektlari va shablonlari std nom maydonida e'lon
qilinadi.
Ehtimol, siz bunday ifodalarni ko'rishingiz kerak edi:
#include <iostream>
using namespace std;
Shuni unutmangki, using e’lonidan foydalanish nomlangan nom
maydonining barcha identifikatorlariga kirish imkonini beradi. Shuning
uchun standart kutubxonalar bilan ishlashda ushbu operatorning
yordamiga murojaat qilmaslik yaxshiroqdir.
Global maydon tom ma'noda standart kutubxonaning sarlavha
fayllaridan turli xil identifikatorlarning nomlari bilan to‘ldiriladi,
ularning aksariyati ushbu dasturda ishlatilmaydi. Esda tutingki, barcha
sarlavha fayllari nom maydoni vositasidan foydalanadi, shuning uchun
agar siz dasturga bir nechta sarlavha fayllarini qo'shsangiz va using
operatoridan foydalansangiz, ushbu sarlavha fayllarida e'lon qilingan
barcha identifikatorlar global ko'rinishga ega bo'ladi. Siz ushbu
kitobning aksariyat misollarida ushbu qoida buzilganligini payqagan
bo‘lishingiz mumkin. Bu faqat misollarning qisqacha mazmuni uchun
qilingan. Siz o'zingizning dasturlaringizda quyidagi misolda bo'lgani
kabi foydalanish kalit so'zi bilan e`lonlardan foydalanishingiz kerak:
Listing 14.20
#include <iostream>
using std::cin ;
using std::cout ;
using std::endl ;
int main( ){
int value = 0 ;
cout << "So, how many eggs did you say you wanted?" << endl ;
cin >> value ;
cout << value << " eggs, sunny-side up!" << endl ;
return( 0 ) ;}
Ushbu dasturni bajarish quyidagi xulosaga olib keladi:
So, how many eggs did you say you wanted?
4
4 eggs, sunny-side up!
Shu bilan bir qatorda, nomlar maydonida e'lon qilingan
identifikatorlarga aniq murojaat qilish mumkin:

174
Listing 14.21
#include <iostream>
int main( ){
int value = 0 ;
std::cout << "How many eggs did you want?" << std::endl ;
std::cin >> value ;
std::cout << value << " eggs, sunny-side up!" << std::endl ;
return( 0 );}
Dastur quyidagi ma'lumotlarni chiqaradi:
How many eggs did you want?
4
4 eggs, sunny-side up!
Ushbu yondashuv kichik dastur uchun juda mos keladi, ammo katta
dasturlarda nom maydoni identifikatorlariga barcha aniq murojaatlarni
kuzatish juda qiyin bo'ladi. Tasavvur qiling: standart kutubxonadan har
bir nom uchun std:: qo'shishingiz kerak bo'ladi!
Nazorat savollari va topshiriqlar:
1. Ism maydonida e'lon qilingan identifikatorlardan foydalanish kalit
so'zini ishlatmasdan foydalanish mumkinmi?
2. Nomlangan va nomlanmagan nomlar maydoni orasidagi asosiy
farqlarni ayting.
3. Standart std nom maydoni nima?
4. Xatolar: quyidagi kodda xato toping:
#include <iostream>
int main()
{
cout << "Hello world!" << end;
return 0;}
5. 4-mashq kodida topilgan xatoni tuzatishning uchta usulini sanab
o'ting.

175
15-MAVZU. OOP (OBYEKTGA YO ’NALTIRILGAN
DASTURLASH ) HAQIDA TUSHUNCHA. C++ DA STRUKTURALAR .
 Obyektga yo'naltirilgan dasturlash yondashuvlari asosida
muammolarni tahlil qilish va yechimlarni topish
 Vazifalarning maqbul yechimlarini topish uchun samarali
obyektga yo'naltirilgan dasturlarni qanday loyihalash kerak?
 Tahlil va loyihalashni hujjatlashtirish uchun yagona
modellashtirish tilidan (UML) qanday foydalanish kerak?

C++ OBYEKTGA YO'NALTIRILGAN DASTURLASH


TILIMI?
C++ tili obyektga yo'naltirilgan dasturlashning yangi tamoyillari va
tijorat dasturlarini ishlab chiqarish uchun dunyodagi eng mashhur C
dasturlash tili o'rtasidagi bog'liqlik sifatida yaratilgan.
90-yillarning oxirida yaratilgan dasturlar o'n yil boshida
yozilganlardan tubdan farq qiladi. Odatda, protsessual yondashuvlarga
asoslangan dasturlarni boshqarish, qo'llab-quvvatlash va
modernizatsiya qilish qiyin.
Grafik foydalanuvchi interfeyslari, Internet, sonli kanallar orqali
telefon liniyalariga kirish va ko'plab yangi texnologiyalar loyihalarning
murakkabligini keskin oshirdi, iste'molchilarning foydalanuvchi
interfeysi sifatiga bo'lgan umidlari ham o‘zgarmas ravishda oshib bordi.
Dasturlarning bunday tez sur'atlar bilan murakkablashishi hujumi
ostida ishlab chiquvchilar yangi dasturlash yondashuvlarini izlashga
majbur bo‘lishdi. Eski protsessual yondashuvlar bugungi kun
talablaridan tobora orqada qoldi. Dasturlar tezda eskirgan va
protsessual dasturni modernizatsiya qilish yangisini ishlab chiqarishdan
oson bo'lmagan. Dasturlarning hajmi oshgani sayin, ularni disk
raskadrovka qilish ancha murakkablashdi. Loyihalar ko'pincha bozorga
chiqmasdan oldin eskirgan. Ushbu loyihalarni qo'llab-quvvatlash va
modernizatsiya qilish xarajatlari ularni amalga oshirishdan tushgan
daromaddan oshib ketdi.
Shunday qilib, obyektga yo'naltirilgan dasturlashning yangi
yondashuvlarini hayotga tatbiq etish dasturchilarning injiqligi emas,
balki yagona najot edi.
Obyektga yo'naltirilgan dasturlash tillari ma'lumotlar tuzilmalari
va ushbu ma'lumotlarni qayta ishlash usullari o'rtasida mustahkam
aloqani yaratadi. Eng muhimi shundaki, bunday dasturlash bilan
176
ma'lumotlar alohida modullarda qanday saqlanishi va qayta ishlanishi
haqida o'ylashning hojati yo'q. Dasturchi shunchaki obyekt
interfeysidan qanday ma'lumotlarni uzatishi kerakligini va nimani
qaytarishini bilib oladi, shundan so'ng u o'z dasturida tayyor moduldan
foydalanadi.
MODELLARNI QURISH
Atrofdagi dunyo obyektining barcha belgilari va aloqalarini
kuzatish uchun biz koinotning modelini yaratishimiz kerak edi, shuning
uchun bu dunyoda hamma narsa bir-biri bilan bog'liq. Modelning
maqsadi haqiqiy dunyoning mazmunli mavhumligini yaratishdir.
Bunday mavhumlik dunyoning o'ziga qaraganda sodda bo‘lishi kerak,
lekin ayni paytda uni yyetarlicha aniq ko'rsatishi kerak, shunda model
Real dunyoda obyektlarning xatti-harakatlarini bashorat qilish uchun
ishlatilishi mumkin.
-bu oddiy globus. Model obyektning o'zi emas; biz
hech qachon globusni yer sayyorasi bilan almashtirib yubormaymiz,
lekin birinchisi ikkinchisini shunchalik yaxshi tasvirlaydiki, biz
globusni o'rganish orqali yerni o'rganishimiz mumkin.
Yaxshi obyektga yo'naltirilgan dasturni yaratish, aslida dasturlash
yordamida haqiqiy obyektlarni modellashtirishdir. Bunday virtual
modelni yaratish uchun, birinchidan, dasturlash vositalarini va
ikkinchidan, ushbu vositalar yordamida dasturni qurish ketma-ketligini
yaxshi bilish muhimdir.
MODELLASHTIRISH TILI
-bu asosan fantastika, dasturni qog'ozda
oldindan modellashtirish tamoyillari bo'yicha kelishuvlar to'plami.
Keling, qog'ozdagi sinflarni uchburchak rasmida tasvirlashga va
ular orasidagi meros munosabatlarini asosiy sinfdan hosilaga nuqta
o'qlar rasmida tasvirlaylik. Masalan, biz 15.1-rasmda ko'rsatilgandek,
flower (gul) sinfidan olingan Geranium (Geranium) sinfini
modellashtiramiz.

177
15.1-rasm. Sinf merosining sxematik tasviri
Rasmda Geranium gulning o'ziga xos turi ekanligi ko'rsatilgan va
bu haqiqiylikka to'liq mos keladi. Vaqt o'tishi bilan biz ko'plab
murakkab munosabatlarni modellashtirishni xohlaymiz va dastur
obyektlarining o'zaro bog'liqligini aks ettiruvchi diagrammalar yaratish
bo'yicha Konvensiya va qoidalar to'plamini ishlab chiqamiz.
Bunday holda, hamma uchun tushunarli bo'lgan yagona
modellashtirish tilining mavjudligi foydali bo'ladi. Shunga qaramay,
bunday til yaratildi va uning nomi UML (Unified Modeling Language-
yagona modellashtirish tili). Uning vazifasi diagrammalardagi
obyektlar o'rtasidagi munosabatlarni xaritalashda bir xillikka
erishishdir. UML tili konvensiyalariga muvofiq, bizning sxemamiz
15.1-rasm boshqacha tasvirlangan bo‘lishi kerak (15.2-rasm).

15.2-rasm. UML konvensiyalarini hisobga olgan holda


meros munosabatlari
UML konvensiyalari juda oddiy. Diagrammalarni tushunish va
ulardan foydalanish qiyin emas. Ushbu konvensiyalarni ushbu bobni
o'zlashtirish jarayonida aniq misollar bilan ko'rib chiqamiz, bu UMLni
kontekstdan tashqarida o'rganish ancha oson.

178
DASTURLARNI LOYIHALASH JARAYONI
Obyektga yo'naltirilgan dasturni tahlil qilish va loyihalashni to'g'ri
bajarish modellashtirish tili konvensiyalariga rioya qilishdan ko'ra
muhimroqdir.
Ko'pgina nashrlar va konferensiyalar ushbu mavzuga
bag'ishlangan. Va agar modellashtirish tili haqida umumiy
kelishuvlarga erishish va UML ishlab chiqarish mumkin bo'lsa, unda
dasturlarni tahlil qilish va loyihalashning asosiy sabablari bo'yicha
tortishuvlar bugungi kungacha davom etmoqda.
Hatto yangi kasb paydo bo'ldi, bular dasturlash
usullarini o'rganadigan va ishlab chiqadigan dasturchilar. Ko'pincha
adabiyotda siz yangi dasturlash usulini tavsiflashga bag'ishlangan
maqolalarni topishingiz mumkin. - bu modellashtirish tili
tahlili va loyihalash yondashuvlarining kombinatsiyasi. Dunyodagi eng
mashhur uchta metodolog - Buch metodini yaratgan Grady Booch,
obyektga yo'naltirilgan dasturlash yondashuvlarini ishlab chiqqan Iver
Jakobson va obyektni modellashtirish texnologiyasini yaratgan Jeyms
Rambaugh.
Ushbu darsda keltirilgan material taxminan objectory metodlariga
amal qiladi.
Dasturlarni loyihalash jarayoni iterativdir. Bu shuni anglatadiki,
dasturni ishlab chiqarishda biz vaqti-vaqti bilan butun jarayonni
takrorlaymiz, chunki talablarni tushunish kuchayadi.
Iterativ rivojlanishni kaskadli rivojlanishdan ajratish kerak, bunda
bir bosqichdan chiqarish keyingi bosqichga kirish bo'ladi va orqaga yo'l
yo'q (15.3-rasm).
Loyiha ustida ishlash loyiha talablarini rasmlantirishdan
boshlanadi, ular rivojlanish jarayonida o'zgarishi mumkin, bu esa
allaqachon yaratilgan dasturiy ta'minot bloklariga o'zgartirishlar
kiritishni talab qiladi. Katta loyiha alohida bloklarga bo'linadi, ular
uchun avval prototip lar, so'ngra ularni bajarish tartiblari yaratiladi.
Alohida modullarning bajarilishini sinab ko'rish ularning prototiplariga
o'zgartirishlar kiritish zarurligiga olib kelishi mumkin va alohida
bloklardagi o'zgarishlar ularni vaqti-vaqti bilan butun loyihada o'zaro
ta'sir qilish tamoyillarini qayta ko'rib chiqarishga majbur qiladi.

179
15.3-rasm. Loyihalash jarayoni
Ishlar ketma-ketligini yana bir bor takrorlaymiz:
1. Kontsepsiyani ishlab chiqarish.
2. Tahlil qilish.
3. Loyihalash.
4. Amalga oshirish.
5. Sinov.
6. Qaytish.
- afsuski, haqiqiy hayotdan uzoq bo'lgan
sof g'oyani ko'tarishdir;
-bu loyiha talablarini anglash jarayoni;
-bu kod yaratiladigan sinf modelini rasmlantirish jarayoni;
-kod yozish (masalan, C++ da);
- hamma narsa yaxshi yoki yo'qligini tekshirish;
-bu sizning mahsulotingizni mijozga berilishi mumkin bo'lgan
holatga keltirishdir.
Bularning barchasini amalda qo'llash qoladi.
DOMEN MODELINI YARATISH
- bu domen (dasturiy mahsulotdan foydalanish
sohasi) haqida ma'lum bo'lgan hamma narsani yozib oladigan hujjat.
Domen modeli domen obyektlaridan iborat bo'lib, ularning har biri
tizimdan foydalanish holatlarini tavsiflashda aytib o'tilgan ma'lum bir
elementga mos keladi.
Biz dasturiy obyektlar bilan emas, balki loyihani ishlab chiqarishda
hisobga olinishi kerak bo'lgan haqiqiy ishtirokchilar bilan
shug'ullanayotganimizni tushunish muhimdir. Hech kim bizni har bir
domen obyekti uchun dasturda obyektlar yaratishga majburlamaydi.
UML konvensiyalaridan foydalanib, diagramma yaratish
mumkin, unda domen obyektlari o'rtasidagi munosabatlar xuddi

180
dasturdagi sinflar o'rtasidagi munosabatlar tasvirlanganidek aks
ettiriladi. Bu UMLning kuchli tomonlaridan biri: loyihalashning barcha
bosqichlarida bir xil vositalardan foydalanish mumkin.
Masalan, hisob-kitob va depozit hisobvaraqlari bank
hisobvarag'ining umumiy tushunchasiga aniqlik kiritilganligini qayd
etish mumkin. UMLda olingan sinflarning umumlashtirilishi asosiy
o'qlar yordamida ko'rsatiladi (15.4-rasm)
Ushbu rasmda ko'rsatilgan diagrammada to'rtburchaklar turli xil
domen obyektlarini, yuqoriga yo'naltirilgan o'qlar esa xususiy
obyektlarni umumlashtirishni anglatadi. Shunday qilib, C++ tili nuqtai
nazaridan aytish mumkinki, domen obyektlari joriy hisob va depozit
hisobvarag'i obyektdan olingan bank hisobvarag'i.

15.4-rasm. UML vositalari bilan ifodalangan domen obyektlari


o'rtasidagi munosabatlar
- bu turli xil munosabatlarni o'rnatish uchun ishlatilishi
mumkin bo'lgan boy modellashtirish tili. Biroq, biz uchun eng muhimi
umumlashtirish, investitsiya va assotsiatsiya munosabatlari bo'ladi.
ESLATMA: Yana shuni esda tutingki, bu holda domen obyektlari
o'rtasidagi munosabatlar ko'rib chiqiladi. Keyinchalik, loyihani ishlab
chiqarishda siz sinflarni meros qilib olish orqali checkingaccount (joriy
hisob) va BankAccount (bank hisobvarag'i) sinf obyektlari o'rtasidagi
ushbu munosabatlarni amalga oshirishni xohlashingiz mumkin, ammo
bu loyihani ishlab chiqarishning mumkin bo'lgan variantlaridan biri
bo'ladi. Hozircha biz haqiqiy domen obyektlari bir-biri bilan qanday
aloqa qilishini tushunishga harakat qilmoqdamiz.

181
UMUMLASHTIRISH
ko'pincha merosning sinonimi sifatida qaraladi,
ammo ular o'rtasida sezilarli farq bor. Umumlashtirish munosabatlar
turini tavsiflaydi, meros esa dasturlash orqali umumlashtirishni amalga
oshirishdir.
Umumlashtirish shuni anglatadiki, olingan obyekt bazaning pastki
turi hisoblanadi.
Shunday qilib, joriy hisob-bu bank hisobining bir turi. O'z
navbatida, bank hisobvarag'i hisob-kitob va depozit hisobvaraqlarining
atributlari va xususiyatlarini umumlashtiradi.
Ko'pincha bitta obyekt ko'plab kichik obyektlardan iborat.
Masalan, mashina rul, shinalar, eshiklar, Vites qutisi va boshqalardan
iborat. Joriy hisob qoldiqdan, tranzaktsiyalar yozuvidan, mijoz kodidan
va boshqalardan iborat. UML yordamida o'z-o'zidan joylashtirish yoki
tarkib tashqi obyektdan ichki obyektga yo'naltirilgan uchida olmosli o'q
bilan ko'rsatiladi (15.5-rasm).

15.5-rasm. Investitsiyalarning nisbati

15.6-rasm. Obyektlar orasidagi murakkab munosabatlar


15.5-rasm diagrammasi shuni ko'rsatadiki, joriy hisob obyektida
boshqa domen obyekti - qoldiq mavjud. Juda murakkab munosabatlar
to'plamini ko'rsatish uchun oldingi ikkita diagrammani birlashtirish
mumkin (15.6-rasm).
15.6-rasm diagrammasi shuni ko'rsatadiki, hisob-kitob hisobvarag'i
va depozit hisobvarag'i obyektlari bank hisobvarag'iga umumlash-
182
tiriladi va qoldiq obyektlari va tranzaktsiyalar yozuvlari bank
hisobvarag'i obyektiga kiritiladi.
Assotsiatsiya ikkita obyekt bir-birini "biladi" va qandaydir tarzda
o'zaro ta'sir qiladi deb taxmin qiladi. Ta'rif loyihalash bosqichida ancha
aniqroq bo'ladi, ammo tahlil qilish uchun faqat A obyekti va B obyekti
o'zaro ta'sir qiladi deb taxmin qilinadi, ammo ularning hech biri
boshqasining shaxsiy turini o'z ichiga olmaydi. UMLda ushbu
assotsiatsiya obyektlar orasidagi oddiy tekis chiziq bilan ko'rsatilgan
(15.7-rasm).

15.7-rasm. Assotsiatsiya munosabati


15.7-rasm diagrammasi A obyekti B obyekti bilan qandaydir tarzda
o'zaro ta'sir qilishini anglatadi.
Endi biz dasturdan foydalanishning barcha holatlarini va domen
obyektlari o'rtasidagi munosabatlarni namoyish qilish vositalarini
tushunganimizdan so'ng, dasturiy mahsulotga qo'yiladigan talablarni
batafsil ko'rib chiqishimiz mumkin.
Har bir foydalanish holatini bir qator senariylarga bo‘lish mumkin.
- bu foydalanish holatlarini aniqlaydigan muayyan holatlar
to'plamining tavsifi. Masalan, mijoz hisobdan pul olib qo'yadigan
foydalanish holati bir nechta senariylarga ega bo‘lishi mumkin.
Misol uchun:
1. Mijoz joriy hisobvaraqdan 300 dollar olish to'g'risida so'rov
yuboradi, hamyoniga naqd pul qo'yadi va kvitansiyani kutadi.
2. Mijoz joriy hisobvaraqdan $300 olish uchun so'rov yuboradi,
ammo hisobdagi qoldiq atigi $200. U amalni amalga oshirish uchun
joriy hisobvaraqda pul yetarli emasligi haqida ma'lumot oladi.
3. Mijoz joriy hisobvaraqdan 300 dollar olish to'g'risida so'rov
yuboradi, ammo bugungi kunda ushbu hisobvaraqdan 100 dollar olib
tashlangan va kunlik limit 300 dollarni tashkil etadi. Unga faqat 200
dollarni olib qo'yishga ruxsat berilganligi haqida ma'lumot keladi.
4. Mijoz joriy hisobvaraqdan 300 dollar olish to'g'risida so'rov
yuboradi, ammo kvitansiyalarni chop etish uchun rulonda qog'oz
183
tugadi. U yuzaga kelgan texnik nosozlik haqida ma'lumot oladi va bank
xodimlari ushbu muammoni hal qilishini kutish taklifini oladi.
Senariylar ro’yxatini davom ettirish mumkin. Har bir senariy
tizimdan foydalanishning dastlabki holati variantini belgilaydi.
Ko'pincha bunday variantlar alohida holatlardir (hisobdagi pul yetarli
emas, texnik nosozlik va boshqalar). Ba'zan senariy foydalanuvchiga
taklif qilingan yechim variantini o'z ichiga oladi. Masalan, mijozni
yopilishidan oldin hisob sonidan pul o'tkazishni taklif qilish. Siz son-
sanoqsiz turli xil senariylarni o'ylab topishingiz mumkin, ammo ular
orasida faqat tizim unga qo'yiladigan talablarda ifodalangan muayyan
harakatlar bilan javob berishga tayyor bo'lganlarni tanlashingiz kerak.
Har bir foydalanish holati uchun Senariylar ro’yxati aniqlagandan
so'ng, talablar hujjatiga kiritilgan va bir qator ta'riflarni o'z ichiga olgan
barcha senariylar uchun qo'llanmalar ishlab chiqilishi kerak.
1. Senariyning boshlanishini belgilaydigan shartlar.
2. Ushbu senariyni bajarishni o'z ichiga olgan kalitlar.
3. Foydalanuvchi tomonidan bajariladigan harakatlar.
4. Dasturni bajarish uchun kerakli natijalar.
5. Foydalanuvchiga qaytarilgan ma'lumotlar.
6. Boshlang'ich takrorlashlar va ulardan chiqarish shartlari.
7. Ssenariyning mantiqiy tavsifi.
8. Ssenariyni tugatish sharti.
9. Ssenariyni bajarish natijalari.
Ushbu jadval turli xil foydalanish holatlari o'rtasidagi
munosabatlar ko'rsatilganda ancha foydali bo'ladi. Bunday
munosabatlarning faqat ikkitasi bo‘lishi mumkin: foydalanish va
kengaytirish. Foydalanish munosabati bir vaziyat boshqasidan
foydalanishini anglatadi. Masalan, tizimda Listingdan o'tmasdan
hisobdan pul olishning iloji yo'q. Ushbu munosabat 15.9-rasmda
ko'rsatilgan.

184
15.8-rasm. Foydalanish holati diagrammasi

15.9-rasm. Foydalanish holati o'rtasidagi bo'ysunish munosabati


15.9-rasmda hisobdan pul olish uchun tizimda Listingdan o'tish
kerakligi ko'rsatilgan. Shunday qilib, vaziyat hisobdan chiqarish
vaziyatdan foydalanadi tizimda Listingdan o'tish, ya'ni Listingdan o'tish
amali hisobdan chiqarish amalining bir qismidir.
Foydalanish holatini kengaytirish turli vaziyatlar o'rtasida
qandaydir mantiqiy shartli munosabatlarni o'rnatishni o'z ichiga oladi,
bu sinflarni meros qilib olish orqali ham amalga oshirilishi mumkin.
Umuman olganda, obyektni modellashtirish bo'yicha mutaxassislar
orasida foydalanish va kengayish o'rtasidagi farq haqida juda ko'p
kelishmovchiliklar mavjud, ularning aksariyati ikkinchi atamani juda
noaniq deb hisoblamaydilar. Shaxsan men bir amal boshqasini bajarish
uchun mutlaqo zarur bo'lganda foydalanish atamasiga murojaat
qilaman. Agar amalni bajarish bir qator shartlar bilan cheklangan bo'lsa,
men foydalanish holatini kengaytirish atamasidan foydalanaman.
Ba'zi dasturlar har qanday tizimdan tashqarida mustaqil ravishda
ishlash uchun yoziladi, faqat oxirgi foydalanuvchi bilan bevosita
aloqada bo'ladi. Biroq, ko'pincha mavjud tizimga kiritilishi kerak
bo'lgan loyihalarni ishlab chiqarish kerak. Bunday holda, o'zaro aloqani
o'rnatish uchun zarur bo'lgan tizimlarning barcha tafsilotlari va
mexanizmlarini tahlil qilish kerak. Mavjud tizim bilan aloqalar statik
yoki dinamik bo'ladi.
VIZUALIZATSIYA
talablar hujjatining yakuniy qismidir. Ushbu moda
nomi yaratilgan mahsulotning grafik foydalanuvchi interfeysini
loyihalashda yordam berish uchun yaratilgan diagrammalar, chizmalar,
ekran tasvirlari, prototiplar va boshqa vizual vositalar.
Katta loyihalarni yaratishda tizimning muayyan vaziyatlarda o'zini
qanday tutishini yaxshiroq tasavvur qilish uchun loyihaning to'liq

185
prototipini ishlab chiqarish foydali bo‘lishi mumkin. Ko'pincha,
hujjatlarga grafik dastur loyihaga qo'yiladigan talablarni aniqlash
funksiyasi bilan eng yaxshi ishlaydi, chunki bu tizim qanday bo‘lishi
kerakligini va uning yakuniy versiyada qanday ishlashini aniq ko'rish
imkonini beradi.
Tahlil va loyihalashning har bir bosqichi oxiriga kelib,
deb nomlangan bir qator hujjatlar to'planadi. Bunday hujjatlarning
taxminiy to'plami 15.1-jadvalda ko'rsatilgan.

Artefakt Tavsif
Foydalanuvchi interfeysini vizualizatsiya
Foydalanish qilish bilan tizimdan foydalanishning barcha
holatlarining holatlari, senariylar, stereotoqimlar, dastlabki
tavsifi shartlar va bajarilish natijalari to'g'risida
batafsil hujjat
Loyiha ishlab chiqilayotgan domen
Domen modeli obyektlarining munosabatlar diagrammasi

Hamkorlik xuddi shu muammoni hal qilishda ishtirok


tashkilotining etadigan tashqi obyektlar va tizimlar o'rtasidagi
diogrammalari munosabatlarning diogrammalari

Mavjud Loyiha ishlab chiqilayotgan past darajadagi


tizimlarni tahlil apparat tizimining tavsifi va diagrammalari
qilish

Ilova talablari Ushbu loyihaga mijozning talablari tavsifi


Loyihani ishlab chiqarishda hisobga olinishi
Сheklovlar kerak bo'lgan tizim platformasi cheklovlari va
to'g'risidagi mo'ljallangan mijozlarning xususiyatlari tavsifi
hisobot
Hisob-kitob va Loyihani ishlab chiqarish vaqti va bosqichlari
taqvim rejasi va har bir bosqich bajarilgandan keyin mijozga
taqdim etiladigan materiallar ko'rsatilgan
kalendar rejasi
15.1-jadval. Loyiha hujjatlarini tashkil etuvchi artefaktlar

186
LOYIHALASH
Tahlil davomida asosiy e'tibor domenni ko'rib chiqarish va loyiha
vazifalari va talablarini aniqlashga qaratilgan bo'lsa, loyihalash
yechimlarni topishga qaratilgan. - bu dasturlash orqali
bizning ideal modelimizni amaliy amalga oshirishni rejalashtirish.
Ushbu jarayonning natijasi dastur loyihasi hujjatini yaratishdir.
Loyiha hujjati ikki qismdan iborat: sinf loyihasi va dastur
arxitekturasi. Birinchi bo'lim, o'z navbatida, statik (turli sinflarning
tavsifi, ularning tuzilishi va xususiyatlari) va dinamik (sinflarning
o'zaro ta'sirining tavsifi) bo'limlarni o'z ichiga oladi.
Sinflarning dastlabki to'plami yaratilganda, ularning munosabatlari
va o'zaro munosabatlarini modellashtirishni boshlash vaqti keldi.
Aniqroq bo‘lish uchun avval statik modelni, so'ngra dinamik modelni
tushuntiramiz. Haqiqiy loyihalash jarayonida bir modeldan
ikkinchisiga erkin o'tish mumkin, ikkalasini ham tafsilotlar bilan
to‘ldirish, aslida yangi sinflarni qo'shish va ularni oldinga siljish bilan
tavsiflash mumkin.
Statik model uchta sohaga qaratilgan: javobgarlikni taqsimlash,
atributlar va o'zaro ta'sir. Ulardan eng muhimi sinflar o'rtasida
javobgarlikni taqsimlashdir. Har bir sinf oldida bitta aniq vazifa
qo'yilishi kerak, uning bajarilishi uchun u javobgardir.
Bu har bir sinfda faqat bitta metod mavjud degani emas. Sinf o'nlab
metodlarni o'z ichiga olishi mumkin. Biroq, ularning barchasi izchil va
o'zaro bog'liq bo‘lishi kerak, ya'ni.bitta vazifani bajarilishini ta'minlashi
kerak.
Xulosa qilib aytganda, to'liqroq loyiha modelini yaratish uchun
UMLga o'tish kerak.
Qanday qilib bir xil markadagi turli xil avtomobil modellarini
ishlab chiqarishni loyihalash mumkin? Aytaylik, sizni beshta avtomobil
ishlab chiqaradigan Acme Motors firmasi yollagan: Pluto (xarid qilish
uchun sayohat qilish uchun ixcham kichik avtomobil), Venera (o'rta
quvvatli dvigatelga ega to'rt eshikli "sedan"), Mars (eng kuchli
dvigatelga ega "kupe" tipidagi sport avtomobili, maksimal tezlikka
mo'ljallangan), Yupiter (mini furgon sport kupesi kabi majburiy
dvigatel bilan, ammo u kamroq tezlikda, ammo kuchliroq) va yer (kam
quvvatli, ammo tezkor furgon).

187
Ammo keling, modellar orasidagi farqlarni batafsilroq tahlil
qilaylik. Shubhasiz, ular dvigatel kuchi, tana turlari va ixtisosligi bilan
farq qiladi. Ushbu asosiy xususiyatlarni birlashtirib, biz turli xil
modellarning xususiyatlarini olamiz.
Shunday qilib, bizning misolimizda modellarning nomlariga emas,
balki ularning asosiy xususiyatlariga e'tibor qaratish muhimroqdir.
Bunday belgilar deb ataladi va UMLda maxsus tarzda
ko'rsatiladi.

15.10-rasm. Diskriminator munosabat modeli


15.10-rasm diagrammasi shuni ko'rsatadiki, turli xil modellar
sinflari dvigatel kuchi, tana turi va avtomobilning maqsadi kabi
diskriminatorlarni birlashtirib, avtomobil sinfidan ishlab chiqarilishi
mumkin.
Har bir diskriminator oddiy ro’yxat sifatida amalga oshirilishi
mumkin. Masalan, biz tana turlarining ro’yxatini e'lon qilamiz:
enum BodyType={sedan, coupe, minivan, stationwagon}
Biroq, har bir diskriminatorni shunchaki nomlash orqali e'lon qilish
mumkin emas.
Masalan, maqsad ko'plab parametrlar bilan belgilanadi. Bunday
holda, diskriminatorni sinf sifatida modellashtirish mumkin va
diskriminatorning har xil tiplari sinf obyektlari sifatida qaytadi.
Kuch sinflaridan foydalanish merosga murojaat qilmasdan turli xil
mantiqiy turlarni yaratishga imkon beradi. Shuning uchun dasturda har
bir yangi tur uchun sinf yaratmasdan, ko'plab turlarni osongina
boshqarish mumkin.
Odatda C++ dasturlarida kuch sinflaridan foydalanish
ko'rsatkichlar yordamida amalga oshiriladi. Shunday qilib, bizning

188
misolimizda Car sinfi (loyiha sinfiga mos keladigan mashina)
PerformanceCharacteristics sinf obyektiga ko'rsatgichni o'z ichiga oladi
(15.11-rasm).
Agar siz mashq qilmoqchi bo'lsangiz, diskriminatorlar uchun
o'zingizning kuch sinflaringizni yarating tana (tana) va dvigatel
(dvigatel).
Class Car : public Vehicle
public:
Car();
-Car();
// boshqa ochiq usullar chiqarib tashlandi
private:
PerformanceCharacteristics*pPerformance;
};

DINAMIK MODEL
Loyiha modelida nafaqat sinflar o'rtasidagi munosabatlarni, balki
ularning o'zaro ta'sir tamoyillarini ham ko'rsatish muhimdir. Masalan,
sinflar joriy hisob, ATM va kvitansiya sinf bilan o'zaro ta'sir qiladi
mijoz vaziyatda hisobdan chiqarish. Tahlil boshida ishlatilgan ketma-
ket diagrammalar turiga qaytish (15.10-rasm), endi 15.20-rasmda
ko'rsatilgandek, ular uchun belgilangan usullar asosida sinflarning
o'zaro ta'sirini ko'rib chiqing.

15.11-rasm. Diskriminator kuch sinfi sifatida

189
15.12-rasm. Sinf obyekti o'rtasidagi munosabatlar
Ushbu oddiy diagramma dasturdan foydalanishning ma'lum bir
holatida loyihaning bir nechta sinflari o'rtasidagi o'zaro ta'sirni
ko'rsatadi. U erdagi sinf sinfga topshirishi kerak joriy hisob hisobdagi
pul qoldig'ini hisobga olish uchun javobgarlik, joriy hisob esa ATM
sinfiga ushbu ma'lumotni foydalanuvchiga etkazish uchun
javobgarlikni beradi.
C++ obyektga yo'naltirilgan dasturlash tamoyillarini to'liq qo'llab-
quvvatlaydi: inkapsulyatsiya, meros va polimorfizm.

INKAPSULYATSIYA
Muhandis o'z rivojlanishida rezistordan foydalanganda, uni qayta
ixtiro qilmaydi, balki omborga boradi (do'konga, hamkasbiga -
variantlar mumkin) va belgilangan parametrlarga muvofiq o'zi uchun
kerakli qismni tanlaydi. Shu bilan birga, agar u zavod xususiyatlariga
muvofiq ishlasa, bu aniq rezistorning qanday ishlashi haqida unchalik
tashvishlanmaydi.
Aynan tashqi tuzilmalarda ishlatiladigan obyektlarning yashirinligi
yoki avtonomiyasining bu xususiyati inkapsulyatsiya deb ataladi.
Inkapsulyatsiya yordamida ma'lumotlarni yashirishni ta'minlash
mumkin. Bu juda muhim xususiyatdir, buning natijasida foydalanuvchi
ishlatilgan obyektning ichki ishi haqida o'ylamasligi mumkin.
Sovutgichdan foydalanish muzlatgichning ishlash tamoyillari
to'g'risida bilimlarni talab qilmagani kabi, yaxshi ishlab chiqilgan
dasturiy ta'minot obyektidan foydalanish uning ichki a'zo

190
o'zgaruvchilari o'rtasidagi munosabatlar haqida qayg'urmaslikka imkon
beradi.
C++ tilida inkapsulyatsiya xususiyati sinflar deb nomlangan
nostandart (maxsus) ma'lumotlar turlarini yaratish orqali qo'llab-
quvvatlanadi. Sinflar qanday yaratilganligi haqida siz 6-darsda bilib
olasiz. Yaratilgandan so'ng, yaxshi belgilangan sinf to'liq kapsulali
obyekt vazifasini bajaradi, ya'ni u butun dastur moduli sifatida
ishlatilishi mumkin. Sinfning haqiqiy ichki ishi yashirin bo‘lishi kerak.
Yaxshi belgilangan sinf foydalanuvchilari ushbu sinf qanday ishlashini
bilishlari shart emas; ular faqat bitta narsani bilishlari kerak - uni
qanday qilib yopishtirish kerak.
MEROS
C++ tili merosni qo'llab-quvvatlaydi. Bu shuni anglatadiki, mavjud
ma'lumotlarning kengaytmasi bo'lgan yangi ma'lumotlar turini (sinfini)
e'lon qilish mumkin. Ushbu yangi subklassa mavjud sinfdan meros
bo'lib o'tganligi va uning hosilasi deb nomlanganligi aytiladi.
POLIMORFIZM
C++ tili funksiyalar va sinflarning polimorfizmi deb ataladigan
narsa tufayli turli xil obyektlar uchun bir xil nomdagi funksiyalarni
bajarishda o'zgarishlar kiritish qobiliyatini qo'llab-quvvatlaydi. Poli
ko'p, morfe - rasm degan ma'noni anglatadi, shuning uchun
polimorfizm rasmlarning xilma-xilligini anglatadi.

Nazorat savollari va topshiriqlar:


1. Obyektga yo'naltirilgan va protsedurali dasturlash o'rtasidagi farq
nima?
2. Obyektga yo'naltirilgan tahlil va loyihalash bosqichlari qanday?
3. Aytaylik, ikki tomonlama transport, svetofor va piyodalar o'tish
joylari bilan kesishgan ikkita ko'cha bor. Svetofor chastotasining
o'zgarishi yo'l harakatini tahlil qilish uchun qanday obyektlar va qanday
sinflar kerak bo'ladi?
4. 3-mashqni murakkablashtiramiz. Aytaylik, haydovchilarning uch
turi bor: taksi haydovchilari qizil chiroqqa o'tish; sekin va ehtiyotkorlik
bilan harakatlanadigan norezidentlar, mashinalarni boshqacha
boshqaradigan xususiy shaxslar.
5. Shuningdek, piyodalarning ikki turi mavjud: o'zlari xohlagan
ko'chani kesib o'tadigan local aholi va ko'chani faqat yashil chiroq bilan
kesib o'tadigan sayyohlar.
191
6. Ushbu mulohazalar modelni qanday o'zgartiradi?
7. Sizga konferentsiya va uchrashuv vaqtini rejalashtirish dasturi,
shuningdek, kompaniya tashrif buyuruvchilari va konferentsiya
ishtirokchilari uchun mehmonxona joylarini bron qilish buyurilgan.
Asosiy quyi tizimlarni aniqlang.
8. 7-mashqda muhokama qilingan dasturning mehmonxona xonalarini
bron qilish bilan bog'liq qismining sinf interfeyslarini loyihalash.

192
16-MAVZU. SINFLAR VA OBYEKTLAR
 Sinflar va obyektlar
 Yangi sinfni aniqlash va ushbu sinf obyektlarini yaratish
 A'zo funksiyalari va a'zo o'zgaruvchilar
 Konstruktor va uni ishlatish

Asosiy sinflar C++ tilining o'rnatilgan vositalarini kengaytiradi, bu


esa haqiqiy hayot dasturchilar uchun qo'yadigan murakkab
muammolarni hal qilishga yordam beradi.
YANGI SINFLAR YARATISH
Siz allaqachon o'zgaruvchilarning turlari, shu gapdan ishorasiz
butunlar va belgilar bilan tanishgansiz. O'zgaruvchining turi juda ko'p
ma'lumotlarni o'z ichiga oladi. Masalan, Agar siz Height va Width
o'zgaruvchilarini ishorasizqisqa butun (unsigned short int) deb e'lon
qilsangiz, ularning har biri butun sonni 0-65 535 oralig'ida saqlashi
mumkin, shu bilan birga faqat ikkita baytni egallaydi. Agar siz bunday
o'zgaruvchiga ishorasizbutun sondan boshqa qiymat berishga harakat
qilsangiz, xato haqida xabar olasiz. Bu shuni anglatadiki, bunday
o'zgaruvchi yordamida siz ismingizni saqlay olmaysiz, shuning uchun
buni qilishga urinmang.
Faqat Height va Width o'zgaruvchilarini ishorasiz qisqa butun deb
e'lon qilish orqali siz ularni qo'shish yoki ulardan biriga boshqasiga
qiymat berish imkoniyatiga ega bo'lasiz.
Shunday qilib, o'zgaruvchining turi belgilaydi:
 uning hajmi xotirada;
 u saqlashi mumkin bo'lgan ma'lumotlar turi;
 uning ishtirokida amalga oshirilishi mumkin bo'lgan amallar.
Ma'lumotlar turi toifadir. Bunga mashina, uy, odam, meva,
geometrik rasm va boshqalar kiradi.C++ tilida dasturchi o'zi xohlagan
har qanday turni yaratishi mumkin va ushbu turlarning har biri
o'rnatilgan asosiy tiplarning xususiyatlari va funksiyalarini
birlashtirishi mumkin.
Dasturlar odatda xodimlar haqidagi ma'lumotlarni kuzatish yoki
isitish tizimining ishlashini tanqid qilish kabi haqiqiy muammolarni hal
qilish uchun yoziladi. Murakkab muammolarni faqat bitta butun
qiymatlari va belgilaridan foydalangan holda yozilgan dasturlar
yordamida hal qilish mumkin bo‘lsa, turli xil obyektlar uchun noyob

193
turlarni yaratish mumkin bo'lsa, yechimlar ancha sodda ko'rinadi. Bu
o'zgaruvchilar rostga qanchalik yaqin bo'lsa, bunday dasturni yozish
osonroq bo'ladi.
SINFLAR VA SINF A'ZOLARI
Sinfni e'lon qilish orqali yangi tur yaratiladi. Sinf shunchaki bog'liq
funksiyalar to'plami bilan birlashtirilgan o'zgaruvchilar to'plamidir (va
ko'pincha har xil tipdagi).
Avtomobilni turli yo'llar bilan tasavvur qilish mumkin, masalan,
g'ildiraklar, eshiklar, o'rindiqlar, derazalar va boshqalardan iborat
to'plam sifatida yoki mashina haqida o'ylab, siz uning harakatlanish,
tezlikni oshirish, tormozlash, to'xtash va hokazolarni tasavvur
qilishingiz mumkin bu obyekt deb ataladi. Avtomobil haqida biz bilgan
hamma narsani bitta sinfga kiritish dasturchi uchun bir qator
afzalliklarga ega. Axir, barcha ma'lumotlar bitta obyektda to'plangan,
unga murojaat qilish, nusxalash va uning ma'lumotlarini boshqarish
oson. Sizning sinfingiz mijozlari, ya'ni dasturning ushbu sinf bilan
ishlaydigan qismlari sizning obyektingizdan unda nima borligi yoki u
qanday ishlashi haqida tashvishlanmasdan foydalanishi mumkin.
Sinf o'zgaruvchan turlarning har qanday kombinatsiyasidan,
shuningdek boshqa sinflarning turlaridan iborat bo‘lishi mumkin.
Sinfdagi o'zgaruvchilar a'zo o'zgaruvchilar yoki berilgan a'zolar deb
ataladi.
A'zo ma'lumotlar sifatida ham tanilgan a'zo o'zgaruvchilar faqat o'z
sinfiga tegishli. A'zo o'zgaruvchilar sinfning g'ildiraklar va dvigatel
bilan bir xil tarkibiy qismlari - avtomobilning tarkibiy qismlari.
Sinfdagi funksiyalar odatda a'zo o'zgaruvchilar bo'yicha
harakatlarni bajaradi. Ular a'zo funksiyalar yoki sinf usullari deb
ataladi. Car sinfining usullari Start() va Break () ni o'z ichiga olishi
mumkin. Cat sinfida hayvonning yoshi va vaznini ifodalovchi bunday
a'zo ma'lumotlar bo‘lishi mumkin va bu sinfning funktsional qismi
Sleep (), Meow() va ChaseMice () usullari bilan ifodalanishi mumkin.
A'zo funksiyalari a'zo o'zgaruvchilar kabi o'z sinfiga tegishli. Ular
a'zo o'zgaruvchilar bilan ishlaydi va sinfning funktsional
imkoniyatlarini aniqlaydi.
SINF PROTOTIPI
Sinfni e'lon qilish uchun class kalit so'zidan foydalaning, so'ngra
ochiladigan figurali qavs va undan keyin sinf a'zolari ma'lumotlari va
usullari Listingi.
194
Prototip yopiq figurali qavs va nuqta-vergul bilan tugaydi. Bu
yerda, masalan, Cat class prototipi qanday ko'rinishga ega:
class Cat
unsigned int itsAge;
unsigned int itsWeight;
void Meow();
Cat sinfini e'lon qilishda xotira saqlanmaydi. Ushbu e'lon
shunchaki kompilyatorga Cat sinfining mavjudligi, unda qanday
ma'lumotlar borligi (itsAge va itsWeight) va nima qila olishi (meow ()
usuli) haqida xabar beradi. Bundan tashqari, ushbu prototip
kompilyatorga Cat sinfining kattaligi haqida xabar beradi, ya'ni.har bir
Cat sinf obyekti uchun kompilyator qancha joy ajratishi kerak. Ushbu
misolda butun qiymat to'rt baytni talab qilganligi sababli, Cat
obyektining hajmi sakkiz baytni tashkil qiladi (itsage o'zgaruvchisi
uchun to'rt bayt va itsweight uchun to'rt bayt). Meow () usuli obyektda
xotira ajratishni talab qilmaydi.
Dasturchiga o'zgaruvchan a'zolar, a'zo funksiyalar va sinflarga
nom berish vazifasi yuklatilgan. Har doim tushunarli va mazmunli
ismlar berilishi kerak. Masalan, mushuk (mushuk), to'rtburchaklar
(to'rtburchak) va xodimlar (xizmatchi) sinflar uchun juda mos nomlar,
A Meow() (meow), ChaseMice() (qo'lga olish) va StopEngine()
(to'xtash motori) usullar uchun ajoyib nomlardir chunki ularning
nomlaridan nima qilishlari aniq. Ko'pgina dasturchilar o'zlarining a'zo
o'zgaruvchilarining nomlarini its prefikslari bilan birga olib boradilar
(masalan, itsAge, itsWeight, itsSpeed). Bu a'zo o'zgaruvchilarni sinf
a'zosi bo'lmagan o'zgaruvchilardan ajratishga yordam beradi.
C++ tilida harflarning katta-kichikligi muhim va barcha sinf
nomlari bitta naqshga amal qilishi kerak. Shunga asoslanib, siz hech
qachon sinfingiz nomi qanday yozilganligini eslashingiz shart emas:
to'rtburchaklar, to'rtburchaklar yoki to'rtburchaklar. Ba'zi dasturchilar
har bir sinf nomiga bitta harfli prefiks qo'shishni yaxshi ko'radilar (sinf
so'zidan) masalan, cCat yoki cPerson, boshqalari esa ism uchun faqat
katta yoki kichik harflardan foydalanadilar. Men sinf nomlarini mushuk
yoki shaxs kabi katta harf bilan boshlashni afzal ko'raman.
Bundan tashqari, ko'plab dasturchilar funksiya nomlarini katta
harflar bilan boshlaydilar va boshqa barcha o'zgaruvchilar nomlari
uchun faqat kichik harflardan foydalanadilar. Ismlarning tarkibiy
qismlari bo'lgan so'zlar odatda pastki chiziq belgilari bilan bo'linadi

195
(masalan, Chase_Mice) yoki har bir so'zni katta harf bilan boshlaydi
(masalan, ChaseMice yoki DrawCircle).
Dastur davomida bitta uslubga rioya qilish muhimdir. Dasturlash
tajribasini orttirganingizda, o'zingizning yozish uslubingiz nafaqat
nomlash, balki to‘ldirish, figurali qavslarni tekislash va izohlarni tuzish
bo'yicha konventsiyalarni ham o'z ichiga oladi.
ESLATMA: Odatda dasturiy mahsulotlarni ishlab chiqaradigan
nufuzli kompaniyalar dasturlarning uslub xususiyatlarini qamrab
oladigan standartlashtirish masalalari bilan shug'ullanadigan maxsus
bo'limlarga ega. Bu barcha ishlab chiquvchilar hamkasblari tomonidan
yaratilgan dasturlarni osongina o'qishlarini ta'minlaydi.
OBYEKTNI ANIQLASH
Yangi turdagi obyekt har qanday butun o'zgaruvchisi bilan bir xil
tarzda aniqlanadi:
unsigned int GrossWeight;
Cat Frisky;
// Cat obyektini aniqlang
Ushbu dasturiy ta'minot satrlarida unsigned int tipiga ega bo'lgan
grossweight nomli o'zgaruvchi aniqlanadi va mushuk sinfining obyekti
(yoki turi) bo'lgan Frisky obyekti ham aniqlanadi.
OBYEKTLAR BILAN TAQQOSLAGANDA SINFLAR
Siz hech qachon mushuk bilan mavhum tushuncha sifatida
o'ynashni xayolingizga ham keltirmaysiz. Muayyan mavhumlik bo'lgan
Cat sinfi va Cat sinfining alohida obyekti o'rtasidagi farq aynan bir xil.
Shuning uchun Frisky - bu Grossweight - ishorasiz int tipidagi
o'zgaruvchi bo'lgan ma'noda mushuk tipidagi obyekt. Shunday qilib,
biz obyekt ma'lum bir sinfning alohida namunasi ekanligiga keldik.
SINF A'ZOLARIGA KIRISH
Frisky kabi Cat sinfining haqiqiy obyektini aniqlagandan so'ng, biz
ushbu obyekt a'zolariga kirish huquqiga ega bo‘lishimiz kerak bo‘lishi
mumkin. Buning uchun to'g'ridan-to'g'ri kirish operatori ishlatiladi (.).
Shuning uchun, Frisky obyektining weight a'zo o'zgaruvchisiga 50
sonini berish uchun siz yozishingiz mumkin
Frisky. Weight = 50;
Xuddi shunday, meow () usulini chaqirish uchun quyidagi
yozuvdan foydalanish kifoya:
Frisky. Meow();

196
Ba'zi bir sinf usulidan foydalanish kerak bo'lganda, ushbu usul
chaqiriladi. Ushbu misolda Frisky obyektining Meow () usuli
chaqiriladi.
QIYMATLAR SINFLARGA EMAS, BALKI
OBYEKTLARGA BERILADI
C++ tilida ma'lumotlar turlariga qiymatlarni o‘zlashtirish mumkin
emas, ular faqat o'zgaruvchilarga beriladi. Masalan, bunday yozuv
noto'g'ri:
int = 5; // noto'g'ri
Kompilyator buni xato deb hisoblaydi, chunki siz int tipiga son
berolmaysiz. Buning o'rniga siz butun sonli o'zgaruvchini aniqlab,
ushbu o'zgaruvchiga 5 sonini o‘zlashtirishingiz kerak. Masalan:
int x; // x ni int tipidagi o'zgaruvchi sifatida aniqlang
x = 5; //x o'zgaruvchiga 5 qiymatini berish
Shunday qilib, 5 soni int tipiga ega bo'lgan x o'zgaruvchiga
beriladi. Xuddi shu sabablarga ko'ra quyidagi yozuv qabul qilinishi
mumkin emas:
Cat.itsAge=5; / / noto'g'ri
Agar Cat obyekt emas, balki sinf bo'lsa, kompilyator bu ifodani
noto'g'ri deb belgilaydi, chunki Cat sinfining (ya'ni turi) itsage
o'zgaruvchisiga 5 sonini o‘zlashtirish mumkin emas. Buning o'rniga,
Cat sinfining obyektini aniqlash va ushbu obyektning tegishli a'zo
o'zgaruvchisiga 5 sonini berish kerak. Masalan:
Cat Frisky; // ushbu ta'rif int x ga o'xshaydi;
Frisky.itsAge = 5; / / ushbu topshiriq = 5 ga o'xshash;
Tasavvur qiling-a, siz uch yoshli bolangiz bilan yurib, unga
mushukni ko'rsatasiz va "bu Frisky, ajoyib mushuk, Frisky, hura"deb
aytasiz. Hatto kichkina bola ham kulib: "yo'q, Mushuklar hurishni
bilmaydi", deb aytadi.
Agar yozsangiz:
Cat Frisky;// Frisky ismli mushukni (obyektni) yarating
Frisky. Bark();// Friskiga baqirishni ayting.
Keyin kompilyator sizga hatto virtual Mushuklar ham
hurishni bilmasligini aytadi, chunki ular uchun bunday usul e'lon
qilinmagan.
Cat sinfida meow() (miyovlash) usuli mavjud. Agar siz mushuk
sinfida Meow () usulini aniqlamasangiz, unda kompilyator sizning
mushukingizni hatto miyovlashiga yo'l qo'ymaydi.
197
Tavsiya etiladi!
 Sinfni e'lon qilish uchun class kalit so'zidan foydalaning.
 To'g'ridan-to'g'ri kirish operatoridan foydalaning (.) a'zo
o'zgaruvchilar va sinf usullariga kirish uchun.
Tavsiya etilmaydi!
 Prototipni ta'rif bilan aralashtirmang.
 Prototip sinf mavjudligini e'lon qiladi va ta'rif obyekt uchun
xotirani saqlaydi.
 Sinfni obyekt bilan aralashtirmang.
 Sinfga qiymatlarni tayinlamang. Obyektning a'zo
o'zgaruvchilariga qiymatlarni belgilang.
SINF A'ZOLARIGA KIRISHNI CHEKLASH
Sinf prototipida boshqa kalit so'zlar ham qo'llaniladi. Ulardan eng
muhimi, sinf a'zolariga kirishni belgilaydigan public (ochiq) va private
(yopiq).
Sinfning barcha a'zolari-ma'lumotlar va usullar sukut bo'yicha
yopiq.Yopiq a'zolarga faqat sinfning o'zi funksiyalari orqali kirish
mumkin.
Ochiq a'zolar dasturning boshqa barcha funksiyalari uchun mavjud.
Sinf a'zolariga kirishni aniqlash juda muhimdir va aynan shu
muammoni hal qilishda boshlang'ich dasturchilar ko'pincha
qiyinchiliklarga duch kelishadi. Vaziyatni aniqlashtirish uchun ushbu
bobda quyida keltirilgan misolni ko'rib chiqing:
class Cat
{
unsigned int itsAge;
unsigned int itsWeight;
void Meow();
};
Ushbu e'londa itsAge va itsWeight o'zgaruvchilari, shuningdek
Meow() funksiyasi yopiq, chunki sinfning barcha a'zolari sukut
bo'yicha private. Agar sinf a'zolariga kirishni o'zgartirish zarur bo'lsa,
unda bu aniq bajarilishi kerak.
Agar dastur yuqorida ko'rsatilgandek Cat sinfini tavsiflasa, u holda
main () funksiyasidan itsage a'zo o'zgaruvchisiga murojaat qilish
kompilyatsiya xatosiga olib keladi:
Cat Boots;
Boots.itsAge = 5; / / xato!

198
Shuningdek, ishning o'zida, birinchi navbatda, kompilyator itsage,
itsweight va Meow () atamalarini faqat Cat sinfida ishlatish
mumkinligini ko'rsatadi, keyin tashqi funksiyada Cat sinfining Boots
obyektiga tegishli bo'lgan itsage a'zosi o'zgaruvchisidan foydalanishga
harakat qilinadi. Boots obyekti dasturda rostan ham mavjud bo‘lsada,
bu qiziquvchan ko'z uchun yopiq bo'lgan ushbu obyekt a'zolariga kirish
mumkin degani emas.
Gap shundaki, Cat sinfining e'lonida sizning ushbu sinf a'zolariga
murojaat qilish huquqlaringiz haqida hech narsa aytilmagan, ya'ni sizda
bunday huquqlar yo'q. Faqat Boots obyektining o'ziga xos funksiyalari
har doim public va private bo'lgan barcha sinf ma'lumotlariga kirish
huquqiga ega. Siz o'zingiz Cat sinfini yaratgan bo'lsangiz ham, bu sizga
dasturda yopiq bo'lgan ma'lumotlarni qaytarish yoki o'zgartirish
huquqini bermaydi.
Biroq, har qanday pozitsiyadan chiqarish yo'li mavjud. Cat
sinfidagi o'zgaruvchilarga kirish uchun ularni quyidagi tarzda oching:
class Cat
public:
unsigned int itsAge;
unsigned int itsWeight;
void Meow();
Endi Public kalit so'zi tufayli sinfning barcha a'zolari (itsAge,
itsWeight va Meow()) ochiq. 16.1 Listingida ochiq o'zgaruvchan a'zolar
bilan Cat sinfining prototipi ko'rsatilgan.
Listing 16.1. Oddiy classning ochiq a'zosiga kirish
#include <iostream>
using namespace std;
class Cat / / sinfni e'lon qilish
{
public: / / quyidagi a'zolar ochiq
int itsAge;
int itsWeight;
};
int main()
{
Cat Frisky;
Frisky.itsAge =5;
cout << "Frisky is a cat who is ";
cout << Frisky.itsAge << " years old.\n";
return 0;
}
Natija:
Frisky is a cat who is 5 years old.

199
Tahlil:
3-qatorda class kalit so'zi mavjud. Bu kompilyatorga keyingi blok
sinf prototipi ekanligini aytadi. Yangi sinf nomi class kalit so'zidan
keyin darhol keladi. Bunday holda, biz Cat sinfini e'lon qilamiz.
Sinf prototipining tanasi 4-qatorda ochiladigan figurali qavs bilan
boshlanadi va 8-qatorda yopiq figurali qavs va nuqta-vergul bilan
tugaydi. 5-qatorda public kalit so'z mavjud bo'lib, u xususiy kalit so'z
yoki sinf e'lonining oxiriga qadar barcha keyingi a'zolar ochiq deb e'lon
qilinishini anglatadi.
6 va 7-qatorlar itsAge va itsWeight a'zo o'zgaruvchilarini e'lon
qiladi.
9-qatorda dasturning main () funksiyasi boshlanadi. Frisky 11-
qatorda Cat sinfining misoli, ya'ni Cat sinfining obyekti sifatida
aniqlanadi. 12-qatorda Frisky obyektining itsAge maydoniga 5
o'rnatiladi. 13 va 14-qatorlarda ma'lumotlarni ekranga chiqarish uchun
itsAge a'zosi o'zgaruvchisi ishlatiladi.
SINF MA'LUMOTLARINING PRIVATE HOLATI
Sinflardan foydalanishning umumiy strategiyasiga ko'ra, sinf
a'zolari o'zgaruvchilari yopiq holda qoldirilishi kerak. Buning
yordamida sinf ichidagi ma'lumotlarni inkapsulyatsiya qilishga
erishiladi. Kirish faqat sinfning yopiq ma'lumotlariga kirishni
ta'minlaydigan a'zo funksiyalariga ochilishi kerak (bu funksiyalar kirish
usullari deb ham ataladi). Ushbu usullarni dasturning istalgan joyidan
yopiq a'zo o'zgaruvchilarning qiymatlarini qaytarish yoki o'rnatish
uchun chaqirish mumkin.
Nima uchun dasturda yopiq sinf a'zolari va dasturning qolgan qismi
o'rtasida bunday vositalar ishlatiladi? Kirish usullari bilan ishlash
o'rniga, sinf ma'lumotlarini tashqi kirish uchun ochish osonroq emasmi?
Kirish usullaridan foydalanish obyektlarda ma'lumotlarni saqlash
tafsilotlarini foydalanuvchidan yashirishga imkon beradi, shu bilan
birga ularni ushbu ma'lumotlardan foydalanish usullari bilan
ta'minlaydi. Natijada, tashqi dastur kodida kirish usullari va
murojaatlarini qayta yozmasdan, sinf ichidagi ma'lumotlarni saqlash va
qayta ishlash usullarini yangilash mumkin.
Agar Cat obyektining yoshini qaytaradigan dasturdagi ba'zi bir
tashqi funksiyalar uchun itsage o'zgaruvchisiga to'g'ridan-to'g'ri
kirishni ochsangiz, Cat sinf muallifi ushbu ma'lumot komponentini
saqlash usulini o'zgartirishga qaror qilsa, ushbu funksiyani qayta yozish
200
kerak bo'ladi. Ammo, agar tashqi funksiya va sinf ma'lumotlari o'rtasida
getage () a'zo funksiyasi bo'lsa, u holda Cat sinfi xohlagancha
yangilanishi mumkin, bu dasturning asosiy kodidagi GetAge()
funksiyasini chaqirish usuliga ta'sir qilmaydi. Dasturga kirish usulini
chaqirganda, kerakli qiymat unsigned integer yoki long turidagi
o'zgaruvchida saqlanganligini yoki so'ralganda hisoblanganligini
bilishingiz shart emas.
Ushbu yondashuv sizning dasturingizdan foydalanishni va
kelajakda uni qo'llab-quvvatlashni osonlashtiradi. Aytishimiz
mumkinki, bu dasturning umrini uzaytiradi, chunki sinflarni o'zgartirish
orqali siz asosiy kodga ta'sir qilmasdan dasturning bajarilishini sezilarli
darajada modernizatsiya qilishingiz mumkin.
16.2 Listingida bu safar yopiq a'zo o'zgaruvchilar va yopiq
ma'lumotlarga kirishning ochiq usullari e'lon qilingan Cat sinfi
ko'rsatilgan.
Listing 16.2. Sinf ma'lumotlariga kirish usullarini e'lon qilish
class Cat
{
public:
unsigned int GetAge():
void SetAge(unsigned int Age);
unsigned int GetWeight();
void SetWeight(unsigned int Weight);
void Meow();
private:
unsigned int itsAge;
unsigned int itsWeight;
};
Ushbu sinfda beshta public funksiyasi mavjud.
Frisky mushukining yoshini aniqlash uchun tegishli qiymatni
setAge() usuliga o'tkazish kerak:
Cat Frisky;
Frisky. SetAge (5); / / Frisky yoshini ochiq kirish usuli bilan
o'rnating
Usullar yoki ma'lumotlarni yopiq deb e'lon qilish kompilyatorga
dasturlash xatolarini oldindan topishga imkon beradi. Ajam dasturchilar
ko'pincha ma'lumotlarni yopiq deb e'lon qilish va shu bilan tegishli
kirish huquqiga ega bo'lmagan foydalanuvchilardan ba'zi maxfiy
ma'lumotlarni yashirish deb noto'g'ri ishonishadi. Aslida, bunday emas.

201
Shu munosabat bilan C++ tilining ixtirochisi Straustrap (Stroustrup)
shunday dedi: "C++ ga kirishni boshqarish mexanizmlari baxtsiz
hodisalardan himoya qiladi, ammo firibgarlardan emas" (ARM, 1990).
Tavsiya etiladi!
 Sinfning a'zo o'zgaruvchilarini yopiq deb e'lon qiling (private kalit
so'z bilan).
 Yopiq sinf a'zolari ma'lumotlariga kirish usullarini ochiq deb e'lon
qiling.
 A'zo ma'lumotlarini qayta ishlash uchun yopiq sinf a'zo
funksiyalaridan foydalaning.
Tavsiya etilmaydi!
 Sinfdan tashqarida yopiq a'zo o'zgaruvchilardan
foydalanishga urinmang.
CLASS KALIT SO'ZI
Class kalit so'zi quyidagi sintaksisga ega:
sinf nomi
// bu yerda kirishni boshqarish kalit so'zlari mavjud
Class kalit so'zi yangi turlarni e'lon qilish uchun ishlatiladi. Sinf-
bu har xil tipdagi o'zgaruvchilar, shu gapdan boshqa sinflar bo'lgan
sinfga a'zo ma'lumotlar to'plami. Sinf shuningdek, sinf funksiyalari
yoki sinf ma'lumotlari bo'yicha harakatlarni amalga oshirish uchun
ishlatiladigan usullarni, shuningdek sinf ichidagi boshqa xizmat
turlarini o'z ichiga oladi;
Yangi turdagi obyektlarni aniqlash har qanday o'zgaruvchini
aniqlashga o'xshaydi. Avval turi (sinf), so'ngra o'zgaruvchining nomi
(obyekt) ko'rsatiladi. Sinf a'zolariga (ma'lumotlar va funksiyalar)
murojaat qilish uchun nuqta operatori (.)ga murojaat qiling.
Sinfning ochiq yoki yopiq bo'limlarini e'lon qilish uchun public
yoki private kirishni boshqarish kalit so'zlari ishlatiladi. Har bir kalit
so'z kirishni boshqarish rejimini ushbu asosiy spovdan foydalangan
paytdan boshlab sinf e'lonining oxirigacha yoki keyingi kirishni
boshqarish kalit so'zi paydo bo'lguncha o'zgartiradi. Barcha sinf
prototiplari yopiq figurali qavs va nuqta-vergul bilan tugaydi.
1-misol:
class Cat
{
public:
unsigned int Age;
unsigned int Weight:

202
void Meow();
};
Cat Frisky;
Frisky. Age = 8;
Frisky Weight = 18:
Frisky. Meow();
SINF METODLARINI (USUL, FUNKSIYA) ANIQLASH
Yuqorida aytib o'tilganidek, kirish usullari yopiq sinf a'zolari
o'zgaruvchilari bilan ishlash uchun interfeysni ta'minlaydi. Kirish
usullari uchun, boshqa barcha e'lon qilingan sinf usullari kabi,
bajarilishini aniqlash kerak. Shunday qilib, usullar sinfda e'lon qilinadi
va aniqlanadi.
A'zo funksiyasining ta'rifi sinf nomi bilan boshlanadi, so'ngra
ikkita nuqta, funksiya nomi va uning parametrlari. 16.3 Listingi oddiy
Cat sinfining e'lonini ko'rsatadi, unda ilgari e'lon qilingan
ma'lumotlarga kirish usullari va bitta oddiy a'zo funksiyasining ta'riflari
mavjud.
Listing 16.3. Oddiy sinf usullarini aniqlash
1 #include <iostream>
2 using namespace std;
3 class Cat// sinf e'lonini boshlash
4{
5 public:// Public bo'limining boshlanishi
6 int GetAge;// kirish usuli
7 void SetAge (int age); / / kirish usuli
8 void Meow();// oddiy usul
9 private:// xususiy bo'limning boshlanishi
10 int itsAge; // atama o'zgaruvchisi
11 };
12 int Cat::GetAge()
13 {
14 return itsAge;
15 }
16 void Cat::SetAge(int age)
17 {
18 itsAge = age;
19 }
20 void Cat::Meow()
21 {
22 cout << "Meow.\n";
23 }
24 int main()
25 {
26 Cat Frisky;
27 Frisky. SetAge(5);
28 Frisky. Meow();

203
29 cout << "Frisky is a cat who is "
30 cout << Frisky.QetAge() << " years old.\n";
31 Frisky. Meow();
32 return 0;
33 }
Natija:
Meow.
Frisky is a cat who is 5 years old.
Meow.
Tahlil:
3-11 qatorlar Cat sinfining ta'rifini o'z ichiga oladi. 5-qatorni Public
kalit so'zi mavjud, bu kompilyatorga undan keyin sinfning ochiq
a'zolari to'plami kelishini aytadi. 6-qatorda 10-qatorda e'lon qilingan
private itsAge a'zo o'zgaruvchisiga kirishni ta'minlaydigan GetAge ()
public usul prototipi mavjud. 7-qatorda public SetAge() kirish
funksiyasi e'lon qilinadi, u argument sifatida butun sonni oladi va
itsAge o'zgaruvchisiga ushbu argumentning qiymatini beradi.
8-qatorda Meow () usuli e'lon qilinadi. Ushbu usul Meow so'zini
ekranga chiqarish uchun ishlatiladigan sinf a'zosi ma'lumotlariga kirish
funksiyasi emas.
9-qatorda private bo'lim boshlanadi, unda faqat bitta private itsAge
a'zo o'zgaruvchisi prototipi (10-qator) mavjud. Sinf prototipi 11-
qatorda yopiq figurali qavs va nuqta-vergul bilan tugaydi.
12-15 qatorlar GetAge () a'zo funksiyasining ta'rifini o'z ichiga
oladi. Ushbu usul hech qanday parametrlarni qabul qilmaydi va butun
qiymatni qaytaradi.
E'tibor bering, sinf usullarini aniqlashda sinf nomi, so'ngra ikkita
ikki nuqta va funksiya nomi ishlatiladi. Ushbu sintaksis tufayli
kompilyator bu yerda aniqlangan GetAge () funksiyasi Cat sinfida e'lon
qilingan funksiya ekanligini bilib oladi. Sarlavha satridan tashqari,
GetAge() boshqa funksiyalar bilan bir xil tarzda yaratilgan.
GetAge () funksiyasining ta'rifi faqat bitta qatorni oladi, bu
funksiya itsAge a'zosi o'zgaruvchisining qiymatini qaytarishini
bildiradi. E'tibor bering, main() funksiyasi ushbu o'zgaruvchiga kira
olmaydi, chunki u Cat sinfining yopiq qismida e'lon qilingan. Bunday
holda, main() funksiyasidan ochiq GetAge () usuliga murojaat
qilishingiz mumkin. GetAge () usuli Cat sinfining a'zo funksiyasi
bo'lganligi sababli, u itsage a'zo o'zgaruvchisiga barcha kirish

204
huquqlariga ega. Natijada GetAge () funksiyasi itsage
o'zgaruvchisining qiymatini main() funksiyasiga qaytaradi.
16-qatorda SetAge () a'zo funksiyasining ta'rifi boshlanadi. U
butun sonli parametrni oladi va itsAge o'zgaruvchisiga ushbu
parametrning qiymatini beradi (27-qator). Cat sinfining a'zosi sifatida
SetAge() funksiyasi itsAge a'zo o'zgaruvchisiga to'g'ridan-to'g'ri kirish
huquqiga ega.
KONSTRUKTORLAR VA DESTRUKTORLAR
Butun o'zgaruvchisini aniqlashning ikkita usuli mavjud.
Birinchidan, o'zgaruvchini aniqlash mumkin, so'ngra (dasturda biroz
pastroq) unga ba'zi qiymatlarni berish mumkin, masalan:
int Weight; // o'zgaruvchini aniqlang
…. // bu yerda boshqa ifodalar keladi
Weight=7; // o'zgaruvchiga qiymat bering
O'zgaruvchini aniqlash va uni darhol ishga tushirish ham mumkin,
masalan:
int Weight=7;
Ishga tushirish jarayoni o'zgaruvchining ta'rifini boshlang'ich
qiymatni o‘zlashtirish bilan birlashtiradi. Bundan tashqari, keyinchalik
bu qiymatni o'zgartirishga hech narsa to'sqinlik qila olmaydi. Bundan
tashqari, ta'rif bilan bir vaqtda amalga oshirilgan initsializatsiya
o'zgaruvchining ajratilgan o'zgaruvchan xotira katakchalarida qolgan
qoldiqlarni o'z ichiga olmaydi.
Sinf a'zolari o'zgaruvchilarini qanday boshlash kerak? Buning
uchun sinf deb nomlangan maxsus a'zo funksiyasidan
foydalanadi. Agar kerak bo'lsa, konstruktor parametrlarni qabul qilishi
mumkin, lekin hatto void turidagi qiymatlarni ham qaytara olmaydi.
Konstruktor-bu sinfning o'zi bilan bir xil nomga ega bo'lgan sinf usuli.
Konstruktorni e'lon qilgandan so'ng, siz destruktorni ham e'lon
qilishingiz kerak. Agar konstruktorlar sinf obyektlarini yaratish va
ishga tushirish uchun xizmat qilsa, destruktorlar ishlatilgan obyektlarni
xotiradan olib tashlaydi va ular uchun ajratilgan xotirani bo'shatadi.
Destruktorga har doim boshida tilda (") belgisi bo'lgan sinf nomi
beriladi. Destruktorlar hech qanday dalillarni qabul qilmaydi va hech
qanday qiymatni qaytarmaydi. Cat class prototipi
quyidagicha ko'rinadi:
Cat();

205
Agar siz konstruktor yoki destruktorni e'lon qilmasangiz,
kompilyator buni siz uchun qiladi. Standart konstruktor va destruktor
argumentlarni qabul qilmaydi yoki hech qanday harakat qilmaydi.
Hech narsa vazifa bajarmaydigan loyihalashdan nima foyda?
Ko'pincha bu faqat protokol uchun kerak. Barcha obyektlar dasturda
lokalizatsiya qilinishi kerak, shuning uchun ularni yaratish va o'chirish
tegishli funksiyani chaqirish bilan birga keladi, bu esa hech narsa qila
olmaydi. Shunday qilib, parametrlarni uzatmasdan obyektni e'lon qilish
uchun, masalan
Cat Rags; / / Rags hech qanday parametr olmaydi
quyidagi konstruktorga ega bo‘lishingiz kerak:
Cat();
Konstruktor sinf obyektini aniqlashda chaqiriladi. Agar Cat
sinfining obyektini yaratish uchun ikkita parametr o'tkazilishi kerak
bo'lsa, u holda Cat sinfining konstruktori quyidagicha aniqlanadi:
Cat Frisky (5,7);
Agar konstruktor bitta parametrni qabul qilsa, obyekt ta'rifi
quyidagicha bo'ladi:
Cat Frisky (3);
Agar konstruktor parametrlarni umuman qabul qilmasa (ya'ni
standart bo'lsa), qavslardan foydalanishga hojat qolmaydi:
Cat Frisky;
Ushbu holat barcha funksiyalar parametrlarni umuman qabul
qilmasa ham, qavs kerak degan qoidadan istisno hisoblanadi. Shuning
uchun siz ushbu ta'rifni xavfsiz yozishingiz mumkin:
Cat Frisky;
Ushbu yozuv standart konstruktorga murojaat sifatida talqin
etiladi. Unda parametrlarning uzatilishi va natijada qavslar mavjud
emas.
Shuni esda tutingki, siz kompilyator tomonidan taqdim etilgan
standart konstruktordan o‘zgarmas ravishda foydalanishingiz shart
emas. Siz har doim o'zingizning standart konstruktoringizni yozishingiz
mumkin, ya'ni.parametrlarsiz konstruktor. Siz o'zingizning standart
konstruktoringizga sinfni boshlash amalga oshiriladigan funksiya
tanasini berishingiz mumkin.
16.4 Listingida siz allaqachon tanish bo'lgan Cat sinfiga
konstruktor va destruktor qo'shildi. Konstruktor Cat obyektini ishga
tushirish va uning yoshini siz taqdim etgan qiymatga tenglashtirish
206
uchun ishlatiladi. Dasturning qaysi joyida destruktor chaqirilganiga
e'tibor bering.
Listing 16.4. Konstruktorlar va destruktorlardan foydalanish
1 #include <iostream>
2 using namespace std;
3 class Cat// sinf e'lonini boshlash
4{
5 public: // ochiq bo'limning boshlanishi
6 Cat(int initialAge); // konstruktor
7 "Cat(); / buzuvchi
8 int GetAge();// kirish usuli
9 void SetAge(int age); //kirish usuli
10 void Meow();
11 private: // yopiq bo'limning boshlanishi
12 int itsAge; // atama o'zgaruvchisi
13 };
14 Cat::Cat(int initialAge)
15 {
16 itsAge = initialAge;
17 }
18 Cat::"Cat() / harakatlarni bajarmaydigan destruktor
19 {}
20 int Cat::GetAge()
21 {return itsAge;}
22 void Cat::SetAge(int age)
23 { itsAge = age; }
24 void Cat::Meow()
25 { cout << "Meow.\n";}
26 int main()
27 {
28 Cat Frisky(5);
29 Frisky. Meow();
30 cout << "Frisky is a cat who is "
31 cout << Frisky.QetAge() << " years old.\n";
32 Frisky. Meow();
33 Frisky. SetAge(7);
34 cout << "Now Frisky is " ;
35 cout << Frisky.GetAge() << " years old.\n";
36 return 0;
37 }
Natija:
Meow.
Frisky is a cat who is 5 years old.

207
Meow.
Now Frisky is 7 years old.
Tahlil:
16.4 Listingi 16.3 Listingiga o'xshaydi, faqat 9-qatorga parametr
sifatida butun son qiymatini oladigan konstruktor qo'shiladi. 10-qatorda
hech qanday parametrlarni qabul qilmaydigan destruktor e'lon qilinadi.
Esingizda bo'lsin, destruktorlar hech qachon parametrlarni qabul
qilmaydi; bundan tashqari, na konstruktorlar, na destruktorlar hech
qanday qiymatni, hatto void tipidagi qiymatni ham qaytarmaydi.
19-22-qatorlarda setage () kirish funksiyasiga o'xshash
konstruktorning bajarilishi aniqlanadi, bu ham hech qanday qiymatni
qaytarmaydi.
24-26-qatorlarda "Cat ()" destruktori aniqlanadi. Ushbu funksiya
hech qanday harakatni amalga oshirmaydi, lekin agar siz uni sinfda
e'lon qilsangiz, uning ta'rifini ham kiritishingiz kerak.
Tavsiya etiladi!
 Obyektlarni ishga tushirish uchun konstruktorlardan
foydalaning.
C++ tilida sinf usulini shunday e'lon qilish imkoniyati mavjudki,
bunday usulga sinf a'zolari o'zgaruvchilarining qiymatlarini o'zgartirish
taqiqlanadi. Buning uchun funksiya prototipida qavslardan keyin, lekin
nuqta-verguldan oldin const kalit so'zi ishlatiladi. Masalan,
argumentlarni qabul qilmaydigan va void tipidagi qiymatni
qaytaradigan SomeFunction () a'zosi funksiyasini shu tarzda e'lon
qilamiz:
void SomeFunction() const;
Ma'lumotlarga kirish funksiyalari ko'pincha const spetsifikatori
bilan e'lon qilinadi. Cat sinfida ikkita kirish funksiyasi mavjud:
void SetAge(int anAge);
int GetAge();
Setage () funksiyasini const spetsifikatori bilan e'lon qilish mumkin
emas, chunki u itsage a'zosi o'zgaruvchisining qiymatini o'zgartiradi.
Va GetAge () funksiyasini e'lon qilishda const spetsifikatoridan
foydalanish mumkin va hatto kerak, chunki u sinfda hech narsani
o'zgartirmasligi kerak. GetAge () funksiyasi shunchaki itsage a'zosi
o'zgaruvchisining joriy qiymatini qaytaradi. Shuning uchun ushbu
funksiyalarning prototipi ushbu rasmda yozilishi kerak:
void SetAge(int anAge);
208
int GetAge() const;
Agar biror bir funksiya const spetsifikatori yordamida e'lon
qilingan bo'lsa va uning bajarilishida obyektning biror bir a'zosi
o'zgarsa, kompilyator xato xabarini ko'rsatadi. Masalan, Agar siz
GetAge() funksiyasini Cat obyektining yoshi necha marta
so'ralganligini hisoblaydigan tarzda yozsangiz, kompilyatsiya xatosi
albatta hosil bo'ladi, chunki bunday hisoblash bilan (ya'ni GetAge ()
funksiyasini chaqirganda) Cat obyekti o'zgaradi.
ESLATMA:Agar obyektni o'zgartirmasa, a'zo funksiyalari
prototiplarida const spetsifikatoridan foydalaning. Bu kompilyatorga
xatolarni yaxshiroq kuzatish imkonini beradi va dasturni disk
raskadrovka qilishda sizga yordam beradi.
Obyektni o'zgartirmaydigan usul prototiplarida const-dan
foydalanish yaxshi dasturlash uslubi hisoblanadi. Bu kompilyatorga
dasturni ishga tushirishdan oldin xatolarni yaxshiroq kuzatish imkonini
beradi.
Yuqorida aytib o'tilganidek, mijozlar sizning sinfingiz obyektlarini
yaratadigan va ulardan foydalanadigan dasturning tarkibiy qismidir.
Ochiq sinf interfeysi (sinf prototipi) ushbu mijozlar bilan shartnoma
sifatida tasavvur qilinishi mumkin, bu mijozlarning sinf bilan o'zaro
munosabatlari usullarini ko'rsatadi.
Masalan, Cat sinfining e'lonida mijoz dasturi setage() kirish
funksiyasidan foydalangan holda ushbu sinf obyektining har qanday
yoshini boshlashi va GetAge () kirish funksiyasidan foydalanib ushbu
qiymatni qaytarishi mumkinligi ko'rsatilgan. Shu bilan birga, har bir
Cat sinfidagi obyekt meow () a'zo funksiyasidan foydalangan holda
meow xabarini ekranga chiqarishi kafolatlanadi. E'tibor bering, ochiq
sinf interfeysida sinfni bajarishda ishlatiladigan va mijozlarni
qiziqtirmasligi kerak bo'lgan yopiq itsage a'zo o'zgaruvchisi haqida
hech narsa aytilmagan. Yosh qiymati GetAge() yordamida obyektdan
qaytarilishi va SetAge () yordamida o'rnatilishi mumkin, ammo bu
qiymat saqlanadigan itsage
C++ tilida ma'lumotlar turlarini qat'iy nazorat qilish amalga
oshiriladi, shuning uchun sinf va mijozlar o'rtasidagi bunday kelishuv
kompilyator uchun qonun bo'lib, ushbu shartnoma buzilgan taqdirda
kompilyatsiya xatosini keltirib chiqaradi. Listing 16.5 ushbu
kelishuvlarni buzganligi sababli kompilyatsiya qilinmaydigan
dasturning namunasini ko'rsatadi.
209
ESLATMA: Listing 16.5 kompilyatsiya qilinmaydi!
Listing 16.5. Interfey kelishuvlarini buzish misoli
1 #include <iostream>
2 using namespace std;
3 class Cat
4{
5 public:
6 Cat(int initialAge);
7 Cat();
8 int GetAge() const;
9 void SetAge (int age);
10 void Meow();
11 private:
12 int itsAge;
13 };
14 Cat::Cat(int initialAge)
15 {
16 itsAge = initialAge;
17 cout << "Cat constructor\n";
18 }
19 Cat:: Cat ()
20 {
21 cout << "Cat destructor\n";
22 }
23 int Cat::GetAge() const
24 {
25 return (itsAge++);
26 }
27 void Cat::SetAge(int age)
28 {
29 ItsAge = age;
30 }
31 void Cat::Meow()
32 {
33 cout << "Meow.\n";
34 }
35 int main()
36 {
37 mushuk Frisky;
38 Frisky. Meow();
39 Frisky.Bark ();
40 Frisky.itsAge = 7;
41 return 0;
42 }
Tahlil:
Yuqorida aytib o'tilganidek, ushbu dastur kompilyatsiya
qilinmaydi. Shuning uchun uning ishining natijalari yo'q.

210
Ushbu dasturni yozish juda qiziqarli edi, chunki unda xatolar
maxsus joylashtirilgan edi.
8-qatorda GetAge () const spetsifikatori ko'rsatganidek, ularni
o'zgartirish huquqisiz sinf a'zolari ma'lumotlariga kirish funksiyasi
sifatida e'lon qilinadi. Biroq, GetAge () funksiyasining tanasida, ya'ni
29-qatorda, itsAge a'zosi o'zgaruvchisi ko'payadi, bu usul const deb
e'lon qilinganligi sababli, itsAge o'zgaruvchisining qiymatini
o'zgartirish huquqiga ega emas. Shuning uchun, dasturni kompilyatsiya
qilish paytida ushbu satrda xato qayd etiladi.
10-qatorda Meow () usuli e'lon qilinadi, bu safar const kalit
so'zidan foydalanmasdan, bunday kamchilik xato bo'lmasa-da, bu eng
yaxshi dasturlash uslubidan uzoqdir. Agar ushbu usul Cat sinfining a'zo
o'zgaruvchilarining qiymatlarini nomlamasligi kerak deb hisoblasak, u
const spetsifikatori bilan aniqlanishi kerak.
ESLATMA: Agar biror-bir konstruktor sinfda e'lon qilinsa, bu
holda kompilyator o'z navbatida boshqa biror bir konsgruktorani taklif
qilmaydi, hatto obyektning rasmi bo'yicha ta'rifi e'lon qilingan
konstruktorga mos kelmasa ham. Bunday hollarda kompilyatsiya xato
xabarini ko'rsatadi.
Hech qanday xato qilmasdan dastur yozish aql bovar qilmaydigan
ko'rinadi. Shunga qaramay, ba'zi dasturchilar bunday mo " jizalarga
qodir, garchi, albatta, bunday sehrgarlar juda kam. Ularning aksariyati,
barcha oddiy odamlar kabi, xato qilishadi. Shu sababli, dasturlarni
yaratishning dastlabki bosqichida ularni ushlab qolish va tuzatish orqali
xatolarni kuzatishda yordam beradigan tizimni ishlab chiqqan
dasturchilar mavjud edi.
Kompilyator tomonidan aniqlangan xato xabarlari asablarga ta'sir
qilsa-da, bu dasturni bajarishda xatolar paydo bo‘lishiga qaraganda
ancha yaxshi. Agar kompilyator kamroq sinchkovlik bilan ishlagan
bo'lsa, unda sizning dasturingiz eng noo'rin daqiqada, masalan,
taqdimot paytida ishlamay qolishi ehtimoli katta.
Kompilyatsiya xatolari, ya'ni kompilyatsiya bosqichida aniqlangan
xatolar dasturni ishga tushirgandan so'ng paydo bo'ladigan ijro
xatolariga qaraganda ancha zararsizdir. Kompilyator aniqlangan xato
haqida ehtiyotkorlik bilan va Bir xil tipdagi xabar beradi. Aksincha, ish
vaqti xatosi hozircha o'zini aniqlay olmasligi mumkin, ammo keyin eng
noo'rin daqiqada o'zini namoyon qiladi. Kompilyatsiya xatolari har bir
kompilyatsiya seansida o'zini namoyon qilganligi sababli, ularni
211
aniqlash va tuzatish oson, shuning uchun ular endi esga olinmaydi. Vaqt
o'tishi bilan sehrli fokuslarni tashlamaydigan dasturlarni yaratishga
erishish uchun dasturchi kompilyatorga xatolarni kuzatishda yordam
berishi kerak, bu mumkin bo'lgan nosozliklarning oldini olish uchun
e`lonlardagi spetsifikatorlardan foydalanadi.
Sinfda e'lon qilingan har bir funksiya ta'rifga ega bo‘lishi kerak.
Ta'rif funksiyani bajarish deb ham ataladi. Boshqa funksiyalar kabi, sinf
usulining ta'rifi funksiya sarlavhasi va tanasidan iborat.
Ta'rif kompilyator osongina topishi mumkin bo'lgan faylda bo‘lishi
kerak. Ko'pgina C++ kompilyatorlari bunday fayl C yoki cpp
kengaytmasiga ega bo‘lishini afzal ko'rishadi. Ushbu kitob
kengaytmadan foydalanadi .cpp, lekin siz o'zingizning
kompilyatoringizning afzalliklarini bilib olishingiz kerak.
ESLATMA: Ko'pgina kompilyatorlar fayl kengaytma haqida deb
hisoblashadi. C C tilida yozilgan dasturlarni o'z ichiga oladi va SRP
kengaytmali fayllar C++ dasturlaridir. Siz har qanday kengaytmadan
foydalanishingiz mumkin, ammo C++dasturlarida yuzaga kelishi
mumkin bo'lgan tushunmovchiliklarni minimallashtiradigan cpp.
Sinf e'lonlari dastur bilan bitta faylga joylashtirilishi mumkin,
ammo bu yaxshi dasturlash uslubi deb hisoblanmaydi. Ko'pgina
dasturchilar tomonidan tuzilgan shartnomada, odatda, nomi dastur
faylining nomi bilan bir xil bo'lgan sarlavha fayliga e`lon qo'yish
tavsiya etiladi, ammo kengaytma sifatida quyidagi variantlardan
foydalaniladi .h, .hp yoki .hpp. Ushbu kitob sarlavhali fayl nomlari
uchun .hpp kengaytmadan foydalanadi, lekin siz o'zingizning
kompilyatoringizning afzalliklarini bilib olishingiz kerak.
Masalan, Cat class prototipini CAT, hpp deb nomlangan faylga va
sinf usullarining ta'rifini Cat.srr deb nomlangan faylga qo'yish mumkin.
Keyin sarlavha faylini kengaytmali fayl kodiga kiritishingiz kerak .srr.
Buning uchun CAT faylidagi dastur kodining boshida. cpp quyidagi
buyruqdan foydalanadi:
#include "Cat. hpp"
Ushbu buyruq kompilyatorga dasturning ma'lum bir joyida HPP sat
faylining tarkibini kiritishni buyuradi. Include buyrug'ini bajarish
natijasi klaviaturadan dasturning ushbu joyiga tegishli sarlavha
faylining to'liq tarkibini qayta yozganingiz bilan bir xil. Shuni yodda
tutingki, ba'zi kompilyatorlar harflarning katta-kichikligiga sezgir va

212
#include E’lonida va diskda fayl nomlarining yozilishi aniq mos
kelishini talab qiladi.
Nima uchun sarlavha faylini kengaytma bilan ajratish kerak .
kengaytmali dastur faylidan hpp.SRP, agar biz hali ham dastur fayliga
sarlavha faylining tarkibini kiritmoqchi bo'lsak? Amaliyot shuni
ko'rsatadiki, ko'pincha sizning sinfingiz mijozlari uni amalga oshirish
tafsilotlari haqida qayg'urmaydilar. Kichik sarlavha faylini
o'qiyotganda, ular barcha kerakli ma'lumotlarni olishadi va ushbu
sinfning ishlash tafsilotlari bilan faylni e'tiborsiz qoldirishlari mumkin.
Bundan tashqari, kengaytmali sarlavha faylining tarkibi bo‘lishi
mumkin . hpp-ni bitta emas, balki bir nechta dastur fayllariga qo'shishni
xohlaysiz.
ESLATMA:Sinf prototipi kompilyatorga ushbu sinf nima
ekanligini, unda qanday ma'lumotlar borligini va qanday funksiyalarga
ega ekanligini aytadi. Sinf prototipi uning interfeysi deb ataladi, chunki
u foydalanuvchiga sinf bilan qanday munosabatda bo‘lishni aytadi.
Interfeys odatda kengaytmali faylda saqlanadi .sarlavha fayli deb
nomlangan hpp.
Funksiya ta'rifidan kompilyator uning qanday ishlashini bilib oladi.
Funksiyaning ta'rifi sinf usulini bajarish deb ataladi va kengaytma bilan
faylda saqlanadi .srr. Sinfning bajarilishi tafsilotlari faqat sinf
muallifiga tegishli. Sinf mijozlari, ya'ni. ushbu sinfdan foydalanadigan
dasturning qismlari funksiyalar qanday bajarilishini bilishlari shart
emas.
Oddiy funksiyalar bilan bo'lgani kabi, inline kalit so'zi yordamida
usullarni almashtirish mumkin. Buning uchun inline kalit so'zi
qaytariladigan qiymat turidan oldin joylashtirilishi kerak. Masalan,
almashtirilayotgan getweight () a'zo funksiyasining ta'rifi quyidagi
rasmga ega:
inline int Cat::GetWeight()
{
return itsweight;
}
Bundan tashqari, funksiya ta'rifini sinf prototipiga
joylashtirishingiz mumkin, bu esa avtomatik ravishda bunday
funksiyani almashtiradi:
class Cat
{
public:
int GetWeight () {return itsWeight;}

213
void SetWeight(int aWeight);
};
GetWeight () funksiyasini aniqlash sintaksisiga e'tibor bering.
O'zgartirilgan funksiyaning tanasi sinf usuli e'lon qilingandan so'ng
darhol boshlanadi va qavslardan keyin nuqta-vergul yo'q. Oddiy
funksiyani aniqlashga o'xshab, usulning ta'rifi ochiladigan figurali qavs
bilan boshlanadi va yopuvchi figurali qavs bilan tugaydi. Odatdagidek,
bo‘sh joylar muhim emas va xuddi shu ta'rifni biroz boshqacha yozish
mumkin:
class Cat {
public:
int GetWeight() const
{ return itsWeight; // almashtirish funksiyasi }
void SetWeight(int aWeight);};
16.6 va 16.7 Listinglarida Cat sinfi yana yaratiladi, ammo bu holda
sinf prototipi Cat.hpp faylida, bajarilishi esa Cat.cpp faylida mavjud.
Bundan tashqari, 6.7 Listingida sinf ma'lumotlariga kirish usuli va
Meow() usuli almashtiriladi.
Listing 16.6. Cat.cpp faylida e'lon qilingan Cat
1 #include <iostream>
2 using namespace std;
3 class Cat {
4 public:
5 Cat (int initialAge);
6 ~Cat();
7 int GetAge() const { return itsAge; }
8 void SetAge (int age) { itsAge = age; }
9 void Meow () const { cout << "meow.\n";}
10 private:
11 int itsAge;
12 };
Listing 16.7. Cat.cpp faylida Cat sinfini bajarish
1 #include <iostream>
2 #include "cat.hpp "
3 using namespace std;
4 Cat:: Cat (int initialAge) / / konstruktor
5{
6 itsAge = initialAge;
7}
8 Cat:: Cat()
9 {}
10 int main()
11 {
12 Cat Frisky(5);
13 Frisky. Meow();

214
14 cout << "Frisky is a cat who is ";
15 cout << Frisky.QetAge() << " years old.\n";
16 Frisky. Meow();
17 Frisky. SetAge(7);
18 cout << "Now Frisky is "
19 cout << Frisky.GetAge() << " years old.\n";
20 return 0;
21 }
Natija:
Meow.
Frisky is a cat who is 5 years old.
Meow.
Now Frisky is 7 years old.
Tahlil:
16.6 va 16.7-Listinglarda taqdim etilgan dastur 16.4-Listingdagi
dasturga o'xshaydi, faqat uchta sinf usuli almashtirilgan deb e'lon
qilinadi va sinf prototipining o'zi Cat.hpp sarlavha fayliga
joylashtiriladi.
7-qatorda GetAge () funksiyasi e'lon qilinadi va darhol uning
bajarilishini aniqlash kerak. 8 va 9-qatorlar yana ikkita o'rnatilgan
funksiyalarning e'lonlarini egallaydi, ammo ularning ta'riflari boshqa
faylda mavjud.
16.7 Listingining 4-qatorida #include "cat.hpp " dasturi Cat.hpp
faylining tarkibini o'z ichiga oladi. Kompilyator cat.hpp faylining
tarkibini hisoblash va uni 5-qatordan boshlab berilgan faylga kiritish
buyrug'ini oladi.
Fayllarni boshqa fayllarga joylashtirish qobiliyati sinf e'lonlarini
ularni bajarishdan alohida saqlashga va kerak bo'lganda foydalanishga
imkon beradi. Bu C++dasturlarini yaratishda standart usul. Odatda, sinf
prototiplari hpp kengaytmasi bo'lgan faylda saqlanadi, so'ngra #include
e’loni yordamida tegishli cpp fayliga kiritiladi.
Oddiy sinflarni e'lon qilish va keyinchalik ularni murakkab sinf
prototipiga kiritish orqali murakkab sinf qurish odatiy hol emas.
Masalan, siz g'ildirak sinfini, dvigatel sinfini, Vites qutisi sinfini va
boshqalarni e'lon qilishingiz va keyin ularni avtomobil sinfiga
birlashtirishingiz mumkin. Shunday qilib, sinflar o'rtasidagi o'zaro
munosabatlar e'lon qilinadi. Avtomobilda dvigatel, g'ildiraklar va Vites
qutisi mavjud.
Ikkinchi misolni ko'rib chiqing. To'rtburchak chiziqlardan iborat.
Chiziq ikki nuqta bilan belgilanadi. Har bir nuqta x va y koordinatalari

215
bilan belgilanadi. 16.8 Listingida RECTANGLE faylida joylashgan
Rektangle sinfining prototipi ko'rsatilgan. hpp. To'rtburchak to'rtta
nuqtani bog'laydigan to'rtta chiziq bilan aniqlanganligi va har bir nuqta
grafikada koordinatalarga ega bo'lganligi sababli, avval har bir nuqta
uchun x koordinatalarini saqlash uchun nuqta sinfi e'lon qilinadi.
Listing 16.9 ikkala sinfning e'lonlarini o'z ichiga oladi.

Listing 16.8. Nuqta va to'rtburchaklar sinflarini e'lon qilish


1 #include <iostream>
2 using namespace std;
3 class Point {
4 public:
5 void SetX(int x) { itsX = x; }
6 void SetY(int y) { itsY = y;
7 int GetX() const { return itsX; }
8 int GetY() const { return itsY;}
9 private:
10 int itsX;
11 int itsY;
12 }; / / Point class prototipining oxiri
13 class Rectangle
14 {
15 public:
16 Rectangle (int top, int left, int bottom, int right);
17 Rectangle () {}
18 int GetTop() const { return itsTop; }
19 int GetLeft() const { return itsLeft; }
20 int GetBottom() const { return itsBottom; }
21 int GetRight() const { return itsRight; }
22 Point GetUpperLeft() const { return itsUpperLeft; }
23 Point GetLowerLeft() const ( return itsLowerLeft: }
24 Point GetUpperRight() const ( return itsUpperRight; }
25 Point GetLowerRight() const { return itsLowerRight; )
26 void SetUpperLeft(Point Location) {itsUpperLeft = Location;}
27 void SetLowerLeft(Point Location) {itsLowerLeft = Location;}
28 void SetUpperRight(Point Location) (itsUpperRight = Location;}
29 void SetLowerRight(Point Location) {itsLowerRight = Location;}
30 void SetTop(int top) { itsTop = top; }
31 void SetLeft (int left) { itsLeft = left; }
32 void SetBottom (int bottom) { itsBottom = bottom; }
33 void SetRight (int right) { itsRight = right; }
34 int GetArea() const;
35 private:
36 Point itsUpperLeft;
37 Point itsUpperRight;
38 Point itsLowerLeft;
39 Point itsLowerRight;
40 int itsTop;
41 int itsLeft;
42 int itsBottom;
43 int itsRight;
44 };

216
Listing 16.9. Rect.cpp faylining tarkibi
1 #include "rect.hpp"
2 Rectangle::Rectangle(int top, int left, int bottom, int right)
3{
4 itsTop = top;
5 itsLeft = left;
6 itsBottom = bottom;
7 itsRight = right;
8 itsUpperLeft.SetX(left);
9 itsUpperLeft. SetY(top);
10 itsUpperRight.SetX(right);
11 itsUpperRight.SetY(top);
12 itsLowerLeft.SetX(left);
13 itsLowerLeft.SetY(bottom);
14 itsLowerRight.SetX(right);
15 itsLowerRight. SetY(bottom);
16 }
17 int Rectangle::GetArea() const
18 {
19 int Width = itsRignt - itsLeft;
20 int Height = itsTop - itsBottom;
21 return (Width • Height);
22 }
23 using namespace std;
24 int main()
25 {
26 Rectangle MyRectangle (100, 20, 50, 80 );
27 int Area = MyRectangle.GetArea();
28 cout << "Area: "<< Area << "\n";
29 cout << "Upper Left X Coordinate:";
30 cout << MyRectangle.GetUpperLeft().GetX();
31 return 0;
32 }
Natija:
Area: 3000
Upper Left X Coordinate: 20
Tahlil:
16.8 Listingining 3-12-qatorlarida grafikada x, y aniq
koordinatalarini saqlash uchun ishlatiladigan nuqta sinfi e'lon qilinadi.
Ushbu dasturda Point sinfi deyarli ishlatilmaydi. Biroq, boshqa chizish
usullarida bu ajralmas hisoblanadi.
Point class prototipida (10 va 11-qatorlarda) ikkita o'zgaruvchi
e'lon qilinadi (itsX va itsY). Ushbu o'zgaruvchilar nuqta koordinatalari
qiymatlarini saqlaydi. X koordinatasining oshishi bilan biz grafikada
o'ngga siljiymiz. Y koordinatasining oshishi bilan biz grafikda yuqoriga
ko'tarilamiz. Boshqa grafikalar boshqa koordinatali tizimlardan
foydalanishi mumkin (boshqa yo'nalishda). Masalan, ba'zi oyna qurish

217
dasturlarida koordinataning qiymati y deraza maydonini pastga
siljitganda ortadi.
Point sinfi x va y nuqtalarining koordinatalarini o'qish va o'rnatish
uchun mo'ljallangan inline-ga kiritilgan kirish funksiyalaridan
foydalanadi, bu funksiyalar 7-8 qatorlarda e'lon qilinadi. Point sinfidagi
obyektlar standart kompilyator tomonidan taqdim etilgan standart
konstruktor va destruktordan foydalanadi. Shuning uchun nuqta
koordinatalari dasturda o'rnatilishi kerak.
13-qatorda to'rtburchakning burchaklarini ifodalovchi to'rtta
nuqtani o'z ichiga olgan to'rtburchaklar sinfining prototipi boshlanadi.
To'rtburchaklar sinf konstruktori top (yuqori), left (chap), bottom
(pastki) va right (o'ng) deb nomlangan to'rtta butun sonli parametrlarni
oladi.
Konstruktorga berilgan ushbu to'rtta parametr tegishli to'rtta a'zo
o'zgaruvchiga ko'chiriladi (16.9-Listingga qarang), so'ngra to'rtta nuqta
(to'rtta nuqta sinf obyektlari) o'rnatiladi.
Oddiy sinf a'zolari ma'lumotlariga kirish funksiyalaridan tashqari,
to'rtburchaklar sinfida 17-qatorda e'lon qilingan GetArea () funksiyasi
mavjud. Maydon qiymatini o'zgaruvchi sifatida saqlash o'rniga, bu
funksiya 16.9 Listingining 19 va 20 qatorlaridagi maydonni hisoblab
chiqadi. Buning uchun avval to'rtburchakning uzunligi va kengligi
qiymatlari hisoblab chiqiladi, so'ngra olingan natijalar ko'paytiriladi.
To'rtburchakning yuqori chap burchagining koordinatasini olish
uchun siz UpperLeft nuqtasiga kirishingiz va uning x qiymatini
so'rashingiz kerak. GetUpperLeft() funksiyasi Rectangle sinfining usuli
bo'lganligi sababli, u to'g'ridan-to'g'ri ushbu sinfning yopiq
ma'lumotlariga, shu gapdan itsupperleft o'zgaruvchisiga ham kirishi
mumkin. Itsupperleft o'zgaruvchisi Point sinfining obyekti va ushbu
obyektning itsX o'zgaruvchisi yopiq bo'lganligi sababli,
GetUpperLeft() funksiyasi ushbu o'zgaruvchiga to'g'ridan-to'g'ri
murojaat qila olmaydi. Buning o'rniga, itsx o'zgaruvchisining qiymatini
olish uchun u GetX () ochiq kirish funksiyasidan foydalanishi kerak.
16.9 Listingining 24-qatorida dasturning asosiy qismi boshlanadi.
Hozirgacha qilingan hamma narsa kompilyatorga nuqta qanday
yaratilganligi va to'rtburchak qanday yaratilganligi to'g'risida xabar
berish uchun bitta maqsadga xizmat qildi (agar kerak bo'lsa).

218
26-qatorda Thor, Left, Bottom va Right parametrlari uchun haqiqiy
qiymatlarni uzatish orqali to'rtburchak (to'rtburchaklar sinf obyekti)
aniqlanadi.
27-qatorda int tipidagi local maydon o'zgaruvchisi yaratiladi.
Yaratilgan to'rtburchakning maydonini saqlash uchun mo'ljallangan.
Maydon o'zgaruvchisiga Rectangle sinfining GetArea() a'zosi
funksiyasi tomonidan qaytarilgan qiymat beriladi.
Rectangle class Client Rectangle obyektini yaratishi va GetArea ()
funksiyasini bajarish nuanslari haqida qayg'urmasdan uning maydonini
qaytarishi mumkin.
Listing 16.8 Rect sarlavha .hpp faylining tarkibini ko'rsatadi. Faqat
Rectangle sinfining prototipini o'z ichiga olgan sarlavha faylini ko'rib
chiqqandan so'ng, dasturchi GetArea() funksiyasi int tipidagi qiymatni
qaytarishini biladi. Rectangle sinf foydalanuvchisi GetArea ()
funksiyasining "ishlab chiqarish" sirlari haqida qayg'urmaydi.
Rectangle sinfining muallifi GetArea () funksiyasining bajarilishini
o'zgartirishi mumkin va bu Rectangle sinfidan foydalanadigan
dasturlarga ta'sir qilmaydi.
TUZILMALAR
Class kalit so'zining juda yaqin qarindoshi strukturani e'lon qilish
uchun ishlatiladigan struct kalit so'zidir. C++ tilida struktura bir xil sinf,
lekin sukut bo'yicha ochiq a'zolar bilan.Strukturani sinf e'lon
qilinganidek e'lon qilish mumkin, unga bir xil a'zo o'zgaruvchilar va
funksiyalar beriladi.
Ikki xil kalit so'zlar deyarli bir xil e`lonlarni yaratayotganidan
hayron bo‘lishingiz mumkin. Bu tarixan shunday bo'lgan. C++ tili C
kengaytma sifatida qurilgan . C tilida tuzilmalar mavjud edi, ammo bu
tuzilmalar sinf usullariga ega emas edi. C++ yaratuvchisi Byorn
Stroustrap tuzilmalarga tayangan, ammo struct ma'lumotlar turi nomini
sinf turi bilan almashtirgan va shu bilan ushbu yangi ta'limning yangi
rivojlangan funktsional imkoniyatlarini e'lon qilgan.
Tavsiya etiladi!
 Sinf prototipini hpp kengaytmasi bo'lgan faylga va uning bajarilishini
cpp kengaytmasi bo'lgan faylga joylashtiring.
 Iloji bo'lsa, const spetsifikatoridan foydalaning.
 Keyingi darsga o'tishdan oldin darslar haqida to'liq ma'lumotga ega
ekanligingizga ishonch hosil qiling.

219
Nazorat savollari va topshiriqlar:
1. To'g'ridan-to'g'ri kirish operatori nima va u nima uchun ishlatiladi?
2. Sinf prototipi uning interfeysi yoki bajarilishimi?
3. Ochiq (Public) va yopiq (Private) a'zo ma'lumotlar o'rtasidagi farq
nima?
4. A'zo funksiyalar yopiq bo‘lishi mumkinmi?
5. A'zo o'zgaruvchilar ochiq bo‘lishi mumkinmi?
6. Agar Cat sinfining ikkita obyekti e'lon qilinsa, ular itsAge a'zo
o'zgaruvchilarining turli qiymatlariga ega bo‘lishi mumkinmi?
7. Sinf e'lonlarini nuqta-vergul bilan to‘ldirish kerakmi? Sinf
usullarining ta'riflari?
8. Hech qanday parametrlarni qabul qilmaydigan va void tipidagi
qiymatni qaytaradigan Cat sinfining meow a'zosi funksiyasining
sarlavhasi qanday ko'rinishga ega bo'lar edi?
9. Sinfni ishga tushirish uchun qanday funksiya chaqiriladi?
10. Bunday a'zo o'zgaruvchilar bilan ishchi (xodimlar) deb nomlangan
sinfni e'lon qiladigan dasturni yozing: age (yosh), years0fService (ish
staji) va ish haqi (ish haqi).
11. A'zo ma'lumotlarini yopiq qilish va barcha a'zo ma'lumotlarni o'qish
va o'rnatish uchun ochiq kirish usullarini ta'minlash uchun Employee
sinfini qayta yozing.
12. Ikkita Employee sinf obyektlarini yaratadigan Employee sinfidan
foydalanib dastur yozing; age, Years0fService va Salary a'zo
ma'lumotlarini o'rnatadi va keyin ularning qiymatlarini chiqaradi.
13. 12-mashqdan olingan dasturga asoslanib, xodim javobni 1000
dollarga yaxlitlash orqali qancha ming dollar ishlab topishini
bildiruvchi employee sinf usulini yarating.
14. Xodimni "yaratish" jarayonida age, YearsOfService va Salary
a'zolari ma'lumotlarini ishga tushirish uchun xodimlar sinfini
o'zgartiring.
15. Keyingi e'londa nima noto'g'ri?
class Square
{
public:
int Side;
}

220
17-MAVZU. C++ DA MODIFIKATOR BILAN ISHLASH
 Public modifikatori
 Private modifikatori
 Protected modifikatori
 Inkapsulyatsiya
 Do’st sinflari va funksiyalari

barcha nomlar uchun bir xil darajada


qo'llaniladi: a'zo funksiyalari, a'zo ma'lumotlari, ichki sinflar va
ro'yxatchilar.
Listing 17.1. Person sinfi
1 class Person
2{
3 public:
4 string name;
5 int age;
6 Person(string n, int a)
7{ name = n; age = a; }
8 void move()
9{
10 cout << userName << " is moving" << endl;
11 }
12 };
kirish spetsifikatori ( ), ya'ni
sinf a'zolari - o'zgaruvchilar va funksiyalarga kirish parametrlarini
belgilaydi. Xususan, bu ularni dasturning istalgan qismidan yoki ochiq
holda taqdim etadi.
Aslida, sinfning umumiy interfeysini
belgilaydi. Ya'ni, bu holda name va age maydonlari ochiq va biz ularga
tashqi kodda har qanday qiymatlarni belgilashimiz mumkin:
1 Person tom("Tom", 22);
2 tom.name = "anvar";
3 tom.age = -1001;
Shu jumladan, siz ba'zi bir nomaqbul qiymatlarni belgilashingiz
mumkin, masalan, foydalanuvchi yoshi uchun manfiy qiymat. Tabiiyki,
bu juda yaxshi holat emas.
Biroq, boshqa yordamida biz sinf
a'zolarining bajarilishini yashirishimiz mumkin, ya'ni ularni yopiq qilib,
sinf ichida inkapsulyatsiya qilishimiz mumkin. Biz shaxsiy sinfni
xususiy spetsifikatordan tashqari qayta yozamiz:

221
Listing 17.2. Modifikatorlar bilan ishlash
#include <iostream>
#include <string>
using namespace std;

class Person
{
public:
Person(string n, int a)
{
name = n; age = a;
}
void setAge(int a)
{
if (a > 0 && a < 100) age = a;
}
string getName()
{
return name;
}
int getAge()
{
return age;
}
private:
string name;
int age;
};

int main()
{
Person tom("Tom", 22);
// string personName = tom.name; // xato-name
o‘zgaruvchisi yopiq
cout << "Name: " << tom.getName() << "\tAge: " <<
tom.getAge() << endl;
tom.setAge(31);
cout << "Name: " << tom.getName() << "\tAge: " <<
tom.getAge() << endl;
tom.setAge(291);
cout << "Name: " << tom.getName() << "\tAge: " <<
tom.getAge() << endl;
return 0;
}
Endi Person sinfidagi name va age o'zgaruvchilari yopiq, shuning
uchun biz ularga to'g'ridan-to'g'ri murojaat qila olmaymiz. Biz ularga
faqat sinf ichida murojaat qilishimiz mumkin.

222
Shunday bo'lsada, tashqi tomondan name va age
o'zgaruvchilarining qiymatlarini olish uchun getAge va getName
qo'shimcha funksiyalari aniqlanadi.
Name o'zgaruvchisining qiymatini to'g'ridan - to'g'ri faqat
konstruktor orqali, age o'zgaruvchisining qiymatini esa konstruktor
yoki setAge funksiyasi orqali o'rnatish mumkin.
Shunday qilib, sinf holati tashqi tomondan yashiringan, unga faqat
sinf interfeysi taqdim etadigan qo'shimcha funksiyalar orqali kirish
mumkin.
Shuni ham ta'kidlash joizki, agar sinfda kirish spetsifikatori
bo'lmasa yoki ba'zi sinf a'zolari uchun aniqlanmagan bo'lsa, u holda
private kirish spetsifikatori sukut bo'yicha ishlatiladi:
Listing 17.3. Person sinfi
1 class Person{
2 string name;
3 int age;
4 public:
5 Person(string n, int a)
6 {name = n; age = a;}
7 void move()
8 {cout << name << " is moving" << endl;}
9 void setAge(int a)
10 { if (a > 0 && a < 100) age = a; }
11 string getName()
12 { return name;}
13 int getAge()
14 { return age;}};
Name va age o'zgaruvchilari uchun bu yerda kirish spetsifikatori
aniqlanmagan, shuning uchun ular sukut bo'yicha
ga ega.
Kirish turi Qiymati

private deb e'lon qilingan sinf a'zolaridan faqat sinf


a'zolari va do'stlari (sinflar yoki funksiyalar)
funksiyalari foydalanishi mumkin.

protected deb e'lon qilingan sinf a'zolari sinfning


a'zo va do'st funktsiyalari (sinflari yoki funksiyalari)
tomonidan ishlatilishi mumkin . Bundan tashqari,

223
ular ma'lum bir sinfning olingan sinflari tomonidan
ishlatilishi mumkin.

public deb e'lon qilingan sinf a'zolari har qanday


funksiya tomonidan ishlatilishi mumkin.
17.1-rasm. A'zolarga kirishni boshqarish
INKAPSULYATSIYA
Obyektga yo'naltirilgan dasturlashda (yoki
"ma'lumotni yashirish") — bu obyektni amalga oshirish tafsilotlarini
yashirin saqlash jarayoni. Foydalanuvchilar obyektga ochiq interfeys
orqali kirishadi.
Inkapsulyatsiyalangan sinflardan foydalanish
osonroq va dasturlaringizning murakkabligini kamaytiradi.
To'liq inkapsulyatsiyalangan sinf bilan siz faqat qaysi usullardan
foydalanish mumkinligini, qaysi argumentlarni qabul qilishini va qaysi
qiymatlarni qaytarishini bilishingiz kerak.
Inkapsulyatsiyalangan sinflarni o'zgartirish oson.

Listing 17.4. Values sinfi obyektini yaratish


1 #include <iostream>
2 class Values
3{
4 public:
5 int m_number1;
6 int m_number2;
7 int m_number3;
8 };
9 int main()
10 {
11 Values value;
12 value.m_number1 = 7;
13 std::cout << value.m_number1 << '\n';
14 }
Ba'zan dastur oldida qo'yilgan vazifalarni bajarish uchun bir nechta
mustaqil sinflarning o'zaro ta'sirini ta'minlash kerak. Masalan,
PartNode va PartsList sinflari bir-biri bilan chambarchas bog'liq. Agar
PartNode sinfining itsPart ko'rsatgichi PartsList da to'g'ridan-to'g'ri
ishlatilishi mumkin bo'lsa, bu qulay bo'ladi.

224
Albatta, itsPart ni ochiq yoki hech bo'lmaganda himoyalangan a'zo
o'zgaruvchisi deb e'lon qilish mumkin, ammo bu sinflardan foydalanish
g'oyasiga zid bo'lgan yo'ldan uzoq. Itspart ko'rsatgichi PartNode
sinfining o'ziga xos a'zosi bo'lganligi sababli, uni tashqi sinflarga kirish
imkoni bo'lmasligi kerak.
Ammo, agar siz boshqa sinfga ma'lumot yoki yopiq usullarni
taqdim qilmoqchi bo'lsangiz, bu sinfni do'st deb e'lon qilish kerak. Bu
sizning sinf interfeysingizni do'st sinfining imkoniyatlari bilan
kengaytiradi.
Shuni ta'kidlash kerakki, sinfning do'stligi boshqa sinflarga
o'tkazilmaydi. Boshqacha qilib aytganda, Agar siz mening do'stim
bo'lsangiz va Vanya sizning do'stingiz bo'lsa, bu Vanya ham mening
do'stim degani emas.
Sinflarning do'stligi bir tomonlama. Bir sinfni boshqa sinfning
do'sti deb e'lon qilish, ikkinchisini birinchisining do'stiga
aylantirmaydi. Agar xohlasangiz, sirlaringizni men bilan baham
ko'rishingiz mumkin, ammo bu sizga sirlarimni aytib berishim kerak
degani emas.
Boshlang'ich C++ dasturchilaridan do'stlar sinflarini e'lon qilish
obyektga yo'naltirilgan dasturlash asosidagi inkapsulyatsiya prinsipiga
zid ekanligini tez-tez eshitishingiz mumkin. Rostini aytsam, bu juda
keng tarqalgan be’manilik. Do'st-sinf prototipi shunchaki boshqa sinf
interfeysini kengaytiradi.
DO'STONA SINF
Ikkinchi sinf e'lonidagi kalit so'zidan foydalanib, bitta sinfni
boshqa birovning do'sti deb e'lon qilish birinchi sinfga ikkinchi sinf
a'zolariga kirish huquqini beradi.
Listing 17.6.
class PartNode()
public:
friend class PartsList;
DO’ST FUNKSIYALARI
Ba'zan butun sinfga emas, balki faqat bitta yoki bir nechta a'zo
funksiyalarga ruxsat berish kerak bo'ladi. Bu do'stlar tomonidan boshqa
sinf a'zolari funksiyalarini e'lon qilish orqali amalga oshiriladi. Bundan
tashqari, butun sinfni do'st deb e'lon qilish shart emas. Aslida, har
qanday funksiya boshqa sinfning a'zosi yoki yo'qligidan qat'i nazar,
do'st deb e'lon qilinishi mumkin.

225
C va C++ satrlari oxirgi belgisi nol bilan tugaydigan belgilar
massividir. Bunday satrga misol:
myString [] = "Salom dunyo".
Ammo String sinfida amalga oshirib bo'lmaydigan narsa bu sinf
obyektini belgilar qatori bilan qo'shish natijasida yangi qatorni hosil
qilish:
char cString[] = { "Hello"} ;
String string(" World");
String string = cString + sstring; // xato!
Satrlarni qo‘shimcha yuklangan operator funksiyasi bilan ishlatib
bo'lmaydi. Qo‘shimcha yuklangan operator funksiyasini belgilar
qatoriga chaqirish mumkin emasligi sababli, ushbu urinish
kompilyatsiya xatosiga olib keladi.
Ushbu muammoni operator + ni ikkita string obyektini
jamlaydigan tarzda yuklaydigan string sinfidagi do'st funksiyasini e'lon
qilish orqali hal qilish mumkin. Tegishli string sinf konstruktori
satrlarni string obyektlariga o'zgartiradi, shundan so'ng operator + do'st
funksiyasi chaqiriladi, u ikkita obyektni birlashtiradi.
DO'STLAR FUNKSIYALARI
Funksiyani sinf do'sti sifatida e'lon qilish uchun do'st kalit so'zidan
keyin funksiya prototipi ishlatiladi. Bu funksiyani ta'minlamaydi. Bu
ko'rsatgichga kirish, lekin barcha yopiq va himoyalangan ma'lumotlar
va a'zo funksiyalarga kirishni ta'minlaydi.
Listing 17.7.
class PartNode
{
friend void PartsList::Insert(Part +);
friend int SomeFunction();
};
CHIQARISH OPERATORINING QO‘SHIMCHA
YUKLANISHI
Endi bizning String sinfimizni cout obyektidan foydalanib, asosiy
tipdagi ma'lumotlarni chiqarishda bo'lgani kabi ma'lumotlarni chiqarish
uchun imkoniyat bilan ta'minlash vaqti keldi. Hozirgacha a'zo
o'zgaruvchining qiymatini chiqarish uchun quyidagi ifodadan
foydalanish kerak edi:
cout << theString.GetString();
yoki
cout << theString;
226
Buning uchun operator funksiyasini qo‘shimcha yuklash kerak.
Ma'lumotlarni chiqarish uchun iostream operatorlaridan foydalanish
mumkin.

Nazorat savollari va topshiriqlar:


1. Boshqa sinfning shaxsiy namoyishi bo'lgan sinfni qanday e'lon qilish
kerak?
2. Obyektlari boshqa sinfning a'zo o'zgaruvchilari sifatida ishlatilishi
kerak bo'lgan sinfni qanday e'lon qilish kerak?
3. Sinfni boshqa sinf ichida yaratish va bajarish o'rtasidagi farqlar
qanday?
4. Do'st funksiyasi nima? Sinf do'sti nima?
5. Agar dog sinfi boy ning do'sti bo'lsa, unda boy itning do'sti deb ayta
olasizmi?
6. Do'st funksiyasi prototipini qayerga joylashtirish kerak?
7. String sinfining obyekti bo'lgan atama o'zgaruvchisini o'z ichiga
olgan Animal sinfini e'lon qiling.

227
18-MAVZU. STATIK BERILGANLAR, STATIK SINFLAR
 Statik a'zo o'zgaruvchilar va a'zo funksiyalar
 Statik a'zo o'zgaruvchilar va a'zo funksiyalardan foydalanish
 Funksiyalar va a'zo funksiyalarga ko'rsatgichlarni yaratish va
qo'llash
 Funksiya ko'rsatgichlari qatori bilan ishlash
C++ dasturlash tili ko'lamni cheklash va o'zgaruvchilar va
ko'rsatgichlardan foydalanishning bir necha usullarini taklif etadi.
Oldingi boblarda siz butun dasturda ishlatiladigan global
o'zgaruvchilarni va alohida funksiyalarda ishlatiladigan lokal
o'zgaruvchilarni yaratishni o'rgandingiz. Siz sinf o'zgaruvchilari va a'zo
o'zgaruvchilarga ko'rsatgichlar nima ekanligini bilib oldingiz.
STATIK A'ZO O'ZGARUVCHILAR
Hozirgacha siz har qanday obyekt ma'lumotlari ishlatiladigan
obyektga xos va bir nechta sinf obyektlari tomonidan birgalikda
qo'llanilmasligi mumkinligiga ishongansiz. Boshqacha qilib aytganda,
agar beshta mushuk obyekti yaratilgan bo'lsa, unda ularning har biri o'z
hayoti, hajmi va boshqalar bilan ajralib turadi.
Biroq, ba'zida dastur tomonidan ma'lumotlarning to'planishini
nazorat qilish kerak bo'ladi. Ma'lum bir sinfdagi jami qancha obyektlar
yaratilganligi va hozirda qancha obyektlar mavjudligi haqida ma'lumot
talab qilinishi mumkin.
Statik a'zo o'zgaruvchilar sinfning barcha obyektlari tomonidan
taqsimlanadi. Ular dasturning barcha qismlari uchun mavjud bo'lgan
global ma'lumotlar va odatda faqat bitta obyekt uchun mavjud bo'lgan
a'zolar ma'lumotlari o'rtasidagi "oltin markaz" ga o'xshaydi.
Statik a'zolar obyektga emas, balki sinfga tegishli deb taxmin qilish
mumkin. Agar oddiy a'zolarning ma'lumotlari bitta obyekt uchun
mavjud bo'lsa, unda statik atamalar butun sinf tomonidan ishlatilishi
mumkin. 18.1-Listing howmanycats statik a'zosi bo'lgan Cat obyektini
e'lon qiladi. Ushbu o'zgaruvchi konstruktor chaqirilganda statik
HowManyCats o'zgaruvchisi ko'payishi yoki destruktor chaqirilganda
manfiy o'sish bilan amalga oshiriladigan yaratilgan Cat obyektlari
sonini hisobga oladi.
Listing 18.1. Statik a'zo o'zgaruvchilar
1 #include <iostream>
2 using namespace std;
3 class Cat

228
4{
5 public:
6 Cat(int age):itsAge(age) {HowManyCats++; }
7 virtual ~Cat() { HowManyCats--; }
8 virtual int GetAge() { return itsAge; }
9 virtual void SetAge(int age) { itsAge = age;}
10 static int HowManyCats;
11 private:
12 int itsAge;
13 };
14 int Cat::HowManyCats = 0;
15 int main(){
16 const int MaxCats = 5; int i;
17 Cat *CatHouse[MaxCats];
18 for (i = 0; i<MaxCats; i++)
19 CatHouse[i] = new Cat(i);
20 for (i = 0; i<MaxCats; i++)
21 {cout << "There are ";
22 cout << Cat:: HowManyCats;
23 cout << " cats left!\n";
24 cout<<"Deleting the one which is ";
25 cout << CatHouse[i]->GetAge();
26 cout << " years old\n";
27 delete CatHouse[i];
28 CatHouse[i] = 0;}
29 return 0;}
Natija:
There are 5 cats left!
Deleting the one which is 0 years old
There are 4 cats left!
Deleting the one which is 1 years old
There are 3 cats left!
Deleting the one which is 2 years old
Listing 18.2. Obyektlardan foydalanmasdan statik a'zolarga kirish
#include<iostream>
using namespace std;
class Cat{
public:
Cat(int age):itsAge(age){ HowManyCats++; }
virtual ~Cat() { HowManyCats--; }
virtual int GetAge() { return itsAge; }
virtual void SetAge(int age) {itsAge = age;}
static int HowManyCats;
private:
int itsAge;
};
int Cat::HowManyCats = 0;
void TelepathicFunction();
int main()

229
{
const int MaxCats = 5; int i;
Cat * CatHouse[MaxCats];
for (i = 0; i<MaxCats; i++)
CatHouse[i] = new Cat(i);
TelepathicFunction();
for ( i = 0; i<MaxCats; i++)
{delete CatHouse[i];
TelepathicFunction();}
return 0;}
void TelepathicFunction()
{cout << "There are ";
cout << Cat::HowManyCats << " cats alive!\n";}
Natija:
There are 1 cats alive!
There are 2 cats alive!
There are 3 cats alive!
There are 4 cats alive!
There are 5 cats alive!
There are 4 cats alive!
There are 3 cats alive!
There are 2 cats alive!
There are 1 cats alive!
There are 0 cats alive!
Listing 18.3. statik a'zoga kirish
1 #include <iostream>
2 using namespace std;
3 class Cat
4{
5 public:
6 Cat(int age):itsAge(age){ HowManyCats++; }
7 virtual ~Cat() { HowManyCats--; }
8 virtual int GetAge() { return itsAge;}
9 virtual void SetAge(int age) { itsAge = age; }
10 virtual int GetHowMany() { return HowManyCats; }
11 private:
12 int itsAge;
13 static int HowManyCats;
14 };
15 int Cat:: HowManyCats = 0;
16 int main()
17 {
18 const int MaxCats = 5; int i;
19 Cat *CatHouse[MaxCats];
20 for (i = 0; i<MaxCats; i++)
21 CatHouse[i] = new Cat(i);
22 for (i = 0; i<MaxCats; i++)
23 {cout << "There are ";
24 cout << CatHouse[i]->GetHowMany();
25 cout << " cats left!\n";

230
26 cout << "Deleting the one which is ";
27 cout << CatHouse[i]->GetAge()+2;
28 cout << " years old\n";
29 delete CatHouse[i];
30 CatHouse[i] = 0;
31 }
32 return 0;
33 }
Tavsiya etiladi!
 Bir nechta sinf obyektlari tomonidan ma'lumotlarni
almashish uchun statik a'zo o'zgaruvchilarni qo'llang.
 Statik a'zo o'zgaruvchilarga kirishni shaxsiy yoki
himoyalangan deb e'lon qilish orqali cheklang.
Tavsiya etilmaydi!
 Bitta obyekt ma'lumotlarini saqlash uchun statik a'zo
o'zgaruvchilardan foydalanmang. Ushbu o'zgaruvchilar obyektlar
o'rtasida ma'lumot almashish uchun mo'ljallangan.
STATIK A'ZO FUNKSIYALARI
Statik a'zo funksiyalari statik a'zo o'zgaruvchilarga o'xshaydi: ular
bitta obyektga tegishli emas, balki butun sinf doirasiga kiradi. Shuning
uchun ularni 18.4-Listingda ko'rsatilgandek, bitta sinf obyekti
yaratilmagan hollarda ham chaqirish mumkin.
Listing 18.4. Statik a'zo funksiyalari
1 #include <iostream>
2 using namespace std;
3 class Cat
4{
5 public:
6 Cat(int age):itsAge(age){ HowManyCats++; }
7 virtual ~Cat() { HowManyCats--; }
8 virtual int GetAge() { return itsAge; }
9 virtual void SetAge(int age) { itsAge = age; }
10 static int GetHowMany() { return HowManyCats; }
11 private:
12 int itsAge;
13 static int HowManyCats;
14 };
15 int Cat::HowManyCats = 0;
16 void TelepathicFunction();
17 int main()
18 {
19 const int MaxCats = 5;
20 Cat * CatHouse[MaxCats]; int i;
21 for (i = 0; i<MaxCats; i++)
22 {CatHouse[i] = new Cat(i);

231
23 TelepathicFunction();}
24 for ( i = 0; i<MaxCats; i++)
25 {delete CatHouse[i];
26 TelepathicFunction();}
27 return 0;}
28 void TelepathicFunction()
29 {cout << "There are " << Cat::GetHowMany() << " cats
alive!\n";}
Natija:
There are 1 cats alive!
There are 2 cats alive!
There are 3 cats alive!
There are 4 cats alive!
There are 5 cats alive!
There are 4 cats alive!
There are 3 cats alive!
There are 2 cats alive!
There are 1 cats alive!
There are 0 cats alive!
Statik a'zo funksiyalari bu ko'rsatgichni o'z ichiga olmaydi.
Shuning uchun ular const spetsifikatori bilan e'lon qilinishi mumkin
emas. Bundan tashqari, a'zo funksiyalar ushbu ko'rsatgich yordamida
a'zo o'zgaruvchilarga kirish huquqiga ega bo'lganligi sababli, statik a'zo
funksiyalar odatdagi statik bo'lmagan a'zo o'zgaruvchilardan foydalana
olmaydi.
STATIK FUNKSIYALAR
Statik a'zo funksiyalarga ularni sinf obyektlaridan oddiy a'zo
funksiyalari sifatida chaqirish yoki ularni obyektlarsiz chaqirish orqali
kirish mumkin, bu holda sinf nomini aniq ko'rsatib beradi.
Listing 18.5
class Cat
{public:
static int GetHowMany() { return HowManyCats; }
private:
static int HowManyCats;};
int Cat: : HowManyCats = 0;
int main()
{int howMany;
Cat theCat// obyektni aniqlash
howMany-theCat GetHowMany (); / / obyekt orqali kirish
howMany = Cat:: GetHowMany (): - / / obyektsiz kirish}
FUNKSIYA KO'RSATKICHLARI
Massiv nomi o‘zgarmas ravishda uning birinchi elementini
ko'rsatganidek, funksiya nomi ham funksiyaning o'ziga ishora qiladi.
Siz funksiya ko'rsatgichi o'zgaruvchisini e'lon qilishingiz va
232
keyinchalik ushbu ko'rsatgich yordamida uni chaqirishingiz mumkin.
Ushbu imkoniyat juda foydali bo‘lishi mumkin, chunki u klaviaturadan
kiritilgan foydalanuvchi buyruqlari orqali funksiyalar chaqiriladigan
dasturlarni yaratishga imkon beradi.
Funksiya ko'rsatgichini aniqlash uchun yagona muhim tafsilot - bu
ko'rsatgich murojaat qiladigan obyekt turini bilishdir. Int tipidagi
ko'rsatgich, albatta, butun son o'zgaruvchisi bilan bog'liq. Xuddi
shunday, funksiya ko'rsatgichi faqat berilgan imzo va qaytish turiga ega
funksiyalarni chaqirishi mumkin.
E'londa
long (+ funcPtr) (int);
funcptr funksiyasi uchun ko'rsatgich yaratiladi (ko'rsatgich nomidan
oldin * belgisiga e'tibor bering), u butun sonli parametrni oladi va Long
turidagi qiymatni qaytaradi. (* FuncPtr) atrofidagi qavslar majburiydir,
chunki (int) atrofidagi qavslar bilvosita (*) operatoridan ustun turadi.
Agar siz birinchi qavslarni olib tashlasangiz, unda bu ifoda butun sonli
parametrni qabul qiladigan va ko'rsatgichni Long turidagi qiymatga
qaytaradigan funcPtr funksiyasini e'lon qiladi. (Esda tutingki, C++ dagi
barcha bo‘sh joylar e'tiborga olinmaydi.)
Quyidagi ikkita misolni ko'rib chiqing:
long Function (int);
long (* funcPtr) (int);
Birinchi qatorda Function() - bu butun sonli parametrni qabul
qiladigan va ko'rsatgichni Long turidagi o'zgaruvchiga qaytaradigan
funksiya. Ikkinchi misolda funcPtr butun sonli parametrni qabul
qiladigan va 1ong turidagi o'zgaruvchini qaytaradigan funksiyaga
ko'rsatgichdir.
Funksiya uchun ko'rsatgichni e'lon qilish har doim qaytariladigan
o'zgaruvchining turini va agar mavjud bo'lsa, qavs ichida rasmiy
parametr turlarining Listingini o'z ichiga oladi.
FUNKSIYAGA KO'RSATGICH
Ko'rsatgich orqali funksiyaga kirish, u ko'rsatadigan funksiyaning
odatiy chaqiruvi bilan bir xil tarzda yoziladi. Faqat funksiya nomi
o'rniga ushbu funksiyaga ko'rsatgich nomi ishlatiladi.
Funksiyaga ko'rsatgichni ma'lum bir funksiya bilan bog'lash uchun
unga hech qanday qavssiz funksiya nomini berish kifoya. Funksiya
nomi, siz allaqachon bilganingizdek, funksiyaning o'ziga o‘zgarmas
ko'rsatgichdir. Shuning uchun funksiyaga ko'rsatgich uning nomi bilan
233
bir xil ishlatiladi. Funksiyani ko'rsatgich orqali chaqirganda, joriy
funksiya uchun o'rnatilgan barcha parametrlarni o'rnatishingiz kerak.
Listing 18.6
long(+pFuncOne) (int, int);
long SomeFunction (int, int):
pFuncOne - SomeFunction;
pFuncOne (5,7);
Listing 18.7. Funksiya ko'rsatgichlaridan foydalanmaslik
1 #include <iostream>
2 using namespace std;
3 void Square (int&,int&);
4 void Cube (int&, int&);
5 void Swap (int&, int &);
6 void Getvals(int&, int&);
7 void PrintVals(int, int);
8 int main(){
9 bool fQuit = false;
10 int valOne=1, valTwo=2;
11 int choice;
12 while (fQuit == false)
13 {cout << "(0)Quit (1)Change Values (2)Square (3)Cube (4)Swap:";
14 cin >> choice;
15 switch (choice){
16 case 1:
17 PrintVals(valOne, valTwo);
18 Getvals(valOne, valTwo);
19 PrintVals(valOne, valTwo); break;
20 case 2:
21 PrintVals(valOne, valTwo);
22 Square(valOne, valTwo);
23 PrintVals(valOne, valTwo); break;
24 case 3:
25 PrintVals(valOne, valTwo);
26 Cube(valOne, valTwo);
27 PrintVals(valOne, valTwo); break;
28 case 4:
29 PrintVals(valOne, valTwo);
30 Swap(valOne, valTwo);
31 PrintVals(valOne, valTwo); break;
32 default: fQuit = true; break;}
33 if (fQuit) break;}
34 return 0;}
35 void PrintVals(int x, int y)
36 {cout << "x: " << x << " y: " << y << endl;}
37 void Square (int& rX, int& rY)
38 {rX *= rX; rY *= rY;}
39 void Cube (int& rX, int& rY)
40 {int tmp;
41 tmp = rX; rX *= rX; rX = rX * tmp;

234
42 tmp = rY; rY*=rY; rY = rY * tmp;}
43 void Swap(int& rX, int& rY)
44 {int temp;
45 temp = rX; rX = rY; rY = temp;}
46 void Getvals(int& rValOne, int& rValTwo)
47 {cout << "New value for ValOne: "; cin >> rValOne;
48 cout << "New value for ValTwo: "; cin >> rValTwo;}
Natija:
(0)Quit (1)Change Values (2)Square (3)Cube (4)Swap: 1
x: 1 y: 2
New value for Val0ne: 2
New value for ValTwo: 3
x: 2 y: 3
(0)Quit (1)Change Values (2)Square (3)Cube (4)Swap: 3
x: 2 y: 3
?: 8 y: 27
(0)Quit (1)Change Values (2)Square (3)Cube (4)Swap: 2
x: 8 y: 27
?: 64 y: 729
(0)Quit (1)Change Values (2)Square (3)Cube (4)Swap: 4
x: 64 y: 729
? : 729 y: 64
(0)Quit (1)Change Values (2)Square (3)Cube (4)Swap: 0
FUNKSIYANI CHAQIRISH UCHUN SO'RALGAN
VARIANT
Funksiya uchun ko'rsatgichning nomi funksiyaning o'zi nomini
umuman takrorlamasligi kerak, garchi siz buni qilishga haqlisiz.
Masalan, pFunc butun son qiymatini qabul qiladigan va Long turidagi
o'zgaruvchini qaytaradigan funksiyaga ko'rsatgich bo'lsin va bu
funksiyaning nomi pFunc bo'lsin. Sizda ikkita murojaatdan birini
chaqirish imkoniyati mavjud:
pFunc(x);
yoki
(*pFunc) (x);
Ikkala ifoda ham bir xil natijaga olib keladi. Birinchi ifoda qisqaroq
bo‘lsada, ikkinchisi dasturga ko'proq moslashuvchanlikni beradi.
Xuddi shu funksiyaning takroriy murojaatlari orqali kod hajmini
oshirish dasturning o'qilishini yomonlashtiradi. Ushbu parametr
funksiyalar uchun ko'rsatgichlardan foydalanish samaradorligini
ko'rsatish uchun maxsus berilgan. Haqiqiy sharoitda funksiya
ko'rsatgichlarini qo'llashning afzalliklari yanada ravshanroq, chunki
ular kodning takrorlanishini yo'q qilishga imkon beradi va dasturni
yanada aniqroq qiladi. Masalan, funksiya ko'rsatgichlari mavjud

235
vaziyatga qarab bitta qatorga to'planishi va undan funksiyalarni
chaqirishi mumkin.
FUNKSIYA KO'RSATGICHLARI MASSIVLARI
Butun son ko'rsatgichlari qatorini e'lon qilishga o'xshab, ma'lum bir
turdagi qiymatlarni qaytaradigan ma'lum bir imzoga ega bo'lgan
funksiyalar uchun ko'rsatgichlar qatorini e'lon qilish mumkin. Listing
18.8-bu listing 18.7 dasturining yana bir variantidir, unda
funksiyalarning barcha ko'rsatkichlari bir qatorga birlashtirilgan.
Listing. 18.8. Funktsiya ko'rsatgichlari qatoridan foydalanish
1 #include <iostream>
2 using namespace std;
3 void Square (int&, int&);
4 void Cube (int&, int&);
5 void Swap (int&, int &);
6 void GetVals(int&, int&);
7 void PrintVals(int, int);
8 int main()
9 {int valOne=1, valTwo=2;
10 int choice, i;
11 const int MaxArray = 5;
12 void (*pFuncArray[MaxArray])(int&, int&);
13 for (i=0; i<MaxArray; i++)
14 {cout << "(1)Change Values (2)Square (3)Cube (4)Swap: ";
15 cin >> choice;
16 switch (choice)
17 {case 1:pFuncArray[i] = GetVals; break;
18 case 2:pFuncArray[i] = Square; break;
19 case 3:pFuncArray[i] = Cube; break;
20 case 4:pFuncArray[i] = Swap; break;
21 default:pFuncArray[i] = 0;}}
22 for (i=0; i<MaxArray; i++)
23 {if ( pFuncArray[i] == 0 ) continue;
24 pFuncArray[i](valOne, valTwo);
25 PrintVals(valOne, valTwo);}
26 return 0;}
27 void PrintVals(int x, int y)
28 {cout << "x: " << x << " y: " << y << endl;}
29 void Square (int & rX, int & rY)
30 {rX *= rX; rY *= rY;}
31 void Cube (int & rX, int & rY)
32 {int tmp;
33 tmp = rX; rX *= rX; rX = rX * tmp;
34 tmp = rY; rY *= rY; rY = rY * tmp;}
35 void Swap(int & rX, int & rY)
36 {int temp;
37 temp = rX; rX = rY; rY = temp;}
38 void GetVals (int & rValOne, int & rValTwo)

236
39 {cout << "New value for ValOne: "; cin >> rValOne;
40 cout << "New value for ValTwo: "; cin >> rValTwo;}
Natija:
(1)Change Values (2)Square (3)Cube (4)Swap: 1
(1)Change Values (2)Square (3)Cube (4)Swap: 2
(1)Change Values (2)Square (3)Cube (4)Swap: 3
(1)Change Values (2)Square (3)Cube (4)Swap: 4
(1)Change Values (2)Square (3)Cube (4)Swap: 2
New Value for Val0ne: 2
New Value for ValTwo: 3
x: 2 y: 3
x: 4 y: 9
x: 64 y: 729
x: 729 y: 64
x: 531441 y: 4096
FUNKSIYA KO'RSATGICHLARINI BOSHQA
FUNKSIYALARGA O'TKAZISH
Funksiya ko'rsatgichlari (yoki ko'rsatgich massivlari) kerakli
funksiya ko'rsatgichi yordamida ularga murojaat qilish uchun boshqa
funksiyalarga o'tkazilishi mumkin. 18.7 Listingi tanlangan funksiyaga
ko'rsatgichni boshqa funksiyaga o'tkazish orqali yaxshilanishi mumkin
(main () dan tashqari), bu asl qiymatlarni chop etish uchun chiqaradi,
funksiyani chaqiradi va o'zgartirilgan qiymatlarni qayta chop etadi.
Void (+)(int&, int&) loyihalashi juda katta. Uni soddalashtirish
uchun siz voidni qaytaradigan va int tipidagi qiymatlarga ikkita
havolani qabul qiladigan funksiyalarga ko'rsatgichlarning yangi turini
(uni VPF deb ataymiz) e'lon qilish orqali typedef kalit so'zidan
foydalanishingiz mumkin.
Hozirgacha yaratilgan barcha funksiyalar ko'rsatkichlari biror bir
sinfga tegishli bo'lmagan umumiy funksiyalar uchun ishlatilgan. Shu
bilan birga, sinflarga (usullarga) a'zo bo'lgan funksiyalar uchun
ko'rsatkichlar yaratishga ruxsat beriladi.
Bunday ko'rsatgichni yaratish uchun oddiy funksiyaga ko'rsatgich
bilan bir xil sintaksis ishlatiladi, lekin sinf nomi va qamrov doirasi
operatori (::) qo'shiladi.
Shunday qilib, pFunc ko'rsatgichini ikkita butun parametrini qabul
qiladigan va voidni qaytaradigan Shape sinfining a'zo funksiyalariga
e'lon qilish quyidagicha:
void (Shape::*pFunc) (int,int);
A'zo funksiyalari ko'rsatkichlari ilgari ko'rib chiqilgan oddiy
funksiyalar ko'rsatkichlari bilan bir xil tarzda qo'llaniladi. Faqatgina
237
farq shundaki, funksiyani chaqirish uchun funksiyalar chaqiriladigan
tegishli sinf obyekti bo‘lishi kerak. Listing 18.11 sinf usuli uchun
ko'rsatgichdan foydalanishni ko'rsatadi.
A'ZO FUNKSIYALARI UCHUN KO'RSATGICH
MASSIVLARI
Oddiy funksiyalar belgilariga o'xshab, a'zo funksiyalar
ko'rsatkichlari massivda saqlanishi mumkin. Bunday massivni ishga
tushirish uchun siz turli xil a'zo funksiyalarning manzillaridan
foydalanishingiz mumkin.
Tavsiya etiladi!
 Sinf obyektlarida usullarni chaqirish uchun a'zo
funksiyalaridagi ko'rsatgichlardan foydalaning.
 A'zo funksiyasiga ko'rsatgichni e'lon qilishni osonlashtirish
uchun typedef-dan foydalaning.
Tavsiya etilmaydi!
 Agar siz ularsiz qila olsangiz, a'zo funksiyalari uchun belgilar
yaratishni suiste'mol qilmang.
Nazorat savollari va topshiriqlar:
1. Statik a'zo o'zgaruvchilar yopiq bo‘lishi mumkinmi?
2. Statik a'zo o'zgaruvchini e'lon qiling.
3. Statik funksiyani e'lon qiling.
4. Int tipidagi parametrni qabul qiladigan va Long turidagi qiymatni
qaytaradigan funksiyaga ko'rsatgichni e'lon qiling.
5. 4-topshiriqda yaratilgan ko'rsatgichni Car sinfining a'zo funksiyasi
uchun ko'rsatgichga o'zgartiring.
6. 5-topshiriqda yaratilgan o'nta ko'rsatgich qatorini e'lon qiling.
7. Bitta oddiy a'zo o'zgaruvchisi va bitta statik a'zo o'zgaruvchisi
bo'lgan sinfni e'lon qiladigan qisqa dastur yozing. A'zo o'zgaruvchini
ishga tushiradigan va statik a'zo o'zgaruvchini ko'paytiradigan
konstruktor yarating. Keyin statik o'zgaruvchining qiymatini bittaga
kamaytiradigan destruktorni tavsiflang.
8. 7-mashq dasturini statik a'zo o'zgaruvchiga statik a'zo funksiyasi
orqali kirish uchun o'zgartiring. Statik atama o'zgaruvchisini yopiq
qiling.
9. Statik bo'lmagan a'zo o'zgaruvchining qiymatiga kirish uchun 9-
mashq dasturida a'zo funksiyasi uchun ko'rsatgich yarating va undan
ushbu qiymatlarni chop etish uchun foydalaning.

238
19-MAVZU. OPERATORLARNI QAYTA ANIQLASH.
 A'zo funksiyalarini qo‘shimcha yuklash
 Operatorlarni qo‘shimcha yuklash
 O'zgaruvchilar uchun dinamik xotira ajratish bilan sinflarni
saqlash uchun funksiyalarni yaratish

QO‘SHIMCHA YUKLANGAN A'ZO FUNKSIYALARI


- bu bitta nom ostida ikki yoki undan ortiq
funksiyalarni e'lon qilishni anglatadi, ammo turli xil parametrlarga ega.
Sinf a'zolari funksiyalari xuddi shu tarzda qo‘shimcha yuklanishi
mumkin.
Rectangle sinfida (Listing 19.1) ikkita DrawShape () funksiyasi
e'lon qilinadi. Parametrlar Listingini o'z ichiga olmaydigan birinchisi,
joriy sinf qiymatlari asosida to'rtburchakni chizadi. Ikkinchisi ikkita
qiymatni oladi - kenglik va uzunlik - va ularga muvofiq, sinfning joriy
qiymatlarini e'tiborsiz qoldirib, to'rtburchak hosil qiladi.
Listing 19.1. A'zo funksiyalarining haddan tashqari yuklanishi
1 #include <iostream>
2 using namespace std;
3 class Rectangle
4 {public:
5 Rectangle(int width, int height);
6 ~Rectangle(){}
7 void DrawShape() const;
8 void DrawShape(int aWidth, int aHeight) const;
9 private:
10 int itsWidth; int itsHeight;
11 };
12 Rectangle::Rectangle(int width, int height)
13 {itsWidth=width; itsHeight=height; }
14 void Rectangle::DrawShape() const
15 {DrawShape(itsWidth, itsHeight); }
16 void Rectangle::DrawShape(int width, int height) const
17 {for(int i=0; i<height; i++) {
18 for(int j=0; j<width; j++)
19 {cout<<"*";}
20 cout<<"\n"; } }
21 int main(){
22 Rectangle theRect(30,5);
23 cout<<"DrawShape():\n";
24 theRect.DrawShape();
25 cout<<"\nDrawShape(40,2):\n";
26 theRect.DrawShape(40,2);
27 return 0;}

239
Natija:
DrawShape():
******************************
******************************
******************************
******************************
******************************
DrawShape(40,2):
****************************************
****************************************
STANDART QIYMATLARDAN FOYDALANISH
Sinfning a'zo funksiyalari, odatdagi funksiyalar kabi, sukut
bo'yicha berilgan qiymatlardan foydalanishi mumkin. Standart
argumentlar bilan a'zo funksiyalarni e'lon qilishda, Listing 19.2 da
ko'rsatilgandek, sizga tanish bo'lgan sintaksis ishlatiladi.
19.1 va 19.2 Listinglari bir xil vazifalarni bajaradi, ammo Listing
19.1 dagi qo‘shimcha yuklangan funksiyalardan foydalanish dasturni
yanada o'qilishini soddalashtiradi.
Listing 19.2.
#include <iostream>
using namespace std;
class Rectangle
{ public:
Rectangle(int width, int height);
~Rectangle(){}
void DrawShape
(int aWidth, int aHeight, bool UseCurrentVals = false) const;
private:
int itsWidth;
int itsHeight;};
Rectangle::Rectangle(int width, int height):
itsWidth(width),
itsHeight(height){}
void Rectangle::DrawShape(
int width,
int height,
bool UseCurrentValue )const{
int printWidth;
int printHeight;
if (UseCurrentValue == true)
{printWidth = itsWidth;
printHeight = itsHeight;}
else
{printWidth = width;
printHeight = height;}
for (int i = 0; i<printHeight; i++){
for (int j = 0; j< printWidth; j++)

240
{cout <<"*";}
cout << "\n";}}
int main(){
Rectangle theRect(30,5);
cout << "DrawShape(0,0, true)...\n";
theRect.DrawShape(0,0, true);
cout <<"DrawShape(40,2)...\n";
theRect.DrawShape(40,2);
return 0;}
Natija:
DrawShape():
******************************
******************************
******************************
******************************
******************************
DrawShape(40,2):
****************************************
****************************************
Dasturda qay biri ishlatishini qanday hal qilish kerak – qo‘shimcha
yuklangan funksiyalar yoki standart qiymatlar? Quyidagi qoidalarga
e'tibor bering. Qo‘shimcha yuklangan funksiyalardan foydalanish
afzalroqdir, agar:
1) dasturda vaziyatga qarab turli xil algoritmlardan foydalanish
kerak;
2) funksiyaga uzatiladigan qiymatlar turini o'zgartirish
imkoniyatiga ega bo‘lish kerak.

KONSTRUKTOR
Agar sinf konstruktori aniq e'lon qilinmasa, standart konstruktor
ishlatilishini bilib oldingiz, u parametrlarni o'z ichiga olmaydi va
dasturda o'zini namoyon qilmaydi. Sukut bo'yicha ishlatiladigan
maxsus konstruktorni yaratish qiyin emas, u ham hech qanday
parametrlarni qabul qilmaydi, lekin sinf obyektlarini yaratishni
boshqarishga imkon beradi.
Kompilyator tomonidan taqdim etilgan konstruktor sukut bo'yicha
berilgan deb nomlanadi. Shu bilan birga, standart konstruktor
parametrlarni o'z ichiga olmaydigan har qanday boshqa sinf
konstruktori deb ham ataladi. Bu g'alati tuyulishi mumkin, ammo
vaziyatga ushbu loyihalarni amalda qo'llash nuqtai nazaridan
qarasangiz, vaziyat yanada aniqroq bo'ladi.

241
E'tibor bering, agar dasturda biror bir konstruktor yaratilgan bo'lsa,
unda kompilyator o'zining standart konstruktorini taklif qilmaydi.
Shuning uchun, agar sizga parametrlarsiz konstruktor kerak bo'lsa va
dasturda bitta konstruktor yaratilgan bo'lsa, unda standart konstruktorni
o'zingiz yaratishingiz kerak bo'ladi.
KONSTRUKTORLARNING QO‘SHIMCHA YUKLANISHI
Konstruktor obyektni yaratish uchun mo'ljallangan. Masalan,
to'rtburchaklar konstruktorining maqsadi to'rtburchaklar obyektini
yaratishdir. Konstruktorni ishga tushirishdan oldin dasturda
to'rtburchak yo'q. Faqat u uchun ajratilgan xotira maydoni mavjud.
Konstruktor tugagandan so'ng dasturda foydalanishga tayyor obyekt
paydo bo'ladi.
Konstruktorlar, boshqa barcha funksiyalar kabi, qo‘shimcha
yuklanishi mumkin. Loyihalalarning qo‘shimcha yuklanishi dasturning
samaradorligi va moslashuvchanligini oshirishning kuchli vositasidir.
Masalan, biz ko'rib chiqayotgan to'rtburchaklar obyektida ikkita
konstruktor bo‘lishi mumkin. Birinchisi to'rtburchakning kengligi va
uzunligini belgilaydi, ikkinchisi parametrlarga ega emas va
o'lchamlarni o'rnatish uchun standart qiymatlardan foydalanadi. Ushbu
g'oya Listing 19.3 da amalga oshiriladi.
Listing 19.3. Konstruktorning qo‘shimcha yuklanishi
#include <iostream>
using namespace std;
class Rectangle
{ public:
Rectangle();
Rectangle(int width, int length);
~Rectangle() {}
int GetWidth() const { return itsWidth; }
int GetLength() const { return itsLength; }
private:
int itsWidth;
int itsLength;
};
Rectangle:: Rectangle()
{itsWidth = 5;
itsLength = 10;}
Rectangle::Rectangle (int width, int length)
{itsWidth = width;
itsLength = length;}
int main(){
Rectangle Rect1;
cout << "Rect1 width: " << Rect1.GetWidth() << endl;
cout << "Rect1 length: " << Rect1.GetLength() << endl;
242
int aWidth, aLength;
cout << "Enter a width: "; cin >> aWidth;
cout << "\nEnter a length: "; cin >> aLength;
Rectangle Rect2(aWidth, aLength);
cout << "\nRect2 width: " << Rect2.GetWidth() << endl;
cout << "Rect2 length: " << Rect2.GetLength() << endl;
return 0;}

Natija:
Rect1 width: 5
Rect1 length: 10
Enter a width: 20
Enter a length: 50
Rect2 width: 20
Rect2 length: 50
OBYEKTLARNI ISHGA TUSHIRISH
Hozirgacha obyektlarning a'zo o'zgaruvchilari to'g'ridan-to'g'ri
konstruktor tanasida o'rnatildi. Konstruktorning bajarilishi ikki
bosqichda amalga oshiriladi: konstruktor tanasini ishga tushirish va
bajarish.
Ko'pgina o'zgaruvchilar ushbu bosqichlarning har birida berilishi
mumkin: boshlang'ich paytida ham, konstruktorning ish vaqtida ham.
Ammo konstruktorni ishga tushirish paytida a'zo o'zgaruvchilarni ishga
tushirish mantiqan to'g'ri va ko'pincha samaraliroq. Quyidagi misol a'zo
o'zgaruvchilarni ishga tushirishni ko'rsatadi:
CAT():// konstruktor nomi va parametrlar Listingi
itsAge(5),// Listingni ishga tushirish
itsWeigth(8)
{ } // konstruktor tanasi
Konstruktor parametrlari Listingini yopish uchun qavsdan keyin
figurali qavs qo'yiladi. Keyin a'zo o'zgaruvchilarning nomlari sanab
o'tiladi. Ushbu o'zgaruvchini ishga tushirish uchun o'zgaruvchi
nomidan so‘ng bir juft qavs ishlatiladi. Agar bir vaqtning o'zida bir
nechta o'zgaruvchilar ishga tushirilsa, ular vergul bilan ajratilishi kerak.
Listing 19.4 Listing 19.3 dan olingan o'zgaruvchan konstruktorlarning
ishga tushirilishini ko'rsatadi. Ushbu misolda o'zgaruvchilarni ishga
tushirish konstruktor tanasida ularga qiymatlarni berish o'rniga
ishlatiladi.
Listing 19.4. Dastur kodining bir qismi bilan
1 Rectangle:: Rectangle():
2 itsWidth(5),

243
3 itsLength(10)
4 {}
5 Rectangle::Rectangle (int width, int length):
6 itsWidth(width),
7 itsLength(length)
8 {}
KONSTRUKTOR-NUSXA KO'CHIRUVCHI
Konstruktor va destruktordan tashqari kompilyator sukut bo'yicha
obyektning nusxasini yaratish kerak bo'lganda chaqiriladigan nusxa
ko'chiruvchi konstruktorni ham taqdim etadi.
Obyekt funksiyaga yoki funksiyadan qaytish sifatida qiymat
sifatida uzatilganda, uning vaqtinchalik nusxasi doimo yaratiladi.
Barcha nusxa ko'chiruvchilar faqat bitta parametrni qabul qilishadi.
Ushbu havolani o‘zgarmas qilish kerak, chunki konstruktor unga
uzatiladigan obyektni o'zgartirmasligi kerak. Masalan:
CAT(const CAT & theCat);
Bunday holda, CAT konstruktori sat sinf obyektiga o‘zgarmas
havolani oladi. Nusxa ko'chirish loyihalaridan foydalanishning maqsadi
theCat obyektining nusxasini yaratishdir.
Standart kompilyator tomonidan berilgan nusxa ko'chiruvchi
parametrda ko'rsatilgan obyektdan barcha a'zo o'zgaruvchilarni yangi
obyektning a'zo o'zgaruvchilariga ko'chiradi.
Masalan, CAT sinfida theCat a'zosi o'zgaruvchisi mavjud bo'lib, u
ba'zi bir butun qiymati saqlanadigan dinamik xotira sohasidagi
katakchani ko'rsatadi. Standart nusxa ko'chiruvchi theCat
o'zgaruvchisini eski CAT sinfidan yangi CAT sinfidagi theCat
o'zgaruvchisiga ko'chiradi. Bunday holda, ikkala obyekt ham bir xil
xotira katakchasiga ishora qiladi (19.1-rasm).

19.1-rasm. Standart nusxa ko'chiruvchidan foydalanish


Destruktorning maqsadi xotirani keraksiz narsalardan tozalashdir.
Agar asl CAT sinfining destruktori xotira katakchalarini tozalasa va
yangi CAT sinfining obyektlari hali ham ushbu katakchalarga murojaat

244
qilsa, unda dasturiy ta'minot ustida xavf paydo bo'ladi. Ushbu muammo
19.2-rasmda keltirilgan.

19.2-rasm. Noto'g'ri ko'rsatgichning paydo bo‘lishi


Listing 19.5. Nusxa ko'chirish konstruktori
1 #include<iostream>
2 using namespace std;
3 class CAT{
4 public:
5 CAT();
6 CAT(const CAT &);
7 ~CAT();
8 int GetAge() const { return *itsAge; }
9 int GetWeight() const {return *itsWeight; }
10 void SetAge(int age) { *itsAge = age; }
11 private:
12 int *itsAge;
13 int *itsWeight;};
14 CAT::CAT()
15 {itsAge = new int;
16 itsWeight = new int;
17 *itsAge = 5;
18 *itsWeight = 9;}
19 CAT::CAT(const CAT & rhs)
20 {itsAge = new int;
21 itsWeight = new int;
22 *itsAge = rhs.GetAge();
23 *itsWeight = *(rhs.itsWeight); }
24 CAT:: ~CAT()
25 {delete itsAge; itsAge = 0;
26 delete itsWeight; itsWeight = 0;}
27 int main(){
28 CAT frisky;
29 cout << "frisky's age:"<<frisky.GetAge() << endl;
30 cout << "Setting frisky to 6...\n";
31 frisky. SetAge(6);
32 cout << "Creating boots from frisky\n";
33 CAT boots(frisky);
34 cout << "frisky's age: " << frisky.GetAge() << endl;
35 cout << "boots' age: " << boots.GetAge() << endl;
36 cout << "setting frisky to 7...\n";

245
37 frisky. SetAge(7);
38 cout << "frisky's age: " << frisky.GetAge() << endl;
39 cout << "boot's age: " << boots.GetAge() << endl;
40 return 0;}

Natija:
frisky's age: 5
Setting frisky to 6…
Creating boots from frisky
frisky's age: 6
boots' age: 6
setting frisky to 7…
frisky's age: 7
boots' age: 6
OPERATORLARNING QO‘SHIMCHA YUKLANISHI
C++ tilida int, char va boshqalarni o'z ichiga olgan bir qator
o'rnatilgan ma'lumotlar tiplari mavjud. Operatorlarni qo‘shimcha
yuklash tartibini batafsil ko'rib chiqish uchun Listing 19.6 da yangi
Counter sinfi yaratiladi.
Listing 19.6. Counter sinfi
1 #include <iostream>
2 using namespace std;
3 class Counter{
4 public:
5 Counter();
6 ~Counter(){ }
7 int GetItsVal()const { return itsVal; }
8 void SetItsVal(int x) { itsVal = x; }
9 private:
10 int itsVal;};
11 Counter::Counter():
12 itsVal(0){}
13 int main(){
14 Counter i;
15 cout << "The value of i is " << i.GetItsVal() << endl;
16 return 0;}
Natija:
The value of i is 0
Yuqorida aytib o'tilgan yangi sinf obyektidan foydalanish
cheklovlarini operatorlarni qo‘shimcha yuklash orqali bartaraf etish
mumkin. Ulardan biri funksiyani qo‘shimcha yuklash Listing 19.7 da
ko'rsatilgan.
Listing 19.7. Qo'shimcha operator sinfiga qo'shish
1 #include <iostream>
2 using namespace std;

246
3 class Counter{
4 public:
5 Counter();
6 ~Counter(){ }
7 int GetItsVal()const { return itsVal; }
8 void SetItsVal(int x) { itsVal = x;}
9 void Increment() { ++itsVal; }
10 private:
11 int itsVal;};
12 Counter::Counter():
13 itsVal(0) {}
14 int main()
15 {Counter i;
16 cout << "The value of i is " << i.GetItsVal() << endl;
17 i.Increment();
18 cout << "The value of i is " << i.GetItsVal() << endl;
19 return 0;}
Natija:
The value of i is 0
The value of i is 1
PREFIKS OPERATORLARINING QO‘SHIMCHA
YUKLANISHI
Prefiks operatorini ortiqcha yuklash uchun siz quyidagi turdagi
funksiyadan foydalanishingiz mumkin:
returnType Operator op (parametrlar)
Bunday holda, qo‘shimcha yuklangan operatordir.
void operator++ ()
Ushbu usul Listing 19.8 da ko'rsatilgan.
Listing 19.8. Preincrement operatori
1 #include <iostream>
2 using namespace std;
3 class Counter{
4 public:
5 Counter();
6 ~Counter(){}
7 int GetItsVal()const { return itsVal; }
8 void SetItsVal(int x) { itsVal = x; }
9 void Increment() { ++itsVal; }
10 void operator++ () {++itsVal; }
11 private:
12 int itsVal;};
13 Counter::Counter():
14 itsVal(0) {}
15 int main(){
16 Counter i;
17 cout << "The value of i is " << i.GetItsVal() << endl;
18 i.Increment();

247
19 cout << "The value of i is " << i.GetItsVal() << endl;
20 ++i;
21 cout << "The value of i is " << i.GetItsVal() << endl;
22 return 0;}
Natija:
The value of i is 0
The value of i is 1
The value of i is 2
Listing 19.9. Vaqtinchalik obyektning qaytishi
1 #include <iostream>
2 using namespace std;
3 class Counter
4 { public:
5 Counter();
6 ~Counter(){}
7 int GetItsVal()const { return itsVal; }
8 void SetItsVal(int x) { itsVal = x; }
9 void Increment() { ++itsVal; }
10 Counter operator++ ();
11 private:
12 int itsVal;
13 };
14 Counter::Counter():
15 itsVal(0){}
16 Counter Counter::operator++()
17 {++itsVal;
18 Counter temp;
19 temp. SetItsVal(itsVal);
20 return temp;}
21 int main()
22 {Counter i;
23 cout << "The value of i is " << i.GetItsVal() << endl;
24 i.Increment();
25 cout << "The value of i is " << i.GetItsVal() << endl;
26 ++i;
27 cout << "The value of i is " << i.GetItsVal() << endl;
28 Counter a = ++i;
29 cout << "The value of a: " << a.GetItsVal();
30 cout << " and i: " << i.GetItsVal() << endl;
31 return 0;}
Natija:
The value of i is 0
The value of i is 1
The value of i is 2
The value of a: 3 and i: 3
Agar Counter sinfida qiymatni qabul qiluvchi konstruktor bo'lsa,
unda ushbu konstruktorning parametrlari shunchaki o'sish

248
operatorining qaytish qiymatini qaytarishi mumkin. Ushbu g'oya
Listing 19.10 da amalga oshiriladi.
Listing 19.10. Mavhum vaqtinchalik obyektning qaytishi
1 #include <iostream>
2 using namespace std;
3 class Counter
4 { public:
5 Counter();
6 ~Counter(){}
7 int GetItsVal()const { return itsVal; }
8 void SetItsVal(int x) { itsVal = x; }
9 void Increment() { ++itsVal; }
10 Counter operator++ ();
11 private:
12 int itsVal;
13 };
14 Counter::Counter():
15 itsVal(0){}
16 Counter Counter::operator++()
17 {++itsVal;
18 Counter temp;
19 temp. SetItsVal(itsVal);
20 return temp;}
21 int main()
22 {Counter i;
23 cout << "The value of i is " << i.GetItsVal() << endl;
24 i.Increment();
25 cout << "The value of i is " << i.GetItsVal() << endl;
26 ++i;
27 cout << "The value of i is " << i.GetItsVal() << endl;
28 Counter a = ++i;
29 cout << "The value of a: " << a.GetItsVal();
30 cout << " and i: " << i.GetItsVal() << endl;
31 return 0;}
Natija:
The value of i is 0
The value of i is 1
The value of i is 2
The value of a: 3 and i: 3

249
PREINCREMENT VA POSTINCREMENT O'RTASIDAGI
FARQLAR
Postincrement operatorini ortiqcha yuklashni boshlashdan oldin,
uning preincrement operatoridan qanday farq qilishini aniq
tushunishingiz kerak.
Xuddi shunday, bizning misolimizda preincrement operatori
qiymatni oshiradi, shundan so'ng u obyektni qaytaradi va postincrement
operatori obyektni asl qiymati bilan qaytaradi.
Keling, barchasini yana takrorlaymiz. Quyidagi ifodaga qarang:
a = x++;
Agar dastlab x o'zgaruvchisi 5 ga teng bo'lsa, unda a
o'zgaruvchisining ushbu ifodasida 5 qiymati beriladi, ammo x
o'zgaruvchisi 6 ga teng bo'ladi. Agar x shunchaki o'zgaruvchi emas,
balki obyekt bo'lsa, unda uning postinkrement operatori vaqtinchalik
obyektda 5 ning asl qiymatini saqlab qolishi, x obyektining qiymatini 6
ga oshirishi, so'ngra vaqtinchalik obyektning qiymatini qaytarishi va
uni a obyektiga o‘zlashtirishi kerak.
E'tibor bering, biz vaqtinchalik obyekt haqida gapirayotganimiz
sababli, uni havola sifatida emas, balki qiymat sifatida qaytarish kerak,
chunki vaqtinchalik obyekt funksiyaning qiymatini qaytarishi bilanoq
doiradan chiqib ketadi.
Qo‘shicha yuklangan operatorlarni e'lon qilish funksiyalar bilan bir
xil tarzda amalga oshiriladi. Orerator kalit so'zidan keyin qo‘shimcha
yuklangan operatorning o'zidan foydalaning.
Keling, Counter obyekti argument sifatida ishlaydigan Add ()
funksiyasini yozishdan boshlaylik. Ushbu funksiya ikkita qiymatni
qo'shishi kerak, so'ngra olingan natija bilan qiymatni qaytaring. Ushbu
yondashuv 19.11 Listingida ko'rsatilgan.
Listing 19.11. Qo'shish () funksiyasi
1 #include <iostream>
2 using namespace std;
3 class Counter
4 {public:
5 Counter();
6 Counter(int initialValue);
7 ~Counter(){ }
8 int GetItsVal()const {return itsVal; }
9 void SetItsVal(int x) {itsVal = x;}
10 Counter Add(const Counter &);
11 private:

250
12 int itsVal;
13 };
14 Counter::Counter(int initialValue):
15 itsVal(initialValue){}
16 Counter::Counter():
17 itsVal(0){}
18 Counter Counter::Add(const Counter & rhs)
19 {return Counter(itsVal+ rhs. GetItsVal());}
20 int main(){
21 Counter varOne(2), varTwo(4), varThree;
22 varThree = varOne. Add(varTwo);
23 cout << "var0ne: " << varOne.GetItsVal()<< endl;
24 cout << "varTwo: " << varTwo.GetItsVal() << endl;
25 cout << "varThree: " << varThree.GetItsVal() << endl;
26 return 0;}
Natija:
varOne: 2
varTwo: 4
varThree: 6
IKKI OPERANDLI OPERATORLARNING
QO‘SHIIMCHA YUKLANISHI
Ikki operandli operatorlar bitta operandli operatorlar bilan bir xil
tarzda e'lon qilinadi, faqat ushbu operatorlarning funksiyalari
parametrlarni o'z ichiga oladi. Parametrlar bir xil tipdagi obyektlarga
o‘zgarmas havolalardir.
OPERATORLARNING HADDAN TASHQARI
YUKLANISHI
Siz standart ma'lumotlar turlarining operatorlarini (masalan, int)
ortiqcha yuklay olmaysiz. Shuningdek, operatorlarning belgilangan
ustuvorliklari va assotsiativligini o'zgartirish mumkin emas. Masalan,
bitta operandli operatorni ikkita operand bilan ishlatish uchun
qo‘shimcha yuklay olmaysiz.
Operator tomonidan boshqarilishi mumkin bo'lgan operandlar soni
har bir operatorning muhim xususiyatidir. Bitta operand bilan
ishlatiladigan operatorlar (masalan, inkrement operatori: myValue++)
va ishlashi uchun ikkita operand ko'rsatilishi kerak bo'lgan operatorlar
(masalan, qo‘shish operatori: a+b) o'rtasida farq bor. Bir vaqtning o'zida
faqat shartli operator uchta operandni boshqaradi, foydalanish sintaksisi
quyidagi misolda ko'rsatilgan: (a > b ? x : y).
Tavsiya etiladi!
 Agar dastur kodi bundan keyin aniqroq bo'lsa, operatorlarni
qo‘shimcha yuklang.

251
 Qo‘shimch yuklangan operatorlardan sinf obyektlarini
qaytaring.
O‘ZLASHTIRISH OPERATORI
To'rtinchi va oxirgi, obyektlar bilan ishlash uchun kompilyator
tomonidan taqdim etilgan funksiya, agar siz qo'shimcha funksiyalarni
o'rnatmagan bo'lsangiz, bu o‘zlashtirish operatori funksiyasi
(operator=()). Ushbu operator obyektga yangi qiymat berish kerak
bo'lganda ishlatiladi, masalan:
CAT catOne(5,7);
CAT catTwo(3,4);
// ... dasturning boshqa satrlari
catTwo = catOne;
Ushbu misolda catOne obyekti yaratilgan bo'lib, uning
o'zgaruvchisi itsage 5 ga, itsweigth o'zgaruvchisi esa 7 ga teng. Keyin
catTwo obyekti mos ravishda 3 va 4 o'zgaruvchilar qiymatlari bilan
yaratiladi.
Biroz vaqt o'tgach, catTwo obyektiga catOne obyekt qiymatlari
beriladi. Agar itsage o'zgaruvchisi ko'rsatgich bo'lsa va catTwo obyekt
o'zgaruvchilarining eski qiymatlari bilan nima sodir bo'ladi?
Dinamik xotira sohasida o'z qiymatlarini saqlaydigan a'zo
o'zgaruvchilar bilan ishlash avval nusxa ko'chirish konstruktoridan
foydalanishni muhokama qilishda ko'rib chiqilgan (shuningdek, rasmga
qarang. 19.1 va 19.2).
C++ da ma'lumotlarni yuzaki va chuqur nusxalash farqlanadi.
Yuzaki nusxalashda faqat manzil bir o'zgaruvchidan ikkinchisiga
o'tkaziladi, natijada ikkala obyekt ham bir xil xotira katakchalariga
ishora qiladi. Chuqur nusxa ko'chirishda o'zgaruvchilar qiymatlari
xotiraning bir maydonidan boshqasiga ko'chiriladi. Ushbu nusxalash
usullari o'rtasidagi farqlar 19.3-rasmda ko'rsatilgan.

19.3-rasm. Chuqur nusxalashga misol


252
Yuqorida aytilganlarning barchasi ma'lumotlarni o‘zlashtirish
uchun amal qiladi. O‘zlashtirish operatoridan foydalanganda
ma'lumotlar almashish jarayoni ba'zi xususiyatlar bilan davom etadi.
Shunday qilib, catTwo obyekti o'zgaruvchilari bilan birga mavjud
bo'lib, ularning har biri uchun ma'lum xotira katakchalari ajratilgan.
Obyektga yangi qiymatlar berilgan taqdirda, avval ushbu xotira
katakchalarini bo'shatish kerak:
catTwo = catTwo
Obyektni o'ziga o‘zlashtirish, xuddi shu obyektga murojaat qilgan
ko'rsatgichga bilvosita murojaat qilishda xato bo‘lishi mumkin.
Bunday vaziyatni oldini olish uchun sizning o‘zlashtirish
operatoringiz birinchi navbatda o‘zlashtirish operatorining har ikki
tomonidagi obyektlar bir-biriga mos kelmasligini aniqlashi kerak. Buni
Listing 19.12 da ko'rsatilgandek, bu ko'rsatkich yordamida amalga
oshirish mumkin.
Listing 19.12. O‘zlashtirish operatori
1 #include <iostream>
2 using namespace std;
3 class CAT
4 {public:
5 CAT();
6 int GetAge() const { return *itsAge; }
7 int GetWeight() const { return *itsWeight; }
8 void SetAge(int age) { *itsAge = age; }
9 CAT & operator=(const CAT &);
10 private:
11 int *itsAge;
12 int *itsWeight;
13 };
14 CAT::CAT()
15 {itsAge = new int;
16 itsWeight = new int;
17 *itsAge = 5;
18 *itsWeight = 9;}
19 CAT & CAT::operator=(const CAT & rhs)
20 {
21 if (this == &rhs)
22 return *this;
23 *itsAge = rhs.GetAge();
24 *itsWeight = rhs.GetWeight();
25 return *this;
26 }
27 int main()
28 {
29 CAT frisky;

253
30 cout << "frisky's age: " << frisky.GetAge() << endl;
31 cout << "Setting frisky to 6...\n";
32 frisky. SetAge(6);
33 CAT whiskers;
34 cout << "whiskers' age: " << whiskers.GetAge() << endl;
35 cout << "copying frisky to whiskers...\n";
36 whiskers = frisky;
37 cout << "whiskers' age: " << whiskers.GetAge() << endl;
38 return 0;}
Natija:
frisky's age: 5
Setting frisky to 6…
whiskers' age: 5
copying frisky to whiskers…
whiskers' age: 6
Nazorat savollari va toshiriqlar:
1. Agar siz a'zo funksiyasini qo‘shimcha yuklagan bo'lsangiz, keyinchalik
funksiyaning turli xil variantlarini qanday ajratish mumkin?
2. Nusxa ko'chirish konstruktori qachon chaqiriladi? This ko'rsatgich nima?
3. Destruktor qachon chaqiriladi?
4. Nusxa ko'chirish konstruktori va o‘zlashtirish operatori (=) o'rtasidagi
farq nima?
5. C++ da operator ++ ni sinfda o'chirish amalini bajaradigan tarzda
qo‘shimcha yuklashga ruxsat beriladimi?
6. Itsradius a'zosi bo'lgan bitta o'zgarish bilan SimpleCircle sinfining e'lonini
taqdim eting. Sinf sukut bo'yicha o'rnatilgan konstruktor va destruktordan,
shuningdek radiusni o'rnatish usulidan foydalanishi kerak.
7. 6-mashqda yaratilgan sinfdan foydalanib, standart konstruktor yordamida
itsradius o'zgaruvchisini 5 qiymati bilan ishga tushiring.
8. Itsradius o'zgaruvchisiga parametr qiymatini belgilaydigan sinfga yangi
konstruktor qo'shing.
9. SimpleCircleni itsradiusni dinamik xotira maydoniga saqlash va mavjud
usullarni yozib olish uchun o'zgartiring.
10. SimpleCircle sinfida nusxa ko'chiruvchi konstruktor yarating.
11. Xatolikni toping.
SQUARE SQUARE :: operator=(const SQUARE & rhs)
{ its Side = new int;
*itsSide = rgs. GetSide();
return *this;
}

254
20-MAVZU. VORISLIK.
 Meros
 Merosxo‘rlikdan foydalanish
 Virtual funksiyalar

C++ da obyektlar o'rtasidagi munosabatlarning mohiyatini


yaxshiroq ifodalash uchun iyerarxik meros tizimidan foydalanadi.
MEROS NIMA?
Har bir inson obyektga o'z nuqtai nazaridan qaraydi. Qirollik, tur,
sinf, tartib, oila, jins va tur. -bu umumiy xususiyatga mansub
munosabatlarining bir turi. Ushbu turdagi munosabatlarni hamma joyda
ko'rish mumkin. Yuk mashinasi-bu mashinalarning bir turi, mashina esa
o'z navbatida transport vositalarining bir turi. Keks-bu shirin
taomlarning bir turi, shirin taomlar esa ovqatning bir turi.
Shunday qilib, mashina transport vositalarining bir turi ekanligini
ta'kidlab, biz barcha turdagi transport vositalaridan (vagondan
samolyotgacha) faqat dvigatelli to'rt g'ildirakli qurilmalarni tanlaymiz.
IYERARXIYA VA MEROS

20.1-rasm. Sutemizuvchilar ierarxiyasi


C++ da iyerarxiya sinflar konsepsiyasida amalga oshiriladi, bu
yerda bitta sinf paydo bo‘lishi yoki yuqori darajadagi sinfdan meros
bo'lib o'tishi mumkin. Qoida tariqasida, bir nechta lotin sinflari asosiy
sinf bilan bog'liq. Itlar, mushuklar va otlar sutemizuvchilarning
vakillari bo'lganligi sababli, C++ nuqtai nazaridan, bu sinflarning
barchasi mammal sinfidan olingan deb aytish mumkin.
Sinflar merosining ma'nosini yanada aniqroq ochib berish uchun
ushbu mavzuni hayvonot dunyosining ko'plab vakillari o'rtasidagi

255
munosabatlar misolida ko'rib chiqing. Tasavvur qiling, dasturchi
"Farm" bolalar o'yinini yaratish uchun buyurtma oldi. Fermada
yashovchi hayvonlarni, shu gapdan otlar, sigirlar, itlar, mushuklar,
qo'ylar va boshqalarni yaratishni boshlaganingizda, siz ularning har bir
sinfini shunday usullar bilan ta'minlashingiz kerak bo'ladi.
SINF MEROS SINTAKSISI
Yangi lotin sinfini yaratish uchun kalit so'zidan foydalaniladi,
shundan so'ng yangi sinf nomi, figurali qavs, sinf prototipining tipi
(public yoki boshqa), so'ngra quyidagi misolda bo'lgani kabi asosiy sinf
nomi ko'rsatiladi:
class Dog : public Mammal
Mammal sinfidan Dog sinfining merosiga misol Listing 20.1 da
keltirilgan.
Listing 20.1. Oddiy meros
1 #include<iostream>
2 using namespace std;
3 enum BREED { GOLDEN, CAIRN, DANDIE, SHETLAND, DOBERMAN, LAB };
4 class Mammal
5{
6 public:
7 Mammal();
8 ~Mammal();
9 int GetAge()const;
10 void SetAge(int);
11 int GetWeight()const;
12 void SetWeight();
13 void Speak() const;
14 void Sleep() const;
15 protected:
16 int itsAge;
17 int itsWeight;
18 };
19
20 class Dog : public Mammal
21 {
22 public:
23 Dog();
24 ~Dog();
25 BREED GetBreed() const;
26 void SetBreed(BREED);
27 protected:
28 BREED itsBreed;
29 };
Natija:
Ushbu dastur ekranda hech narsani ko'rsatmaydi, chunki u hozircha
faqat e'lonlar va sinflarni o'rnatishni o'z ichiga oladi. Ushbu dastur hali
hech qanday funksiyani bajarmaydi.
256
PRIVATE VA PROTECTED
(YOPIQ YOKI HIMOYALANGAN)
Siz Listing 20.1 ning 15 va 27-qatorlarida yangi protected kalit
so'zdan foydalanilgan. Hozirgacha sinf ma'lumotlari private kalit so'z
bilan aniqlangan. Ammo private deb e'lon qilingan sinf a'zolari meros
uchun mavjud emas. Albatta, oldingi Listingda itsAge va itsWeight a'zo
o'zgaruvchilarini public sifatida aniqlash mumkin edi, chunki
dasturning boshqa barcha sinflari ushbu o'zgaruvchilarga to'g'ridan-
to'g'ri kirish huquqiga ega bo'lar edi.
Protected kalit so'z bilan aniqlangan himoyalangan ma'lumotlar
aynan shunday. Himoyalangan ma'lumotlar barcha meros sinflar uchun
mavjud, ammo barcha tashqi sinflar uchun mavjud emas.
Demak, uchta mavjud - public, protected va
private. Agar sinf obyektlari funksiyaga o'tkazilsa, u
bilan e'lon qilingan barcha a'zo o'zgaruvchilar va a'zo
funksiyalar ma'lumotlaridan foydalanishi mumkin. Sinf a'zosi
funksiyasi, shuningdek, ushbu sinfning barcha yopiq ma'lumotlarini
( deb e'lon qilingan) va ushbu sinfdan ishlab chiqarilgan boshqa
har qanday sinfning himoyalangan ma'lumotlarini ( deb e'lon
qilingan) ishlatishi mumkin.
Shunday qilib, bizning misolimizda Dog::WagTail() funksiyasi
Private itsBreed o'zgaruvchisining qiymatidan va himoyalangan deb
e'lon qilingan barcha Mammal sinf o'zgaruvchilaridan foydalanishi
mumkin.
Agar Dog sinfi Mammal sinfidan to'g'ridan-to'g'ri emas, balki ba'zi
bir oraliq sinfdan (masalan, DomesticAnimals) meros olingan bo'lsin.
Dog sinfi va barcha oraliq sinflar public deb e'lon qilingan bo'lsa,
Mammal sinfining himoyalangan ma'lumotlariga kirish saqlanib qoladi.
Listing 20.2 ushbu tipdagi barcha ma'lumotlar va funksiyalarga kirish
huquqiga ega bo'lgan Dog sinfida obyekt yaratishni ko'rsatadi.
Listing 20.2. Meros obyektlaridan foydalanish
1 #include<iostream>
2 using namespace std;
3 enum BREED { GOLDEN, CAIRN, DANDIE, SHETLAND, DOBERMAN,LAB};
4 class Mammal
5 { public:
6 Mammal():itsAge(2), itsWeight(5){ }
7 ~Mammal(){ }
8 int GetAge()const { return itsAge; }
9 void SetAge(int age) { itsAge = age; }

257
10 int GetWeight()const { return itsWeight; }
11 void SetWeight(int weight) { itsWeight = weight; }
12 void Speak()const { cout << "Mammal sound!\n"; }
13 void Sleep()const { cout << "shhh. I'm sleeping.\n";}
14 protected:
15 int itsAge;
16 int itsWeight; };
17 class Dog : public Mammal
18 {public:
19 Dog():itsBreed(GOLDEN){ }
20 ~Dog(){ }
21 BREED GetBreed() const { return itsBreed; }
22 void SetBreed(BREED breed) { itsBreed = breed; }
23 void WagTail() const { cout << "Tail wagging. . . \n"; }
24 void BegForFood() const { cout << "Begging for food. . . \n"; }
25 private:
26 BREED itsBreed;};
27 int main(){
28 Dog fido;
29 fido.Speak();
30 fido.WagTail();
31 cout << "Fido is " << fido.GetAge() << "years old\n";
32 return 0;}
Natija:
Mammal sound!
Tail wagging. . .
Fido is 2years old
KONSTRUKTORLAR VA DESTRUKTORLAR
Dog sinfidagi obyektlar bir vaqtning o'zida Mammal sinfidagi
obyektlardir. Dog sinfida fido obyekti yaratilganda, Mammal sinfidan
birinchi nomlangan asosiy konstruktor chaqiriladi. Keyin obyektni
yaratishni tugatadigan Dog sinf konstruktori chaqiriladi. Fido obyekti
hech qanday parametr bilan ta'minlanmaganligi sababli, ikkala holatda
ham sukut bo'yicha o'rnatilgan konstruktor chaqiriladi. Fido obyekti
mammal sinfi va Dog sinfining ikkala konstruktori yordamida to'liq
yaratilgunga qadar mavjud emas.
Fido obyektini kompyuter xotirasidan olib tashlaganingizda, avval
Dog class destruktori, so'ngra Mammal class destruktori chaqiriladi.
Har bir destruktor obyektning tegishli merosxo‘r yoki asosiy sinf
konstruktori tomonidan yaratilgan qismini olib tashlaydi.
Listing 20.3. Konstruktor va destruktorni chaqirish
1 #include<iostream>
2 using namespace std;
3 enum BREED { GOLDEN, CAIRN, DANDIE, SHETLAND, DOBERMAN,LAB};
4 class Mammal
5 { public:
6 Mammal();
7 ~Mammal();

258
8 int GetAge()const
9 { return itsAge; }
10 void SetAge(int age)
11 { itsAge = age; }
12 int GetWeight()const
13 { return itsWeight; }
14 void SetWeight(int weight)
15 { itsWeight = weight; }
16 void Speak()const
17 { cout << "Mammal sound!\n"; }
18 void Sleep()const
19 { cout << "shhh. I'm sleeping.\n";}
20 protected:
21 int itsAge;
22 int itsWeight; };
23 class Dog : public Mammal
24 {public:
25 Dog();
26 ~Dog();
27 BREED GetBreed() const
28 { return itsBreed; }
29 void SetBreed(BREED breed)
30 { itsBreed = breed; }
31 void WagTail() const
32 { cout << "Tail wagging. . . \n"; }
33 void BegForFood() const
34 { cout << "Begging for food. . . \n"; }
35 private:
36 BREED itsBreed;};
37 Mammal::Mammal():
38 itsAge(1),
39 itsWeight(5)
40 {cout << "Mammal constructor. . . \n";}
41 Mammal::~Mammal()
42 {cout << "Mammal destructor. . . \n";}
43 Dog::Dog():
44 itsBreed(GOLDEN)
45 {cout << "Dog constructor. . . \n ";}
46 Dog::~Dog()
47 {cout << "Dog destructor. . . \n"; }
48 int main()
49 {Dog fido;
50 fido.Speak();
51 fido.WagTail();
52 cout << "Fido is " << fido.GetAge() << "years old\n";
53 return 0;}
Natija:
Mammal constructor. . .
Dog constructor. . .
Mammal sound!
Tail wagging. . .
Fido is 1years old
Dog destructor. . .
Mammal destructor. . .

259
Aytaylik, siz Mammal va Dog sinflarida sukut bo'yicha o'rnatilgan
konstruktorlarni qo‘shimcha yuklashingiz kerak, shunda ulardan
birinchisi darhol yangi obyektga ma'lum bir yoshni o‘zlashtiradi.
Asosiy sinfni ishga tushirish uchun siz sinf nomini yozishingiz
kerak, so'ngra Listing 20.4 da ko'rsatilganidek, asosiy sinf parametrlarni
ko'rsatishingiz kerak.
Listing 20.4. Merosxo‘r sinflarda konstruktorlarning
qo‘shimcha yuklanishi.
1 #include <iostream>
2 using namespace std;
3 enum BREED { GOLDEN, CAIRN, DANDIE, SHETLAND, DOBERMAN,LAB};
4 class Mammal
5 {public:
6 Mammal();
7 Mammal(int age);
8 ~Mammal();
9 int GetAge() const { return itsAge; }
10 void SetAge(int age) { itsAge = age; }
11 int GetWeight() const { return itsWeight; }
12 void SetWeight(int weight) { itsWeight = weight; }
13 void Speak() const { cout << "Mammal sound!\n"; }
14 void Sleep() const { cout << "shhh. I'm sleeping.\n"; }
15 protected:
16 int itsAge;
17 int itsWeight;
18 };
19 class Dog : public Mammal
20 {public:
21 Dog();
22 Dog(int age);
23 Dog(int age, int weight);
24 Dog(int age, BREED breed);
25 Dog(int age, int weight, BREED breed);
26 ~Dog();
27 BREED GetBreed() const { return itsBreed; }
28 void SetBreed(BREED breed) { itsBreed = breed; }
29 void WagTail() const { cout << "Tail wagging\n"; }
30 void BegForFood() const { cout << "Begging for food\n"; }
31 private:
32 BREED itsBreed;
33 };
34 Mammal::Mammal():
35 itsAge(1),
36 itsWeight(5)
37 {cout << "Mammal constructor...\n";}
38 Mammal::Mammal(int age):
39 itsAge(age),
40 itsWeight(5)
41 { cout << "Mammal(int) constructor...\n";}
42 Mammal::~Mammal()
43 { cout << "Mammal destructor...\n";}
44 Dog:: Dog():

260
45 Mammal(),
46 itsBreed(GOLDEN)
47 { cout << "Dog constructor...\n"; }
48 Dog::Dog(int age):
49 Mammal(age),
50 itsBreed(GOLDEN)
51 { cout << "Dog(init) constructor...\n"; }
52 Dog::Dog(int age, int weight):
53 Mammal(age),
54 itsBreed(GOLDEN)
55 {itsWeight = weight;
56 cout << "Dog(int, int) constructor...\n"; }
57 Dog::Dog(int age, int weight, BREED breed):
58 Mammal(age),
59 itsBreed(breed)
60 {itsWeight = weight;
61 cout << "Dog(int, int, BREED) constructor...\n";}
62 Dog::Dog(int age, BREED breed):
63 Mammal(age),
64 itsBreed(breed)
65 {cout << "Dog(in, BREED) constructor...\n";}
66 Dog:: ~Dog()
67 {cout << "Dog destructor...\n";}
68 int main()
69 {
70 Dog fido;
71 Dog rover(5);
72 Dog buster(6,8);
73 Dog yorkie (3,GOLDEN);
74 Dog dobbie (4, 20, DOBERMAN);
75 fido. Speak();
76 rover.WagTail();
77 cout << "Yorkie is " << yorkie.GetAge() << " years old\n";
78 cout << "Dobbie weighs ";
79 cout << dobbie. GetWeight() << " pounds\n";
80 return 0;}
Natija:
Mammal constructor…
Dog constructor…
Mammal(int) constructor…
Dog(int) constructor…
Mammal(int) constructor…
Dog(int, int) constructor…
Mammal(int) constructor…
Dog(int, BREED) constructor…
Mammal(int) constructor…
Dog(int, int, BREED) constructor…
Mammal sound!
Tail wagging.
Yorkie is 3 years old.
Dobbie weighs 20 pounds.
Dog destructor…
Mammal destructor…
Dog destructor…
Mammal destructor…

261
Dog destructor…
Mammal destructor…
Dog destructor…
Mammal destructor…
Dog destructor…
Mammal destructor…

Listing 20.5 Mammal sinfida e'lon qilingan Speak ()


funksiyasining Dog sinfidagi o'rnini ko'rsatadi.
Listing 20.5. Merosxo‘r sinfda asosiy sinf usulini qo‘llash
1 #include <iostream>
2 using namespace std;
3 class Mammal
4 {public:
5 Mammal()
6 { cout<<"Mammal constructor...\n";}
7 ~Mammal()
8 { cout<<"mammal destructor...\n";}
9 void Speak() const
10 {cout<<"mammal sound \n";}
11 void Sleep()const
12 {cout<<"shhh. i'm sleeping' \n";}
13 protected:
14 int itAge;
15 int itWeight;};
16 class Dog: public Mammal
17 {public:
18 Dog()
19 {cout<<"dog constructor...\n";}
20 ~Dog()
21 {cout<<"dog dectructor...\n";}
22 void WagTail() const
23 { cout<<" Tail wagging...\n";}
24 void BegForFood() const
25 { cout<<" begging for food...\n";}
26 void Speak() const
27 { cout<<" woof!\n";}
28 private:};
29 int main()
30 {Mammal bigAnimal;
31 Dog fido;
32 bigAnimal.Speak();
33 fido.Speak();
34 return 0;}
Natija:
Mammal constructor. . .
Mammal constructor. . .
dog constructor. . .
mammal sound!

262
woof!
dog destructor. . .
mammal destructor. . .
mammal destructor. . .
Ushbu o'xshash yondashuvlar deyarli bir xil natijalarga olib keladi.
Oldingi misolda, Dog class obyektidan Speak() usuliga murojaat
qilganda, dastur asosiy sinfda Speak() usulini e'lon qilishda
ko'rsatilgandek bajarilmadi.. Agar mammal sinfida it sinfida
almashtirilgan Move () usuli mavjud bo'lsa, unda it sinfining Move()
usuli asosiy sinfda bir xil nomdagi usulni yashiradi deb aytish mumkin.
Biroq, ba'zi hollarda natija kutilmagan bo‘lishi ham mumkin.
Keling, vaziyatni murakkablashtiraylik. Mammal sinfida Move ()
usuli uch marta qo‘shimcha yuklangan deb taxmin qiling. Bir variantda
usul parametrlarni talab qilmaydi, ikkinchisida bitta butun parametri
(masofa), uchinchisida ikkita butun parametri (tezlik va masofa)
ishlatiladi. Dog sinfida parametrlarsiz Move() usuli almashtiriladi.
Shunga qaramay, Dog sinf obyektidan Mammal sinfining qo‘shimcha
yuklangan usulining boshqa ikkita variantiga murojaat qilishga urinish
muvaffaqiyatsiz bo'ladi. Muammoning mohiyati Listing 20.6 da ochib
berilgan.
Listing 20.6 Funksiyalarni yashirish
1 #include <iostream>
2 using namespace std;
3 class Mammal
4 {public:
5 void Move() const
6 { cout<<"mammal move one step\n";}
7 void Move(int distance) const
8 {cout<<"mammal move";
9 cout<<distance<<"steps.\n";}
10 protected:
11 int itsAge;
12 int itsWeight;};
13 class Dog: public Mammal
14 {public:
15 void Move() const
16 { cout<<"dog";}
17 int main()
18 {Mammal bigAnimal;
19 Dog fido;
20 bigAnimal.Move();
21 bigAnimal.Move(2);
22 fido.Move();
23 return 0;}

263
Natija:
mammal move one step
mammal move2steps.
odg move 5 steps.
ASOSIY FUNKSIYANI CHAQIRISH
Siz asosiy funksiyaga murojaat qilishingiz mumkin. Buning uchun
funksiyaga murojaat qilishda siz asosiy sinf nomini, so'ngra ikkita nuqta
belgisi va funksiya nomini aniq ko'rsatishingiz kerak. Masalan:
Mammal:: Move ().
Listing 20.7 da amalga oshirilgan bunday yozuv asosiy sinf usuliga
aniq kirish deb nomlanadi.
Listing 20.7. Asosiy sinf usuliga aniq murojaat qilish
1 #include <iostream>
2 using namespace std;
3 class Mammal
4 { public:
5 void Move() const
6 {cout<<"mammal move one step\n";}
7 void Move(int distance) const
8 {cout<<"mammal move"<<distance;
9 cout<<"steps.\n";}
10 protected:
11 int itAge;
12 int itsWeght;};
13 class Dog: public Mammal
14 {public:
15 void Move() const;};
16 void Dog:: Move () const
17 {cout<<"in dog move...\n";
18 Mammal::Move(3);}
19 int main()
20 {Mammal bigAnimal;
21 Dog fido;
22 bigAnimal.Move(2);
23 fido.Mammal::Move(6);
24 return 0;}
Natija:
mammal move2steps.
mammal move6steps.
Tavsiya etiladi!
 Yangi olingan sinflarni yaratish orqali sinfning funksional
imkoniyatlarini oshiring.

264
VIRTUAL FUNKSIYALAR
C++ dagi polimorfizm shu qadar rivojlanganki, quyidagi misolda
bo'lgani kabi, olingan sinflar obyektlarining manzillarining asosiy
sinfiga belgilar berishga ruxsat beriladi:
Mammal* pMammal = new Dog;
Ushbu ifoda dinamik xotira sohasida Dog sinfining yangi obyektini
yaratadi va ko'rsatgichni mammal sinfining ko'rsatkichi bo'lgan ushbu
obyektga qaytaradi. Bu juda mantiqiy, chunki it sutemizuvchilarning
vakili.
Ushbu ko'rsatgich keyinchalik Mammal sinfining har qanday
usulini chaqirish uchun ishlatilishi mumkin. Bundan tashqari, agar usul
Dog sinfida almashtirilgan bo'lsa, u holda ko'rsatgich orqali usulga
murojaat qilganda, ushbu olingan sinfda ko'rsatilgan variant chaqiriladi.
Bu virtual funksiyalardan foydalanishning mohiyati. Listing 20.8
virtual funksiya qanday ishlashini va virtual bo'lmagan funksiya bilan
nima sodir bo‘lishini ko'rsatadi.
Listing 20.8. Virtual usullardan foydalanish
1 #include <iostream>
2 using namespace std;
3 class Mammal
4 {public:
5 Mammal():itsAge(1) {cout << "Mammal constructor…\n"; }
6 virtual ~Mammal() { cout << "Mammal destructor...\n";}
7 void Move() const { cout << "Mammal move one step\n";}
8 virtual void Speak() const { cout << "Mammal speak!\n"; }
9 protected:
10 int itsAge;
11 };
12 class Dog : public Mammal
13 {public:
14 Dog() { cout << "Dog Constructor...\n"; }
15 virtual ~Dog() { cout << "Dog destructor…\n"; }
16 void WagTail() { cout << "Wagging Tail...\n"; }
17 void Speak()const { cout << "Woof!\n"; }
18 void Move()const {cout << "Dog moves 5 steps...\n"; }
19 };
20 int main(){
21 Mammal *pDog = new Dog;
22 pDog->Move();
23 pDog->Speak();
24 return 0;}
Natija:
Mammal constructor...
Dog Constructor...

265
Mammal move one step
Woof!
ESLATMA: Kompilyatsiya vaqtida foydalanuvchi qaysi sinf
obyektini yaratmoqchi ekanligi va Speak() usulining qaysi versiyasidan
foydalanilishi noma'lum. Ko'rsatgichning obyektga bunday bog'lanishi,
dasturni kompilyatsiya qilish paytida sodir bo'ladigan statik
bog'lanishdan farqli o'laroq, deb ataladi.
VIRTUAL FUNKSIYALAR QANDAY ISHLAYDI
Olingan sinfda, masalan, Dog sinfida obyekt yaratishda, avval
asosiy konstruktor, so'ngra olingan sinf chaqiriladi. Sxematik ravishda
it sinfining obyekti 20.2-rasmda berilgan. E'tibor bering, lotin sinfining
obyekti ikki qismdan iborat bo'lib, ulardan biri asosiy sinf konstruktori
tomonidan, ikkinchisi lotin sinfining konstruktori tomonidan
yaratilgan.

20.2-rasm. Yaratilgan dog sinf obyekti

20.3-rasm. Mammal sinfining virtual funksiyalari jadvali


Agar biror bir obyektda odatiy virtual bo'lmagan funksiya
yaratilgan bo'lsa, unda obyekt ushbu funksiya uchun to'liq javobgarlikni
o'z zimmasiga oladi. Ko'pgina kompilyatorlar v-jadvallar deb
nomlangan virtual funksiyalar jadvallarini yaratadilar.

266
20.4-rasm. Dog sinfining virtual funksiyalari jadvali
Shunday qilib, har bir obyektda vptr ko'rsatkichi mavjud bo'lib, u
o'z navbatida barcha virtual funksiyalarga ko'rsatgichlarni o'z ichiga
olgan virtual funksiyalar jadvaliga murojaat qiladi. Dog sinfidagi
obyekt uchun vptr ko'rsatgichi rasmda ko'rsatilgandek, asosiy Mammal
sinfiga tegishli obyekt qismini yaratishda ishga tushiriladi.
Dog class Builderni chaqirgandan so'ng, vptr ko'rsatkichi Dog sinfi
uchun quritilgan virtual funksiyaning (agar mavjud bo'lsa)
almashtirilgan versiyasini ko'rsatadigan tarzda o'rnatiladi (20.4-rasm).
Natijada, Mammal sinfiga ko'rsatgichdan foydalanganda, vptr
ko'rsatgichi obyektning haqiqiy turiga mos keladigan virtual funksiya
variantiga ishora qiladi. Shuning uchun, oldingi misolda Speak()
usuliga murojaat qilganda, tegishli olingan sinfda berilgan funksiya
bajarildi.
Agar asosiy sinf obyektiga ko'rsatgich qo‘yilsa, ko'rsatgichni
meroso‘r sinf obyektiga o'tkazish juda maqbul va ko'pincha amalda
qo'llaniladi. Keyin merosxo‘r sinf destruktori avtomatik ravishda asosiy
sinf destruktorini chaqiradi va ko'rsatilgan obyekt butunlay o'chiriladi.
Bu qoidadan kelib chiqadi: agar sinfda virtual funksiyalar e'lon
qilingan bo'lsa, unda destruktor virtual bo‘lishi kerak.
Konstruktorlar virtual bo‘lishi mumkin emas, bundan xulosa qilish
mumkinki, virtual nusxa ko'chirish konstruktori ham bo‘lishi mumkin
emas. Ammo ba'zida dastur ko'rsatgichni asosiy sinf obyektiga
o'tkazishi va uni olingan sinf obyektiga to'g'ri nusxalashi talab qilinadi.
Bunga erishish uchun asosiy sinfda virtual clone () usulini yaratish
kerak. Clone () usuli joriy sinf obyektining nusxasini yaratishi va
qaytarishi kerak.
Olingan sinflarda clone () usuli almashtirilganligi sababli, uni
chaqirganda tanlangan sinfga mos keladigan obyektlarning nusxalari

267
yaratiladi. Ushbu usuldan foydalanadigan dastur Listing 20.9 da
ko'rsatilgan.
Listing 20.9. Virtual nusxa ko'chirish konstruktori
1 #include <iostream>
2 using namespace std;
3 class Mammal
4 {public:
5 Mammal():itsAge(1) { cout << "Mammal constructor...\n";}
6 virtual ~Mammal() { cout << "Mammal destructor...\n";}
7 Mammal (const Mammal & rhs);
8 virtual void Speak() const { cout << "Mammal speak!\n";}
9 virtual Mammal* Clone() { return new Mammal(*this);}
10 int GetAge()const {return itsAge;}
11 protected:
12 int itsAge;
13 };
14 Mammal::Mammal (const Mammal & rhs):itsAge(rhs.GetAge())
15 {cout << "Mammal Copy Constructor...\n";}
16 class Dog : public Mammal
17 {public:
18 Dog() { cout << "Dog constructor...\n";}
19 virtual ~Dog() { cout << "Dog destructor...\n"; }
20 Dog (const Dog & rhs);
21 void Speak()const { cout << "Woof!\n"; }
22 virtual Mammal* Clone() {return new Dog(*this); }
23 };
24 Dog::Dog(const Dog & rhs):
25 Mammal(rhs)
26 {cout << "Dog copy constructor...\n";}
27 class Cat : public Mammal
28 {public:
29 Cat() { cout << "Cat constructor\n"; }
30 ~Cat() { cout << "Cat destructor\n"; }
31 Cat (const Cat &);
32 void Speak()const { cout << "Meow!\n"; }
33 virtual Mammal* Clone() { return new Cat(*this); }
34 } ;
35 Cat::Cat(const Cat & rhs):
36 Mammal(rhs)
37 {cout << "Cat copy constructor\n";}
38 enum ANIMALS { MAMMAL, DOG, CAT} ;
39 const int NumAnimalTypes = 3;
40 int main()
41 {
42 Mammal *theArray[NumAnimalTypes];
43 Mammal* ptr;
44 int choice, i;
45 for ( i = 0; i<NumAnimalTypes; i++)
46 {
47 cout << "(1)dog (2)cat (3)Mammal: ";

268
48 cin >> choice;
49 switch (choice)
50 {
51 case DOG: ptr = new Dog;
52 break;
53 case CAT: ptr = new Cat;
54 break;
55 default: ptr = new Mammal;
56 break;
57 }
58 theArray[i] = ptr;
59 Mammal *OtherArray[NumAnimalTypes];
60 for (i=0;i<NumAnimalTypes; i++){
61 theArray[i]->Speak();
62 OtherArray[i] = theArray[i]->Clone();
63 }
64 for (i=0;i<NumAnimalTypes; i++)
65 OtherArray[i]->Speak();}
66 return 0;}
Tavsiya etiladi!
 Agar dastur asosiy va olingan sinflarni o'z ichiga olgan bo'lsa,
virtual usullardan foydalaning.
 Agar dasturda virtual usullar yaratilgan bo'lsa, virtual
destruktordan foydalaning.

Nazorat savollari va topshiriqlar:


1. Virtual funksiya nima?
2. Virtual destruktor nima?
3. Virtual konstruktorni e'lon qilish mumkinmi?
4. Virtual nusxa ko'chirish konstruktorini qanday yaratish mumkin?
5. Agar Hosila sinfida bu funksiya almashtirilgan bo'lsa, Hosila sinf
obyektidan asosiy sinf funksiyasini qanday chaqirish mumkin?
6. Agar Hosila sinfida bu funksiya almashtirilmagan bo'lsa, Hosila sinf
obyektidan asosiy sinf funksiyasini qanday chaqirish mumkin?
7. Agar asosiy sinfda funksiya virtual deb e'lon qilingan bo'lsa va
merosxo‘r sinfda funksiyaning virtualligi ko'rsatilmagan bo'lsa,
funksiya keyingi ishlab chiqarilgan sinfda virtual bo'lib qoladimi?
8. Protected kalit so'z nima maqsadda ishlatiladi?
9. Bitta butun qiymatni qabul qiladigan va voidni qaytaradigan virtual
funksiyani e'lon qiling.
10. To'rtburchaklar sinfidan ishlab chiqarilgan kvadrat sinf e'lonini
yozing, bu esa o'z navbatida Shape sinfidan olingan.

269
11. Aytaylik, oldingi misolda Shape sinf obyekti parametrlardan
foydalanmaydi, to'rtburchaklar sinf obyekti ikkita parametrni oladi
(uzunlik va kenglik) va kvadrat sinf obyekti bitta parametr (1 uzunlik);
kvadrat sinf uchun konstruktorni yozing.
12. 11-mashqdan olingan Square sinfi uchun virtual nusxa ko'chirish
konstruktorini yozing.
13. Xatolikni toping.
void SomeFunction(Shape);
Shape pRect = new Rectangle;
SomeFunction(+pRect);
14. Xatolikni toping.
class Shape()
{
public:
Shape();
virtual -Shape();
virtual Shape(const Shape&);};

270
21-MAVZU. ICHMA-ICH JOYLASHGAN SINFLAR
 Ichki sinf
 Ichki sinf uchun kirish modifikatori
 Ichki sinf obyekti

ICHKI SINF
boshqa sinf ichida joylashgan sinf.
Odatda, ichki sinflar faqat tashqi sinf obyekti ichida mavjud bo‘lishi
mumkin bo'lgan obyektlarni tavsiflash uchun ishlatiladi.
Kichik bir misolni ko'rib chiqing. Aytaylik, foydalanuvchi uchun
uning hisobini tavsiflovchi ma'lumotlarni (Login, parol) aniqlashimiz
kerak.
Listing 21.1.
#include <iostream>
class Person
{
private:
std::string name;

class Account // ichki sinf


{
public:
Account(const std::string& p_email, const std::string&
p_password)
{
email = p_email;
password = p_password;
}
std::string email;
std::string password;
};
Account account{"", ""}; // Account o‘zgaruvchi
public:
Person(const std::string& p_name, const std::string&
p_email, const std::string& p_password)
{
name = p_name;
account = Account(p_email, p_password);
}
void print()
{
std::cout<<"Name: " << name << "\n" << "Email: " <<
account.email << "\n"
<< "Password: " << account.password << std::endl;
}

271
};
int main()
{
Person tom("Tom", "tom@localhost.com", "qwerty");
tom.print();}

Bu yerda Person sinfi foydalanuvchi sinfini ifodalaydi. Uning


hisob ma'lumotlari alohida sinfga ajratilgan - Account.
Account sinfi private deb belgilangan. Shunday qilib, biz ushbu
sinfga faqat Person sinfidan kira olamiz.
Listing 21.2.
class Account // ichki sinf
{public:
Account(std::string p_email, std::string p_password)
{
email = p_email; password = p_password;
}
std::string email; std::string password;
};
Ichki sinflarda kirish spetsifikatorlaridan ham foydalanish
mumkin.
Bunday holda, elektron pochta, parol va konstruktor maydonlari
hisob-kitob sinfidan tashqarida Person sinfida foydalanish uchun Public
deb belgilanadi.
Bundan tashqari, Account sinfi Private bo'lganligi sababli, bu
maydonlar hali ham Person sinfidan tashqarida mavjud emas. Account
o'zgaruvchisi ma'lum bir shaxs obyektining hisob ma'lumotlarini
saqlash uchun aniqlanadi:
Account account{"", ""};
// Account ichki sinfidagi o‘zgaruvchi
Bunday holda, u boshlang`ich ma'lumotlar sifatida - elektron
pochta va parol uchun bo'sh satrlarni oladi.
Person sinf konstruktorida biz elektron pochta va parol uchun
ma'lumotlarni olamiz va ularning asosida account obyektini yaratamiz:
account = Account(p_email, p_password);
Elektron pochta va parol maydonlari Public bo'lganligi sababli, biz
Person sinfining funksiyalariga murojaat qilishimiz mumkin, masalan,
print funksiyalarida ularning qiymatlarini chiqaramiz:
void print()
{ std::cout<<"Name: " << name << "\n" << "Email: " <<
account.email << "\n" << "Password: " <<
account.password << std::endl; }

272
Asosiy funksiyada biz bitta person obyektini yaratamiz va
konstruktor orqali ma'lumotlarni, shu gapdan account obyekti uchun
uzatamiz:
Person tom ("Tom", "tom@localhost.com", "qwerty“);
tom.print();
Yuqoridagi misolda Account obyektlarini Person sinfdan
tashqarida yaratish yoki ishlatish mumkin emas, chunki Account sinfi
Private.
Shu bilan birga, biz uni hammaga ochiq qilishimiz va keyin Person
sinfidan tashqarida unga murojaat qilishimiz mumkin:
Listing 21.3.
#include <iostream>
class Person
{public:
class Account // ichki sinf
{
public:
Account(const std::string& p_email, const std::string&
p_password)
{
email = p_email;
password = p_password;
}
std::string email{};
std::string password{};
void print2()
{std::cout<<"salom";
}
};
Person(const std::string& p_name, const Account&
p_account)
{
name = p_name;
account = p_account;
}
void print()
{
std::cout<<"Name: " << name << "\n" << "Email: " <<
account.email << "\n"
<< "Password: " << account.password << std::endl;
}
private:
std::string name;
Account account{"", ""}; // ichki sinfining obyekti
};
int main()
{
Person::Account account("bob@somemail.com", "qwerty");

273
Person bob("Bob", account);
bob.print();
account.print2();
}
Endi ichki sinf Public. Biz ushbu sinfning obyektlarini yaratishimiz
va tashqi sinf nomidan foydalanib uning o'zgaruvchilari va
funksiyalariga murojaat qilishimiz mumkin:
Person::Account account ("bob@somemail.com", "qwerty");
Ichki sinf funksiyalari to'g'ridan-to'g'ri tashqi sinfning statik
a'zolariga, shuningdek tashqi sinfda aniqlangan boshqa turlarga
murojaat qilishi mumkin.
Tashqi sinfning boshqa a'zolariga ichki sinfdan standart usullar
bilan kirish mumkin: sinf obyekti, ko'rsatgich yoki sinf obyektiga
havola orqali.
Bunday holda, ichki sinfning funksiyalari tashqi sinfda aniqlangan
private o'zgaruvchilar va constlarga murojaat qilishi mumkin.

Nazorat savollari va topshiriqlar:


1. Ichki sinfga nima misol keltirish mumkin?
2. C++ ichki sinf usuli nima?
3. Ichki sinfni nima afzalliklari bor?
4. Nima uchun ichki sinflar ishlatiladi?
5. C++da ichki sinf va sinf o'rtasidagi farq nima?

274
22-MAVZU. POLIMORFIZM
 Ko'p meros va undan foydalanish
 Virtual meros
 Mavhum ma'lumotlar turlari
 Sof virtual funksiyalar

Keling, hayvonlar sinfi ustida ishlashni davom ettiraylik va endi u


qandaydir umumiy sinfdan meros qilib olingan ikkita sinfdan
foydalanadi deb taxmin qilaylik. Ulardan biri qushlarga bag'ishlangan
Bird, ikkinchisi sutemizuvchilarga bag'ishlangan Mammals. Bird
sinfida uchish imkoniyatini belgilaydigan Fly () a'zo funksiyasi mavjud.
Mammals sinfi bir qator kichik sinflarga, shu gapdan otlar sinfiga
bo'lingan. Sinf ikkita a'zo funksiyani o'z ichiga oladi-Whinny() va
Gallop(), mos ravishda chiyillash va yugurishni e'lon qiladi.
Ammo to'satdan siz qiziqarli yangi afsonaviy obyektni - qanotli
Pegasusni yaratishni xohlaysiz, bu ot va qush o'rtasidagi gibridga
o'xshaydi. Faqat bitta merosdan foydalanib, bu vazifani bajarish qiyin
bo'ladi.
Agar siz Pegasus obyektini Bird sinfining a'zosi deb e'lon qilsangiz,
unda Whinny() va Gallop () funksiyalari unga kira olmaydi. Agar
Pegasus Horse sinfining obyekti deb e'lon qilinsa, u holda Fly ()
funksiyasi unga kira olmaydi.
Birinchi yechim Fly() usulini Horse sinfiga nusxalash va keyin
ushbu sinfda Pegasus obyektini yaratish bo‘lishi mumkin. Bunda ikkala
sinf (Bird va Horse) bir xil Fly () usulini o'z ichiga oladi va bir sinfda
usulni o'zgartirganda, boshqa sinfda tegishli o'zgarishlarni amalga
oshirishni unutmaslik kerak bo'ladi.
Muammoni hal qilish uchun bir nechta yondashuvlardan
foydalanish mumkin. Masalan, Horse sinfidagi Gallop() usulini yanada
soddalashtirilgan Move () ga o'zgartirishingiz mumkin, so'ngra ushbu
usulni Pegasus obyektida Fly () usuli vazifasini bajaradigan tarzda
almashtirishingiz mumkin. Horse sinfining boshqa obyektlarida
Move() usuli Gallop () usuli avvalgidek bajariladi. Pegasus obyekti
uchun u Gallop () usuli bilan qisqa masofalarni, Fly() usuli bilan esa
uzun masofalarni bosib o'tishi kerakligini aniqlash mumkin:
Pegasus::Move(long distance)
{
if (distance > veryFar)
fly(distance);

275
else
gallop(distance);
}
Ammo bu yondashuv bir qator cheklovlarga ega, chunki obyekt
endi qisqa masofalarga ucha olmaydi va uzoq masofalarga yugura
olmaydi.
USULNI IYERARXIK SINFLARIGA O'TKAZISH
Ko'pincha, bunday muammolarni hal qilish uchun usul prototipi
sinflarning ierarxik Listingi bo'ylab yuqoriga ko'tarilib, uni ko'proq
lotin sinflariga taqdim etiladi.
Fly() usuli faqat ko'rsatgich Pegasus obyekti bilan bog'langan
taqdirdagina chaqirilishi mumkin. Buning uchun siz ko'rsatgichga
murojaat qilishingiz va qaysi obyektni ko'rsatayotganini aniqlashingiz
kerak.
Ushbu yondashuv RTTI (Runtime Type Identification bajarilganda
turini aniqlash) deb nomlanadi. Ammo RTTI-ni bajarish qobiliyati
faqat C++ kompilyatorlarining so'nggi versiyalariga qo'shildi.
Agar sizning kompilyatoringiz RTTI-ni qo'llab-quvvatlamasa,
dasturga har bir sinf turlarining Listingini qaytaradigan usul qo'shib, uni
o'zingiz amalga oshirishingiz mumkin. Qaytarilgan qiymat dasturni
bajarish paytida tahlil qilinishi mumkin va Agar Pegasus qiymati
qaytarilsa, Fly() usulini chaqirishga ruxsat beriladi.
Fly () usulini chaqirish uchun ko'rsatgich tipini ish vaqtida
o'zgartirish kerak, bu uning Horse obyekti bilan emas, balki Pegasus
merosxo‘r sinfining obyekti bilan bog'liqligini aniqlaydi. Ushbu
yondashuv C++ da dynamic_cast operatori orqali amalga oshiriladi.
Agar dasturda asosiy Horse sinfidagi obyektlarga ko'rsatgich
yaratilgan bo'lsa va unga Pegasus mersoxo‘r sinf obyektiga ko‘rsatgich
berilgan bo'lsa, unda bu ko'rsatgich polimorfik tarzda ishlatilishi
mumkin. Merosxo‘r sinf usuliga murojaat qilish uchun dynamic_cast
operatoridan foydalanib, asosiy sinf ko'rsatkichini merosxo‘r sinf
ko'rsatkichi bilan dinamik ravishda almashtirish kerak.
Dastur davomida asosiy sinf ko'rsatkichi sinovdan o'tkaziladi. Agar
asosiy sinf ko'rsatkichi ko‘rsatilgan joriy obyekt aslida merosxo‘r sinf
obyekti ekanligi aniqlansa, u holda merosxo‘r sinf ko'rsatkichi ushbu
obyekt bilan bog'lanadi. Aks holda, merosxo‘r sinf ko'rsatkichi nolga
aylanadi. Ushbu misol Listing 22.1 da keltirilgan.

276
Listing 22.1. Pastga tushirish
#include <iostream>
using namespace std;
enum TYPE {HORSE, PEGASUS };
class Horse
{
public:
virtual void Gallop(){ cout << "Galloping…\n"; }
private:
int itsAge;
};
class Pegasus : public Horse
{
public:
virtual void Fly()
{ cout << "I can fly! I can fly! I can fly!\n"; }
};
const int NumberHorse = 5;
int main(){

Horse* Ranch[NumberHorse];
Horse* pHorse;
int choice, l;
for (l=0; l<NumberHorse; l++)
{
cout << "(1)Horse (2)Pegasus: ";
cin >> choice;
if (choice == 2)
pHorse = new Pegasus;
else
pHorse = new Horse;
Ranch[l] = pHorse;
}
cout <<" n";
for (int i=0; i<NumberHorse; i++)
{
Pegasus *pPeg = dynamic_cast< Pegasus *> (Ranch[i]);
if (pPeg)
pPeg->Fly();
else
cout << "Just a horse\n";
delete Ranch[i];
}
return 0;
}
Natija:
(1)Horse (2)Pegasus: 1
(1)Horse (2)Pegasus: 2
(1)Horse (2)Pegasus: 1
(1)Horse (2)Pegasus: 2

277
(1)Horse (2)Pegasus: 1
Just a horse
I can fly! I can fly! I can fly!
Just a horse
I can fly! I can fly! I can fly!
Just a horse
Yana bir muammo shundaki, Pegasus Horse tipidagi obyekt
sifatida e'lon qilinganida, uni Pegasus sinfidagi obyektlar Listingiga
qo'shish imkonsiz bo'lib qoladi.
Shunday qilib, faqat bitta merosga rioya qilgan holda, bu
muammoni hal qilish mumkin emas edi. Siz uchta funksiyani - Fly(),
Whinny() va Gallop() - Bird va Horse ikkita sinflari uchun umumiy
bo'lgan asosiy Animal sinfiga o'tkazishingiz mumkin. Natijada, Bird va
Horse sinflari uchun ikkita obyekt Listingi o'rniga bitta umumiy Animal
sinf obyektlari Listingi paydo bo'ladi. Usulning kamchiligi shundaki,
asosiy sinf juda ko'p funksiyalarni o'z zimmasiga oladi.
Bir nechta asosiy sinflardan yangi sinflarni keltirib chiqarish
imkoniyati mavjud. Bunday jarayon deb ataladi. 22.2-
Listingda Pegasus sinfi ikkita asosiy sinf - Pegasus va Horsening
xususiyatlarini meros qilib oladigan tarzda e'lon qilingan. Keyingi
dastur Pegasus obyektini ikkala sinf obyektlari Listingiga qo'shadi.
Listing 22.2. Ko'p meros
#include <iostream>
using namespace std;
const int DefaultSize = 10;
class Array
{
public:
Array(int size = DefaultSize);
Array(const Array &rhs);
Array() { delete [] pType;}
// operatorlar
Array& operator=(const Array&);
int& operator[](int offSet);
const int& operator[](int offSet) const;
int GetitsSize() const { return itsSize; }
friend ostream& operator<< (ostream&, const Array&);
class xBoundary { }
class xSize { } ;
class xTooBig : public xSize ( } ;
class xTooSmall : public xSize { } ;
class xZero : public xTooSmall
class xNegative : public xSize { }
private:
int *pType;

278
int itsSize;
};
Array::Array(int size);
itsSize(size)
{
if (size == 0)
throw xZero();
if (size > 30000)
throw xTooBig():
if (size <1)
throw xNegative();
if (size < 10)
throw xTooSmall();
pType = new int[size];
for (int i = 0; i<size; i++)
pType[i] = 0;
}
int& Array::operator[](int offSet)
{
int size = GetitsSize();
if (offSet >= 0 && offSet < GetitsSize())
return pType[offSet];
throw xBoundary();
return pType[0]; / / kompilyator talabi
}
const int& Array::operator[](int offSet) const
int mysize = Gettitssize();
if (offSet >= 0 && offSet < Getitssize())
return pType[offSet];
throw xBoundary();
qaytish pType[0]; / / kompilyator talabi
int main()
try
Array intArray(0);
for (int j = 0; j< 100; j++)
intArray[j] = j;
cout << "intArray[" << j << "] okay…\n";
catch (Array::xBoundary)
cout << "Unable to process your input!\n";
catch (Array::xTooBig)
cout << "This array is too big…\n";
catch (Array::xTooSmall)
cout << "This array is too small…\n";
catch (Array: :zero)
cout << "You asked for an array";
cout << " of zero objects!\n";
catch (…)
cout << "Something went wrong!\n";
cout << "Done.\n";
return 0;
}

279
Natija:
This array is too small…
Done
KO'P MEROSNI E'LON QILISH
Yaratilgan obyekt bir nechta asosiy sinfning xususiyatlarini meros
qilib olishini ko'rsatish uchun yaratilgan sinf nomidan keyin “ : ”
qo'yiladi, so'ngra barcha asosiy sinflarning nomlari vergul bilan
ko'rsatiladi.
1-misol:
class Pegasus: public Horse, public Bird
2-misol:
class Schnoodle: public Schnauzer, public Poodle
Ikki asosiy sinf 22.1-rasmda ko'rsatilgandek pegasus obyektini
qurishda ishtirok etadilar.

22.1-rasm. Ko'p merosxo‘rlik qo‘llanilishi


Ko'p merosdan foydalanganda bir qator savollar tug'iladi. Masalan,
ikkala asosiy sinf ham bir xil nomga ega bo'lsa yoki virtual funksiyalar
yoki bir xil nomdagi ma'lumotlarni o'z ichiga olsa nima bo'ladi? Turli
xil asosiy sinflarning konstruktorlari qanday ishga tushiriladi? Agar
ikkita asosiy sinf bir xil ota-ona sinfidan meros qilib olingan bo'lsa nima
bo'ladi? Ushbu savollarning barchasi keyingi bo'limda ko'rib chiqiladi,
shundan so'ng siz ko'p merosdan amaliy foydalanishga o'tishingiz
mumkin.
Agar Pegasus sinfi ikkita asosiy sinfdan - Bird va Horse dan meros
qilib olingan bo'lsa va ularning har birida parametrlar Listingi bo'lgan
konstruktorlar e'lon qilingan bo'lsa, Pegasus sinfi ushbu
konstruktorlarni ishga tushiradi. Bu sodir bo'lganda, listing 22.3 da
ko'rsatilgan.

280
Listing 22.3. Ko'p merosda obyektlarni yaratish
#include <iostream>
using namespace std;
typedef int HANDS;
enum COLOR { Red, Green, Blue, Yellow, White, Black, Brown };
class Horse
{public:
Horse(COLOR color, HANDS height);
virtual ~Horse() { cout << "Horse destructor...\n"; }
virtual void Whinny()const { cout << "Whinny!..."; }
virtual HANDS GetHeight() const { return itsHeight; }
virtual COLOR GetColor() const {return itsColor; }
private:
HANDS itsHeight;
COLOR itsColor;
};
Horse::Horse(COLOR color, HANDS height):
itsColor(color), itsHeight(height)
{cout << "Horse constructor...\n";}
class Bird
{public:
Bird(COLOR color, bool migrates);
virtual ~Bird() { cout << "Bird destructor...\n"; }
virtual void Chirp()const { cout << "Chirp..."; }
virtual void Fly()const
{cout << "I can fly! I can fly! I can fly! ";}
virtual COLOR GetColor()const { return itsColor; }
virtual bool GetMigration() const { return itsMigration; }
private:
COLOR itsColor;
bool itsMigration;
} ;
Bird::Bird(COLOR color, bool migrates):
itsColor(color), itsMigration(migrates)
{cout << "Bird constructor…\n";}
class Pegasus : public Horse, public Bird
{public:
void Chirp()const { Whinny(); }
Pegasus(COLOR, HANDS, bool, long);
~Pegasus() { cout << "Pegasus destructor\n";}
virtual long GetNumberBelievers() const
{return itsNumberBelievers;}
private:
long itsNumberBelievers;
};
Pegasus:: Pegasus(
COLOR aColor,
HANDS height,
bool migrates,
long NumBelieve):
Horse(aColor, height),

281
Bird(aColor, migrates),
itsNumberBelievers(NumBelieve)
{cout << "Pegasus constructor\n";}
int main()
{
Pegasus *pPeg = new Pegasus(Red, 5, true, 10);
pPeg->Fly();
pPeg->Whinny();
cout << "\nYour Pegasus is " << pPeg->GetHeight();
cout << "hands tall and ";
if (pPeg->GetMigration())
cout << "it does migrate.";
else
cout << "it does not migrate.";
cout << " nA total of " << pPeg->GetNumberBelievers();
cout << " people believe it exists.\n";
delete pPeg;
return 0;}

Natija:
Horse constructor…
Bird constructor…
Pegasus constructor…
I can fly! I can fly! I can fly! Whinny!…
Your Pegasus is 5 hands tall and it does migrate.
A total of 10 people believe it exists.
Pegasus destructor…
Bird destructor…
Horse destructor…

22.3 Listingida ikkala sinf - Horse va Bird - GetColor () usuliga


ega. Dastur Pegasus obyektining rangini qaytarishi kerak bo‘lishi
mumkin, ammo savol tug'iladi: bu jarayonda ikkita eski usuldan qaysi
biri qo'llaniladi? Axir, ikkala asosiy sinfda e'lon qilingan usullar bir xil
nomga ega. Natijada, dasturni kompilyatsiya qilishda noaniqlik paydo
bo'ladi, uni kompilyatsiya qilishdan oldin hal qilish kerak.
Agar siz shunchaki yozsangiz:
COLOR currentColor = pPeg->GetColor();
kompilyator xato xabarini ko'rsatadi:
'Horse::GetColor' va 'Bird::GetColor' (A'zo aniqlanmagan).
Ushbu noaniqlikni sizga kerak bo'lgan sinf uslubiga aniq murojaat
qilish orqali hal qilish mumkin:
COLOR currentColor = pPeg->Horse::GetColor();

282
Agar Pegasus sinfida bu funksiya almashtirilsa, muammo o'z-
o'zidan hal qilinadi, chunki bu holda Pegasus sinfining a'zo funksiyasi
chaqiriladi:
virtual COLOR GetColor()const { return Horse::GetColor(); }
Agar boshqa sinf usulidan foydalanish zarurati tug'ilsa, unda
quyidagi ifoda bilan unga murojaat qilish xato bo'lmaydi.
COLOR currentColor = pPeg->Bird:: GetColor():

ASOSIY SINFDAN MEROS


Agar boshqa sinf meros qilib olingan ikkala asosiy sinf ham bitta
umumiy asosiy sinfdan, masalan, Animal sinfidan Bird va Horse
sinflari kelib chiqqan bo'lsin. Bu holat 22.2-rasmda berilgan.

22.2-rasm. Umumiy asosiy sinf


22.2-rasmda ko'rsatilgandek Pegasus sinfi uchun asosiy bo'lgan
ikkita sinf birgina umumiy Animal sinfidan meros qilib olingan. Shu
bilan birga, kompilyator Bird va Horse sinflarini bir xil nomdagi ikkita
asosiy sinfning merosxo‘rlari sifatida ko'rib chiqadi, bu esa quyidagi
noaniqlikka olib kelishi mumkin. Masalan, Agar Itsage a'zosi
o'zgaruvchisi va GetAge() funksiyasi Animal sinfida e'lon qilingan
bo'lsa va dastur pGet - >GetAge () deb nomlangan bo'lsa, u holda
Animal sinfidan Bird sinfiga yoki Animal sinfdan Horse sinfiga meros
bo'lib qolgan GetAge () funksiyasi chaqiriladimi? Ushbu qarama-
qarshilik 22.4-Listingda hal qilinadi.
Listing 22.4. Umumiy asosiy sinf
#include <iostream>
using namespace std;
typedef int HANDS;
enum COLOR { Red, Green, Blue, Yellow, White, Black, Brown };
class Animal
{public:

283
Animal(int);
virtual ~Animal() { cout << "Animal destructor...\n"; }
virtual int GetAge() const { return itsAge; }
virtual void SetAge(int age) { itsAge = age; }
private:
int itsAge;
};
Animal::Animal(int age):
itsAge(age)
{cout << "Animal constructor...\n";}
class Horse : public Animal
{public:
Horse(COLOR color, HANDS height, int age);
virtual ~Horse() { cout << "Horse destructor...\n"; }
virtual void Whinny()const { cout << "Whinny!..." ;}
virtual HANDS GetHeight() const { return itsHeight; }
virtual COLOR GetColor() const { return itsColor; }
protected:
HANDS itsHeight;
COLOR itsColor;
};
Horse::Horse(COLOR color, HANDS height, int age):
Animal(age),
itsColor(color),itsHeight(height)
{cout << "Horse constructor...\n";}
class Bird : public Animal
{
public:
Bird(COLOR color, bool migrates, int age);
virtual ~Bird() { cout << "Bird destructor...\n"; }
virtual void Chirp()const { cout << "Chirp..."; }
virtual void Fly()const
{ cout << "I can fly! I can fly! I can fly! ";}
virtual COLOR GetColor()const { return itsColor; }
virtual bool GetMigration() const { return itsMigration; }
protected:
COLOR itsColor;
bool itsMigration;
};
Bird::Bird(COLOR color, bool migrates, int age):
Animal(age),
itsColor(color), itsMigration(migrates)
{cout << "Bird constructor\n";}
class Pegasus : public Horse, public Bird
{public:
void Chirp()const { Whinny(); }
Pegasus(COLOR, HANDS, bool, long, int);
virtual ~Pegasus() { cout << "Pegasus destructor\n";}
virtual long GetNumberBelievers() const
{ return itsNumberBelievers; }
virtual COLOR GetColor()const { return Horse::itsColor; }

284
virtual int GetAge() const { return Horse::GetAge(); }
private:
long itsNumberBelievers;
};
Pegasus::Pegasus(
COLOR aColor,
HANDS height,
bool migrates,
long NumBelieve,
int age):
Horse(aColor, height,age),
Bird(aColor, migrates,age),
itsNumberBelievers(NumBelieve)
{cout << "Pegasus constructor...\n";}
int main(){
Pegasus *pPeg = new Pegasus(Red, 5, true, 10, 2);
int age = pPeg->GetAge();
cout << "This pegasus is " << age << " years old.\n";
delete pPeg;
return 0;}

Natija:
Animal constructor…
Horse constructor…
Animal constructor…
Bird constructor…
Pegasus constructor…
This pegasus is 2 years old.
Pegasus destructor…
Bird destructor…
Animal destructor…
Horse destructor...
Animal destructor…

VIRTUAL MEROS
Listing 22.4 noaniqlik muammosini hal qildi, ya'ni Pegasus sinf
obyektida GetAge() funksiyasi qaysi asosiy sinfdan meros bo'lib
o'tganini aniqlab berdi. Ammo, aslida, bu usul bitta umumiy Animal
asosiy sinfidan meros qilib olinadi.
C++ da, rasmda ko'rsatilgandek, biz bir xil nomdagi ikkita sinf
bilan ishlamayotganimizni ko'rsatish imkoniyati mavjud.

285
22.3-rasm Virtual meros
Odatda, sinf konstruktori faqat asosiy sinfning o'ziga xos
o'zgaruvchilari va a'zo o'zgaruvchilarini ishga tushiradi. Agar virtual
meros ishlatilsa, ushbu qoidadan istisno qilinadi. Asosiy asosiy sinf
o'zgaruvchilari undan kelib chiqadigan sinflarning konstruktorlari
tomonidan emas, balki sinflar iyerarxiyasida bo'lganlar tomonidan
ishga tushiriladi. Shuning uchun Animal sinfi Horse va Bird sinflar
tomonidan emas, balki Pegasus sinf obyekti tomonidan ishga
tushiriladi.
Horse va Bird class konstruktorlari, shuningdek, Animal asosiy
sinf initsializatsiya buyruqlarini o'z ichiga oladi, ammo Pegasus
obyektini yaratishda ushbu initsializatsiya ma'lum bir sinf konstruktori
tomonidan amalga oshiriladi.
Listing 22.5-bu 22.4 Listingi dasturiy ta'minot kodi bo'lib, u virtual
merosdan foydalanish mumkin bo'lgan tarzda qayta yozilgan.
Listing 22.5. Virtual merosdan foydalanish misoli
# include<iostream>
using namespace std;
typedef int HANDS;
enum COLOR{ red, green, blue, yellow, white, black, brown };
class Animal
{ public:
Animal(int);
virtual ~Animal() {"animal destructor...\n";}
virtual int GetAge() const{ return itsAge;}
virtual void SetAge(int age) {itsAge=age;}
private:
int itsAge; } ;
Animal::Animal(int age):
itsAge(age)

286
{ cout<<"Animal constructor...\n"; }
class Horse:virtual public Animal
{ public:
Horse (COLOR color, HANDS height, int age);
virtual ~Horse() { cout<<"Horse destructor...\n";}
virtual void Whinny () const { cout<<"Whinny!...";}
virtual HANDS GetHeight()const { return itsHeight;}
virtual COLOR GetColor() const { return itsColor;}
protected:
HANDS itsHeight;
COLOR itsColor; };
Horse::Horse(COLOR color, HANDS height, int age):
Animal(age),itsColor(color),itsHeight(height)
{ cout<<"Horse constructor...\n"; }
class Bird:virtual public Animal
{ public:
Bird(COLOR color, bool migrates, int age);
virtual ~Bird()
{ cout<<"Bird destructor...\n"
}
virtual void Chirp() const{ cout<<"Chirp...";}
virtual void Fly() const
{ cout<<"I can fly! I can fly! ;I can fly!"; }
virtual COLOR GetColor() const { cout<<itsMigration;}
protected:
COLOR itsColor;
bool itsMigration; };
Bird::Bird(COLOR color, bool migrates, int age):
Animal (age),itsColor(color), itsMigration(migrates)
{ cout<<"bird constructor...\n"; }
class Pegasus: public Horse, public Bird
{ public:
void Chirp() const{Whinny(); }
Pegasus(COLOR, HANDS, bool, long, int);
virtual ~Pegasus() { cout <<"Pegasus
destructor...\n";}
virtual long GetNumberBelievers() const
{return itsNumberBelievers;}
virtual COLOR GetColor() const { return Horse::
itsColor;}
private:
long itsNumberBelievers; };
Pegasus::Pegasus(COLOR aColor,HANDS height, bool
migrates,
long NumBelieve,int age):
Horse(aColor, height, age),
Bird(aColor, migrates, age),
Animal(age), itsNumberBelievers(NumBelieve)
{ cout<<"Pegasus constructor...\n"; }
int main()
{ Pegasus *pPeg= new Pegasus(red, 5, true, 10, 2);

287
int age=pPeg->GetAge();
cout<<"This pegasus is"<<age<<"years old.\n";
delete pPeg;
return 0; }
Agar siz dasturingizda bir nechta merosdan foydalanishga qaror
qilsangiz, shuni ta'kidlash kerakki, dasturni disk raskadrovka qilishda
muammolar paydo bo‘lishi mumkin.
Olingan sinflar asosiy sinfni yagona manba sifatida ko'rishiga
ishonch hosil qilish uchun merosning virtualligi barcha oraliq sinflarda
ko'rsatilishi kerak.
1-misol:
class Horse virtual public Animal
class Bird : virtual public Animal
class Pegasus : public Horse, public Bird
2-misol:
class Schnauzer : virtual public Dog
class Poodle : virtual public Dog
class Schnoodle : public Schnauzer, public Poodle
Tavsiya etiladi!
 Sinfda turli sinflarda e'lon qilingan ma'lumotlar va usullarni
qo'llash zarur bo'lgan hollarda bir nechta merosdan foydalaning.
 Usul yoki ma'lumotlar meros manbasining noaniqligi bilan
bog'liq muammolarni iloji boricha oqlangan tarzda hal qilish uchun
virtual merosdan foydalaning.
ATRIBUTLAR SINFI
-bu bir qator usullarga kirishni ochadigan, ammo
hech qanday ma'lumotni o'z ichiga olmaydigan (yoki hech bo'lmaganda
minimal ma'lumotlar to'plamini o'z ichiga olgan) sinf.
Atribut sinflari funksiyalari meros orqali olingan sinflarga
o'tkaziladi. Sinf atributlari va boshqa sinflar o'rtasidagi yagona farq
shundaki, ular deyarli hech qanday ma'lumotni o'z ichiga olmaydi.
Atribut sinflaridan foydalanish, shuningdek, boshqa asosiy sinflardan
meros bo'lib qolgan ma'lumotlarning merosxo‘r sinfida ishlatilganda
noaniqlik ehtimolini kamaytiradi.
Masalan, Horse sinfi ikkita sinfdan - Animal va Displayabledan
kelib chiqqan deb taxmin qiling, ikkinchisi faqat yangi funksiyalarni
qo'shadi, ammo ma'lumotlarni o'z ichiga olmaydi. Bunday holda, Horse
sinfining barcha meros qilib olingan ma'lumotlari faqat bitta asosiy

288
Animal sinfidan kelib chiqadi va funksiyalar ikkala sinfdan ham meros
bo'lib o'tadi.
(sapability class) ba'zan Mixin (mixin) deb ham
ataladi. n.
MAVHUM MA'LUMOTLAR TURLARI
Obyektni dasturlashda ko'pincha mantiqiy bog'liq sinflarning
iyerarxiyalari yaratiladi. Masalan, Rectangle va Circle sinflaridan kelib
chiqqan rasm sinfini tasavvur qiling. Keyin Square sinf to'rtburchaklar
xususiy turi sifatida to'rtburchaklar sinfidan ishlab chiqariladi.
Har bir olingan sinfda Draw(), GetArea() va boshqa usullar o‘zaro
bog`liq. Shape sinfi va undan olingan Rectangle va Circle bilan dastur
22.6 Listingida ko'rsatilgan.
Listing 22.6. Shape oilasi sinflari
#include<iostream>
using namespace std;
class Shape{
public:
Shape(){ }
virtual ~Shape(){ }
virtual long GetArea() {return -1; }
virtual long GetPerim() {return -1; }
virtual void Draw() { }
private:};
class Circle : public Shape
{ public:
Circle(int radius):itsRadius(radius){}
~Circle(){}
long GetArea(){ return 3* itsRadius*itsRadius;}
long Getperim(){ return 6*itsRadius;}
void Draw();
private:
int itsRadius;
int itsCircumference;};
void Circle::Draw() { cout<<"Circle drawing routine
here!\n";}
class Rectangle:public Shape
{ public:
Rectangle(int len, int width):
itsLength(len),itsWidth(width){}
virtual~Rectangle(){}
long GetArea() {return itsLength+2*itsWidth; }
long GetPerim(){ return 2*itsLength+2*itsWidth;}
virtual int GetLength() { return itsLength;}
virtual int GetWidth() { return itsWidth;}
void Draw();
private:
int itsWidth;
int itsLength;};
void Rectangle::Draw()

289
{ for(int i=0;i<itsLength; i++){
for(int j=0;j<itsWidth; j++)
cout<<"x";
cout<<"\n"; } }
class Square: public Rectangle
{ public:
Square(int len);
Square(int len,int width);
~Square(){}
long GetPerim(){return 4*GetLength();}};
Square::Square(int len):
Rectangle(len,len) {}
Square::Square(int len,int width):
Rectangle(len,width)
{if (GetLength() !=GetWidth())
cout<<"Error, not a square...a Rectangle??\n"; }
int main() {
int choice;
bool fQuit=false;
Shape*sp;
while (! fQuit) {
cout<<"(1)Circle (2)Rectangle (3)Square (0)Quit:";
cin>>choice;
switch (choice) {
case 0: fQuit=true; break;
case 1: sp=new Circle(5); break;
case 2: sp=new Rectangle(4,6); break;
case 3: sp=new Square(5); break;
default: cout<<"Please enter a number between 0 and 3"<<endl;
continue; break; }
if(! fQuit)
sp->Draw();
delete sp;
cout<<"\n"; }
return 0; }

SOF VIRTUAL FUNKSIYALAR


C++ sof virtual funksiyalarga ega mavhum ma'lumotlar turlarini
yaratishni qo'llab-quvvatlaydi. Sof virtual funksiyalar nol qiymat bilan
ishga tushirilganlar deb ataladi, masalan:
virtual void Draw() = 0;
Toza virtual funksiya sinfiga joylashtirish quyidagilarni anglatadi:
1. ushbu sinf obyektini yaratishning mumkin emasligi;
2. olingan sinfda sof virtual funksiyani almashtirish zarurati.
Agar Rectangle sinfi uchta sof virtual funksiyani o'z ichiga olgan
rasm sinfidan meros bo'lib o'tgan bo'lsa, u holda Rectangle sinfida
ushbu uchta funksiyaning barchasi almashtirilishi kerak.

290
Sinfni mavhum ma'lumotlar turi deb e'lon qilish uchun unga bir
yoki bir nechta toza virtual funksiyalarni qo'shish kifoya. Buning uchun
funksiyani e'lon qilgandan so'ng - 0 ni qo'shishingiz kerak, masalan:
class Shape
virtual void Draw () = 0; / / sof virtual funksiya
TEZ-TEZ VIRTUAL FUNKSIYALARNI BAJARISH
Odatda sof virtual funksiyalar mavhum asosiy sinfda e'lon qilinadi
va bajarilmaydi. Mavhum asosiy sinf obyektini yaratish mumkin
emasligi sababli, odatda toza virtual funksiyani bajarishga hojat yo'q.
Funksiya ushbu sinf obyektini yaratish uchun zarur bo'lgan Circle
sinfida almashtiriladi, ammo almashtirilgan funksiya prototipi asosiy
sinfdan sof virtual funksiyani chaqiradi. Ushbu vosita sinf usullarining
qo'shimcha funksiyalariga erishish uchun ishlatiladi.
Ushbu misolda qo'shimcha funksiya oddiy xabarni namoyish
qilishdan iborat. Haqiqiy dasturda sof virtual funksiya juda murakkab
dastur kodini o'z ichiga olishi mumkin.
Shunday qilib, hayvonlar sinfida siz Eat (), Sleep (), Move() va
Reproduce() usullarini sof virtual funksiyalar deb e'lon qilishingiz
mumkin. Keyin Animal sinfidan Mammal va Fish sinflari kelib chiqadi.
Barcha sutemizuvchilar deyarli bir xil tarzda ko'payadi degan
fikrga asoslanib, Mammal sinfida Reproduce() usulini oddiyga
aylantirish mantiqan to'g'ri keladi, shu bilan birga Eat (), Sleep() va
Move() usullarini sof virtual funksiyalar bo‘lib qoladi.
Keyin Mammal sinfidan Dog sinfi kelib chiqadi, unda Dog sinf
obyektlarini yaratish imkoniyatiga ega bo‘lish uchun qolgan uchta sof
virtual funksiyani almashtirish kerak.
Sinfni mavhum deb e'lon qilishni talab qiladigan qoidalar yo'q.
Dasturchi ushbu sinf dasturda qanday rol o'ynashi asosida mavhum
ma'lumotlar turini yaratishga qaror qiladi. Shunday qilib, agar siz
virtual fermani yoki hayvonot bog'ini modellashtirmoqchi bo'lsangiz,
unda hayvonlar sinfini mavhum deb e'lon qilish va obyektlarni yaratish
uchun undan Dog kabi boshqa sinflarni ishlab chiqarish mantiqan to'g'ri
keladi. Agar siz virtual Dogni modellashtirmoqchi bo'lsangiz, endi Dog
sinfi mavhum bo'ladi, undan turli xil Dog zotlarini ifodalovchi kichik
sinflar kelib chiqishi mumkin. Mavhum sinf darajalari soni haqiqiy
obyekt yoki hodisani qanchalik batafsil modellashtirishni
xohlayotganingizga qarab tanlanishi kerak.

291
Tavsiya etiladi!
 Barcha olingan sinflar uchun umumiy interfeys yaratish
uchun mavhum ma'lumotlar turlaridan foydalaning.
 Olingan sinflarda barcha sof virtual funksiyalarni
almashtirishga ishonch hosil qiling.
 Olingan sinflarda almashtirilishi kerak bo'lgan barcha
funksiyalarni sof virtual funksiyalar deb e'lon qiling.
Tavsiya etilmaydi!
 Mavhum sinf obyektini yaratishga urinmang.
MAVHUM SINFLARDAN FOYDALANISH
So'nggi paytlarda C++ dasturlashda mavhum mantiqiy tuzilmalarni
yaratish kontsepsiyasi faol qo'llanilmoqda. Bunday loyihalashlar
yordamida siz ko'plab umumiy vazifalar uchun yechimlarni topishingiz
va o'qish va hujjatlashtirish oson bo'lgan dasturlarni yaratishingiz
mumkin. Sinf merosidan foydalangan holda mantiqiy tuzilmani
yaratish misolini ko'rib chiqing.
Tasavvur qiling, soniyalarni hisoblay oladigan taymer sinfini
yaratishingiz kerak. Bunday sinfda itsseconds butun sonli
o'zgaruvchisi, shuningdek itsseconds o'zgaruvchisini ko'paytiradigan
usul bo‘lishi mumkin. Endi dastur itsseconds o'zgaruvchisining har bir
o'zgarishini kuzatishi va xabar qilishi kerak deb taxmin qiling. Birinchi
yechim bu Timer sinfiga a'zo o'zgaruvchining o'zgarishi to'g'risida
xabar berish usulini qo'shish. Ammo mantiqan bu mutlaqo to'g'ri emas,
chunki bildirishnoma dasturi juda murakkab bo‘lishi mumkin va aslida
vaqtni hisoblash dasturining mantiqiy qismi emas.
O'zgaruvchining o'zgarishini kuzatish va xabardor qilish dasturini
mavhum sinf sifatida ko'rib chiqarish mantiqan to'g'ri keladi, bu vaqtni
hisoblash dasturi bilan ham, vaqti-vaqti bilan o'zgarib turadigan
o'zgaruvchilar bilan har qanday boshqa dastur bilan ham teng ravishda
ishlatilishi mumkin.
Shunday qilib, eng yaxshi yechim sof virtual Update () funksiyasi
bilan Observer brauzerining mavhum sinfini yaratishdir. Endi biz
ikkinchi mavhum sinfni yaratamiz. U Observer sinfidagi obyektlar
qatorini o'z ichiga oladi. Bundan tashqari, u ikkita qo'shimcha usulni
e'lon qiladi:
Observer sinfidagi obyektlarni Listingdan o'tkazadigan Register ()
va ko'rsatilgan o'zgaruvchining o'zgarishini kuzatadigan Notify ().

292
Nihoyat, bir vaqtning o'zida ikkita asosiy sinfdan meros bo'lib
o'tgan yangi ObserverTimer sinfini yaratish mumkin - Observer va
Timer bu vaqtni hisoblash va hisobot berish imkoniyatlarini
birlashtiradi.
KO'P MEROS, MAVHUM MA'LUMOTLAR TURLARI
Ko'pgina dasturchilar Java tilining asosi C++ekanligini bilishadi.
Java dasturlash tilida ishlovchilar nuqtai nazaridan, bir nechta meros
tomonidan taqdim etilgan barcha imkoniyatlarning 90 foizini interfeys
orqali olish mumkin. Java terminologiyasidagi interfeys mavhum
ma'lumotlar turiga o'xshash narsadir, chunki u faqat olingan sinflarda
amalga oshirilishi mumkin bo'lgan funksiyalarni ham belgilaydi.
Ammo yangi sinflar to'g'ridan-to'g'ri interfeysdan kelib chiqmaydi.
Sinflar boshqa sinflardan kelib chiqadi va ularda interfeys funksiyalari
uzatiladi, bu ko‘p merosga o'xshaydi. Shunday qilib, mavhum sinflar
va ko'p merosning birlashishi atribut sinflarining analogini keltirib
chiqardi, natijada ko'p merosda bo'lgani kabi dasturiy kodlarning
haddan tashqari murakkablashuvidan qochish mumkin edi. Bundan
tashqari, interfeyslarda bajariladigan funksiyalar yoki a'zo
o'zgaruvchilar mavjud emasligi sababli, virtual merosga ehtiyoj
qolmaydi.
Ushbu o'zgarishlarning qanchalik qulay yoki maqsadga
muvofiqligi ma'lum bir dasturchining odatlariga bog'liq. Qanday
bo'lmasin, Agar siz C++ tilining ko'p meros va mavhum ma'lumotlar
turlarini yaxshi tushunsangiz, bu Javada amalga oshirilgan so'nggi
yutuqlar va dasturlash tendentsiyalarini o'rganish va o'zlashtirishda
yaxshi asos bo'lib xizmat qiladi.
Nazorat savollari va topshiriqlar:
1. Obyekt tipi nima?
2. Aytaylik, qavariq burchakli to'rtburchaklar yaratish uchun ikkita
asosiy sinfdan - Rectangle va Rounddan meros qilib olingan roundrect
sinfidan foydalaniladi, ular o'z navbatida umumiy Shape sinfidan meros
qilib olingan. Bitta roundrect sinf obyektini yaratishda qancha Shape
sinf obyektlari yaratiladi?
3. Agar Horse va Bird sinflari Animal sinfidan public spetsifikator
sifatida meros bo'lib o'tgan bo'lsa, ushbu sinflarning konstruktorlari
Animal sinf konstruktorini ishga tushiradimi? Agar Pegasus sinfi bir
vaqtning o'zida ikkita sinfdan, Horse va Birddan meros bo'lib o'tgan
bo'lsa, unda hayvonlar sinfining konstruktori qanday boshlanadi?
293
4. Jetplane (reaktiv samolyot) sinfini ikkita asosiy sinfdan - Rocket
(raketa) va Airplane (samolyot) dan meros qilib oling.
5. Avtomobil sinfidan yengil avtomobil (yo'lovchi avtomobili) va
avtobus merosxo‘r sinflarini yaratish uchun dastur yozing. Asosiy
Avtomobil sinfini ikkita sof virtual funksiyaga ega mavhum
ma'lumotlar tipi sifatida e'lon qiling. Yengil avtomobil va avtobus
sinflari mavhum bo'lmasligi kerak.

294
23-MAVZU. C++ DA MAVHUM(ABSTRACT) SINFLAR.
 Sof virtual funksiyalar
 Mavhum ma'lumotlar turlari
 Abstraktsiyalarning murakkab iyerarxiyasi
 Mavhum sinflardan foydalanish

– bu identifikatorlardan farqli bo‘lgan istalgan


dasturlash tili ifodasi hisoblanadi.
Obyektga mo‘ljallangan dasturlashda har bir obyekt prinsipial
dinamik mohiyatga ega, ya’ni u vaqtga bog‘lik holda va unga nisbatan
tashqi faktorlar ta’sirida o‘zgaradi. Abstraksiya Obyektga
mo‘ljallangan dasturlashning modeli hisoblanadi. Sinf umumiy
maydon (atribut, xususiyat) va metodlarga (usul, funksiya) ega bo‘lgan
obyektlarni birlashtiradi. Bitta sinfga mansub obyektlar bir xil
maydonlarga ega bo‘lib, bir xil metodlarni namoyon etadi.
shablon (qolip)ga o‘xshaydi: ular obyektlarning
ekzemplyarlarini (nusxalarini) tayyorlash uchun qo‘llanadi. Atributlar
- sinfning tashqaridan ko‘rinib turgan xususiyatlari. Obyekt ichki
o‘zgaruvchiga bevosita kirishni taqdim etganda yoki usul yordamida
qiymatni qaytargandagina, o‘z atributlarini namoyon qilishi mumkin.
- xabarga yoki holatning o‘zgarishiga javoban
obyekt tomonidan bajariladigan xatti-xarakatlar. U obyekt nima
qilayotganini bildiradi.
Bir obyekt ikkinchi obyekt ustida xatti-harakatlar bajarib, uning
atributlariga ta’sir ko‘rsatishi mumkin. “Xatti-harakat” atamasi o‘rniga
“usulni chaqirish”, “funksiyani chaqirish” yoki «xabarni uzatish»
atamalari qo‘llanadi.
Obyektlar o‘rtasidagi aloqa obyektga mo‘ljallangan dasturlashning
muhim tarkibiy qismidir. Obyektlar o‘zaro aloqasining ikkita asosiy
usuli mavjuddir.
Birinchi usul: obyektlar biri ikkinchisidan mustaqil ravishda
mavjud bo‘ladi. Agar alohida obyektlarga o‘zaro aloqa kerak bo‘lib
qolsa, ular bir-birlariga xabar jo‘natadi.
Xabar uzatish bu obyekt xolatini o‘zgartirish maqsadida usulni
chaqirib olish yoki xulk-atvor modellaridan birini qo‘llashning
o‘zginasidir.
Ikkinchi usul: obyekt tarkibida boshka obyektlar bo‘lishi mumkin.
Xuddi OMDda bo‘lganidek, dastur obyektlardan tashkil topganidek,
295
obyektlar ham, o‘z navbatida, boshqa obyektlardan jamlanishi mumkin.
Ushbu obyektlarning har birida usul va atributlarga ega bo‘lgan
interfeys mavjud bo‘ladi.
- bu asosiy sinf sifatida foydalanish uchun maxsus
ishlab chiqilgan sinf. Mavhum sinf kamida bitta sof virtual funksiyani
o'z ichiga oladi. Virtual a'zo funksiya deklaratsiyasida sof spetsifikator
( ) yordamida siz sof virtual funksiyani e'lon qilasiz. (= 0)
Quyida mavhum sinfga misol keltirilgan:
class AB {
public:
virtual void f() = 0;};

Funksiya AB::f sof virtual funksiyadir. Funksiyani e`lon qilish ham


sof spetsifikatsiyaga, ham taʼrifga ega boʻlishi mumkin emas. Masalan,
kompilyator quyidagilarga ruxsat bermaydi:
struct A {
virtual void g() { } = 0;
};
Siz mavhum sinfdan parametr turi, funksiyani qaytarish turi yoki
aniq konvertatsiya turi sifatida foydalana olmaysiz yoki mavhum sinf
obyektini e'lon qila olmaysiz. Biroq, siz mavhum sinfga ko'rsatgichlar
va havolalarni e'lon qilishingiz mumkin. Quyidagi misol buni
ko'rsatadi:
struct A {
virtual void f() = 0;
};
struct B : A {
virtual void f() { }
};
// Error:
// Class A is an abstract class
// A g();
// Error:
// Class A is an abstract class
// void h(A);
A& i(A&);
int main() {
// Error:
// Class A is an abstract class
// A a;
A* pa;
B b;
// Error:

296
// Class A is an abstract class
// static_cast<A>(b);
}

Sinf A mavhum sinfdir. Virtual a'zo funksiyalari meros qilib


olingan. Agar siz olingan sinfdagi har bir sof virtual funksiyani bekor
qilmasangiz, mavhum asosiy sinfdan olingan sinf ham mavhum bo'ladi.
Masalan:
class AB {
public:
virtual void f() = 0;
};
class D2 : public AB {
void g();
};
int main() {
D2 d; }
Kompilyator d obyekt e`loniga ruxsat bermaydi, chunki D2
mavhum sinfdir; f() dan AB sof virtual funksiyani meros qilib oldi.
Agar g() funksiyani aniqlasangiz, kompilyator D2::f() obyekt e`loniga
ruxsat beradi, chunki bu meros qilib olingan sof virtual AB::f()
funksiyani bekor qiladi. Agar AB::f() mavhumlikdan qochishni
istasangiz, D2 funksiya bekor qilinishi kerak.
Esda tutingki, siz mavhum bo'lmagan sinfdan mavhum sinfni
olishingiz mumkin va sof bo'lmagan virtual funksiyani sof virtual
funksiya bilan bekor qilishingiz mumkin.
Siz a'zo funksiyalarini mavhum sinfning konstruktori yoki
destruktoridan chaqirishingiz mumkin. Biroq, uning konstruktoridan
sof virtual funksiyani chaqirish natijalari (to'g'ridan-to'g'ri yoki
bilvosita) aniqlanmagan. Quyidagi misol buni ko'rsatadi:
struct A {
A() {
direct();
indirect();
}
virtual void direct() = 0;
virtual void indirect() { direct(); }
};

297
Nazorat savollari va topshiriqlar:
1. C++ da interfeys mavhum sinfidan qanday farq qiladi?
2. Sinf interfeysi nima?
3. Mavhum sinf yoki interfeys, qaysidan foydalanish yaxshiroq?
4. Sinf va mavhum sinf o'rtasidagi farq nima?
5. s fayl nomi va haqiqiy a, d sonlari berilgan. Tashqi faylga 1-hadi
a ga ayirmasi d ga teng bo‘lgan arifmetik progressiyaning dastlabki 10
ta hadining qiymatlari yozilsin.
6. 4 ta faylning nomi berilgan. Joriy katalogda joylashgan shu
nomlar bilan berilgan fayllar soni topilsin.
7. Butun sonli fayl nomi berilgan. Fayldagi elementlar soni
topilsin. Agar bunday nomdagi fayl topilmasa – 1 chiqarilsin.
8. Haqiqiy sonli fayl berilgan. 2 ta yangi fayl tuzilsin: 1-faylga
berilgan fayldagi toq nomerdagi sonlar, 2-faylga esa berilgan fayldagi
juft nomerdagi sonlar chop etilsin.
9. Haqiqiy sonli fayl berilgan. 2 ta yangi fayl tuzilsin: 1-faylga
berilgan fayldagi juft nomerdagi sonlar, 2-faylga esa berilgan fayldagi
toq nomerdagi sonlar chop etilsin.

298
24-MAVZU. C++ DA TRY, CATCH.
 Favqulodda vaziyatlar
 Istisnolar qanday ushlanadi va qayta ishlanadi
 Istisnolarni meros qilib olish
 Xatolarni kuzatish va tuzatishning umumiy tuzilmasida
istisnolardan foydalanish
Ushbu kitobda keltirilgan dastur kodi illyustratsion maqsadlarda
yaratilgan. Sizni dasturning ma'lum bir qismida keltirilgan asosiy
dasturlash nuqtalaridan chalg'itmaslik uchun biz mumkin bo'lgan
xatolar haqida gapirmadik. Haqiqiy dasturlar, albatta, mumkin bo'lgan
favqulodda vaziyatlarni ta'minlashi kerak.
XATOLAR VA "ESKI" KOD
Afsuski, barcha dasturchilar xato qilishadi. Dastur qanchalik katta
bo'lsa, unda xatolar paydo bo‘lishi ehtimoli shunchalik yuqori bo'ladi,
ularning aksariyati hozircha e'tiborga olinmaydi va bozorga chiqarilgan
yakuniy dasturiy mahsulotga tushadi. Ushbu haqiqatni qabul qilish
qiyin, shuning uchun ishonchli, xatosiz dasturlarni yaratish har bir
dasturchi uchun birinchi sonli vazifa bo‘lishi kerak.
Dasturiy ta'minot sanoatidagi eng dolzarb muammolardan biri bu
xatolar bo‘lgan dastur kodidir. Odatda dasturlash bilan bog'liq ko'plab
ishlarda eng katta xarajatlar dasturlarni sinovdan o'tkazish va xatolarni
tuzatishdir. Qisqa vaqt ichida va arzon narxlarda mustahkam, ishonchli
va muammosiz dasturlarni yaratish muammosini hal qilgan kishi butun
dasturiy mahsulotlar sanoatida inqilob qiladi.
Dasturlardagi barcha xatolarni bir necha guruhga bo‘lish mumkin.
dasturni bajarish algoritmining yetarli
darajada ishlab chiqilmagan mantig'idan kelib chiqadi.
- sintaktik xatolar, ya'ni noto'g'ri idioma, funksiya yoki
tuzilmadan foydalanish. Ushbu ikki turdagi xatolar eng keng tarqalgan,
shuning uchun ular dasturchilar diqqat markazida.
Nazariya va amaliyot shuni isbotladiki, keyinchalik rivojlanish
jarayonida muammo aniqlansa, uni yo'q qilish shunchalik qimmatga
tushadi. Ma'lum bo‘lishicha, dasturlardagi muammolar yoki xatolar,
agar ularning paydo bo‘lishining oldini olish uchun o'z vaqtida choralar
ko'rilsa, kompaniyaga eng arzon bo'ladi. Kompilyator tomonidan tan
olingan xatolar ham juda qimmatga tushmaydi. C++ tili standartlari
ishlab chiquvchilarni dasturni kompilyatsiya qilish bosqichida iloji

299
boricha ko'proq xatolarni aniqlay oladigan kompilyatorlarni yaratishga
majbur qiladi.
Mantiqiy yoki sintaktik xatolardan ham kattaroq muammo bu
dasturlarning yetarli darajada barqaror emasligi, ya'ni agar
foydalanuvchi taqdim etilgan ma'lumotlarni kiritsa, dastur yaxshi
ishlaydi, ammo xato bilan, masalan, son o'rniga matn kiritilsa, u
ishlamay qoladi.
Dasturlarning barqarorligini oshirish uchun dasturchilar
kutilmagan vaziyatlarning barcha variantlarini oldini olishga
intilishadi. Foydalanuvchi tomonidan kiritilgan nostandart
ma'lumotlarni olishdan tortib, kompyuter xotirasini to‘ldirishgacha
bo'lgan har qanday kutilmagan hodisalarni yengish mumkin bo'lgan
dastur bo‘lib hisoblanadi.
Dasturiy ta'minot kodining noto'g'ri sintaksisidan kelib chiqadigan
xatolarni, dasturchi muammoni noto'g'ri talqin qilgani yoki noto'g'ri hal
qilganligi sababli yuzaga keladigan mantiqiy xatolarni va bashorat
qilinadigan muammolar tufayli yuzaga keladigan favqulodda
vaziyatlarni, masalan, resurslarning ziddiyatlari bilan bog'liq (xotira
yoki disk maydoni yetishmasligini anglatadi).
ISTISNO HOLATLAR
Sintaksis xatolarini aniqlash uchun dasturchilar o'rnatilgan
kompilyator vositalaridan foydalanadilar va dasturlarga turli xil xato
“tuzoq”larini qo'shadilar. Mantiqiy xatolarni aniqlash uchun loyihalash
yechimlarini tanqidiy tahlil qilish va dasturiy mahsulotni har
tomonlama sinovdan o'tkazish amalga oshiriladi.
Biroq, biror bir dasturda istisno holatlar yuzaga kelishi ehtimolini
bartaraf etish mumkin emas. Dasturchi qila oladigan yagona narsa bu
dasturni ularning paydo bo‘lishiga tayyorlashdir. Masalan, dasturni
bajarish paytida kompyuter xotirasining to'lib ketishini oldini olish
uchun dasturlash vositalaridan foydalanish mumkin emas, ammo dastur
ushbu vaziyatda o'zini qanday tutishi dasturchiga bog'liq.
Siz quyidagi dastur javob variantlarini tanlashingiz mumkin:
 dasturni favqulodda to'xtashga olib boring;
 foydalanuvchini nima bo'lganligi haqida xabardor qiling va
dasturdan to'g'ri chiqing;
 foydalanuvchini xabardor qiling va unga dasturning ish
holatini tiklashga va ishlashni davom ettirishga ruxsat bering;

300
 vaqtinchalik yechimni tanlang va foydalanuvchini bezovta
qilmasdan dasturni davom ettiring.
Oxirgi variant, ya'ni vaqtinchalik yechimni tanlash, albatta,
dasturning favqulodda to'xtashidan afzalroqdir. Ushbu parametr har bir
dasturda zarur yoki hatto kerakli bo'lmasa-da, shunga qaramay, barcha
favqulodda vaziyatlarni mustaqil ravishda, avtomatik ravishda va
ishlashni davom ettiradigan kodni yozishga arziydi.
C++ tili dastur davomida yuzaga kelishi mumkin bo'lgan barcha
favqulodda vaziyatlarni kuzatish uchun xavfsiz, integratsiyalashgan
usullarni taqdim etadi.
"ESKIRGAN" KOD HAQIDA BIR NECHA SO'Z
Dasturiy mahsulot vaqt o'tishi bilan eskirish mumkinligi
isbotlangan. Buni stolingiz ustida anchadan beri turgan olmaga
qiyoslash mumkin. Bu hodisa deyarli har qanday kodda yashirin ichki
xatolar mavjud bo'lib, ularga eski dasturning yangi kompyuter
dasturlari va dasturiy ta'minot muhitiga mos kelmasligi qo'shiladi.
Mukammal yozilgan va yaxshi dastur juda tez foydalanuvchi e'tiborini
jalb qilmaydigan narsalarga aylanishi mumkin.
Yuzaga kelgan xatolarni tezda tuzatish va dasturni joriy kun
talablariga muvofiq modernizatsiya qilish uchun siz nafaqat siz, balki
boshqa har qanday dasturchi ham bir muncha vaqt o'tgach uni tushunish
uchun dastur kodini yozishingiz kerak.
ESLATMA: "Eskirgan" kod-bu dasturchilar tomonidan yaxshi
dasturlarning to'satdan ishonchsiz va samarasiz bo'lib qolishini
tushuntirish uchun yaratilgan hazil atamasi. Bunday "eski kod" dan
himoya qilish uchun siz kodni yozishingiz kerak, shunda uning
ishlashini o'zingiz saqlab qolish oson bo'ladi.
ISTISNOLAR
C++ da - bu muammo yuzaga kelgan kod maydonidan
ushbu muammo ko'rib chiqiladigan kod qismiga uzatiladigan obyekt.
Istisno turi kodning qaysi sohasi muammoni hal qilishini va agar
mavjud bo'lsa, uzatilgan obyektning tarkibi foydalanuvchi bilan fikr-
mulohaza uchun qanday ishlatilishini aniqlaydi.
Istisnolardan foydalanishning asosiy g'oyasi juda oddiy.
Resurslarning haqiqiy taqsimlanishi (masalan, xotira taqsimoti yoki
faylni yozib olish) odatda dasturda past darajada amalga oshiriladi.

301
ISTISNOLAR QANDAY ISHLATILADI?
Muammoga olib kelishi mumkin bo'lgan kod parchalarini
joylashtirish uchun try bloklari yaratiladi, masalan:
try
{ SomeDangerousFunction(); }
Sinov bloklarida yuzaga keladigan istisnolar catch bloklarida qayta
ishlanadi, masalan:
try SomeDangerousFunction();
catch(OutOfMemory)
// ba'zi harakatlarni amalga oshirish catch (FileNotFound)
// biz boshqa harakatlar qilamiz
Quyida istisnolardan foydalanishning asosiy tamoyillari
keltirilgan.
1. Istisno vaziyatni keltirib chiqarishi mumkin bo'lgan amal
boshlanadigan dastur maydonlarini aniqlang va ularni sinab ko'rish
bloklariga joylashtiring.
2. Istisnolarni ushlab qolish, ajratilgan xotirani tozalash va
foydalanuvchini tegishli ravishda xabardor qilish uchun catch
bloklarini yarating. 24.1 Listingida try va catch bloklaridan foydalanish
ko'rsatilgan.
-bu muammo haqida ma'lumot uzatish uchun
ishlatiladigan obyektlar.
-bu g'ayrioddiy vaziyatlarni keltirib chiqarishi mumkin
bo'lgan dastur qismlarini o'z ichiga olgan figurali qavs ichidagi blok.
-bu sinab ko'rish blokidan keyin keladigan va
istisnolarni qayta ishlash amalga oshiriladigan blok.
Agar favqulodda vaziyat yuzaga kelsa, boshqaruv joriy sinov
blokidan so'ng darhol catch blokiga o'tkaziladi.
ESLATMA: Ba'zi juda eski kompilyatorlar istisnolarni qayta
ishlashni qo'llab-quvvatlamaydi. Biroq, istisnolarni qayta ishlash ANSI
C++standartining bir qismidir. Kompilyatorlarning barcha zamonaviy
versiyalari ushbu imkoniyatni to'liq qo'llab-quvvatlaydi.

302
FAVQULODDA VAZIYATLARNI KUZATISH BLOKI
Ushbu blok kalit so'zidan keyin ochiladigan figurali qavs bilan
boshlanadigan ifodalar to'plamidir, yopuvchi figurali qavs bilan
tugaydi.
Misol:
try
Function();
{
istisno vaziyatlarni qayta ishlash birligi
}
Ushbu blok qatorlar to'plamidir, ularning har biri kalit so'zi
bilan boshlanadi, so'ngra qavs ichida istisno turi beriladi. Keyin
ochiladigan figurali qavs keladi. Catch bloki yopiladigan figurali qavs
bilan tugaydi.
Misol:
try
Function();
catch (OutOfMemory) // harakatni bajarish
{
}
TRY VA CATCH BLOKLARIDAN FOYDALANISH
Blokning joylashuvini aniqlashga urinayotganda, dasturda xotira
yoki boshqa manbalar qayerda taqsimlanishini aniqlang. Agar
qiymatlarni ruxsat etilgan chegaralardan tashqariga chiqarish, noto'g'ri
ma'lumotlarni kiritish va boshqalar bilan bog'liq xatolar bo'lsa, siz
boshqa yondashuvlardan foydalanishingiz kerak.
Istisno yaratilganda, murojaatlar to'plami tekshiriladi. Istisno har
bir ichki blok uchun murojaatlar to'plamiga o'tkaziladi. Stack o'tishi
bilan local obyektlar uchun destruktorlar chaqiriladi va bu
obyektlarning yo'q qilinishiga olib keladi.
Har bir harakat blokidan keyin bir yoki bir nechta catch bloklari
keladi. Agar yaratilgan istisno catch operatorlarining istisnolaridan
biriga to'g'ri kelsa, u holda ushbu operatorning blok kodi bajariladi.
Agar catch operatorlarining hech biri istisnoga mos kelmasa, Stack
o'tishi davom etadi.
Stack istisnosidan o'tishni bir tomonlama ko'chada sayohat qilish
bilan taqqoslash mumkin. Stack o'tishi bilan uning obyektlari yo'q
qilinadi. Orqaga yo'l yo'q. Agar istisno ushlanib qolsa va qayta ishlansa,
dastur ushbu istisnoni ushlab qolgan catch blokidan keyin ham davom
etadi.

303
Esda tutingki, agar favqulodda vaziyat yuzaga kelsa, dasturni
amalga oshirish u paydo bo'lgan joydan keyin emas, balki catch
blokidan keyin davom etadi.
BIR NECHTA CATCH OPERATORLARIDAN
FOYDALANISH
Ba'zi hollarda, bitta ifodani bajarish bir nechta istisno holatlar
bo‘lishi mumkin. Bunday holda, switch operatori bilan loyihalashga
o'xshash bir-birini ta'qib qiladigan bir nechta catch operatorlaridan
foydalanish kerak. Bunday holda, default operatorining ekvivalenti
(...) ifodasi bo'ladi, uni "hamma narsani ushlab turish"deb
tushunish kerak.

Istisnolar sinflardir va ulardan boshqa sinflar kelib chiqishi


mumkin.
Aytaylik, biz xsize sinfini yaratishimiz va undan xZero,
xTooSmall, xTooBig va xNegative merosxo‘r sinflarini olishimiz
kerak. Natijada, ba'zi funksiyalar uchun size xatosini ushlab turish
o'rnatilishi mumkin, boshqalari uchun xsize xato turlarini ushlab turish
mumkin.
Ushbu g'oyani amalga oshirish listing 24.1 da ko'rsatilgan.
Listing 24.1. Istisnolarni meros qilib olish
#include<iostream>
using namespace std;
const int DefaultSize=10;
class Array {
public:
Array(int itsSize=DefaultSize);
Array(const Array&rhs);
~Array(){delete[] pType;}
Array& operator=(const Array&);
int& operator[](int offSet)const;
int GetitsSize() const{ return itsSize;}
friend ostream& operator<<(ostream&, const Array&);
class xBoundary {};
class xSize {};
class xTooBig: public xSize{};
class xTooSmall: public xSize{};
class xZero:public xTooSmall{};
class xNegative: public xSize{};
private:
int *pType;
int itsSize; };
Array::Array(int size):

304
itsSize(size) {
if (size==0)
throw xZero();
if (size>30000)
throw xTooBig();
if (size<1)
throw xNegative();
if(size<10)
throw xTooSmall();
pType=new int[size];
for (int i=0; i<size; i++)
pType[i]=0; }
int& Array::operator[](int offSet) const {
int size=GetitsSize();
if(offSet>=0&& offSet<GetitsSize())
return pType[offSet];
throw xBoundary();
return pType[0]; }
int main() {
try {
Array intArray(0);
for(int j=0; j<100; j++)
{ intArray[j]=j;
cout<<"intArray["<<j<<"]okay...\n"; } }
catch (Array::xBoundary)
{ cout<<"Unable to process your input!\n"; }
catch (Array::xTooBig)
{ cout<<"This array is too big...\n"; }
catch (Array::xTooSmall)
{ cout<<"This array is too small...\n"; }
catch (Array::xZero)
{ cout<<"You asked for an array";
cout <<"of zero objects!\n"; }
catch(...)
{ cout<<"Somthing went wrong!\n"; }
cout<<"Done.\n";
return 0; }
Ko'pincha, dastur xatoga to'g'ri javob berishi uchun, yuzaga kelgan
istisno turidan ko'ra ko'proq narsani bilish foydalidir. Istisno sinflari
boshqa sinflar bilan bir xil.
ESLATMA: Istisnolar bilan ishlashda ularning mohiyatini yodda
tutish kerak. Agar siz OutOfMemory istisnosini yaratayotgan
bo'lsangiz, unda ushbu sinf konstruktori biror bir obyekt uchun xotira
ajratishga urinmasligi kerak.
Ushbu loyihalashlarning barchasini catch operatorlari bilan qo'lda
yozish juda zerikarli, ularning har biri o'z xabarlarini chiqarishi kerak.

305
Bundan tashqari, dastur hajmining oshishi bilan undagi xatolar ehtimoli
tezda oshadi.
ISTISNOLAR VA SHABLONLAR
Shablonlar bilan ishlashga mo'ljallangan istisnolarni yaratishda
ikkita yechim mavjud. Siz to'g'ridan-to'g'ri shablonda istisno
yaratishingiz mumkin, keyin ular shablonning har bir nusxasi uchun
mavjud bo'ladi yoki shablon prototipidan tashqarida yaratilgan istisno
sinflaridan foydalanishingiz mumkin.
Istisnolardan foydalanish faqat taxmin qilinadigan istisno
vaziyatlarni kuzatish bilan cheklanishi kerak, degan fikr bor, buning
uchun aslida istisnolar yaratilgan.
Istisnolardan foydalanish qanchalik to'g'ri ekanligini hal qilish
uchun quyidagi savollarga javob berishga harakat qiling: natijada dastur
osonlashadimi yoki aksincha, tushunish qiyinlashadimi; xatolar rostan
ham kamayadimi; bunday dasturni qo'llab-quvvatlash qiyinroq yoki
osonlashadimi? Albatta, ushbu savollarga obyektiv javob berish qiyin:
ko'p narsa dasturchining odatlari va subyektiv qarashlariga bog'liq, shu
sababli, ushbu savollar atrofida tortishuvlar paydo bo'ladi.
XATOLAR VA DASTURNI DISK RASKADROVKA
QILISH
Deyarli barcha zamonaviy rivojlanish muhitlari bir yoki bir nechta
o'rnatilgan samarali tuzatuvchilarni o'z ichiga oladi. Nosozliklarni
tuzatuvchidan foydalanishning asosiy g'oyasi quyidagicha: tuzatuvchi
dasturning dastur kodini dasturning alohida satrlari bajarilishini
kuzatish va xatolarni aniqlash uchun qulay rejimda yuklaydi va
bajaradi.
Barcha kompilyatorlar dasturlarni belgilar yordamida yoki ularsiz
kompilyatsiya qilishga imkon beradi. Belgilar bilan kompilyatsiya
qilish kompilyatorga dastur fayllarining dastur kodi va yaratilgan dastur
o'rtasidagi munosabatlarni o'rnatish zarurligini ko'rsatadi, shuning
uchun tuzatuvchi dasturingizdagi keyingi harakatga mos keladigan
dastur kodi qatorini ko'rsatishi mumkin.
Ko'pgina nosozliklarni tuzatuvchilar bilan ishlashda har bir
buyruqning ishlash natijalarini ko'rish uchun dastur kodi va ekran
chiqarishi o'rtasida almashish mumkin. Bundan tashqari, har qanday
o'zgaruvchining joriy qiymatini, shu gapdan sinf a'zolari
o'zgaruvchilarini va dastur ko'rsatgichlari tomonidan havola qilingan
dinamik almashinuv maydoni kataklaridagi qiymatlarni aniqlash,
306
shuningdek murakkab ma'lumotlar tuzilmalarini ko'rish imkoniyati
foydalidir. Nosozliklarni tuzatuvchilar dastur kodida to'xtash
nuqtalarini o'rnatish, o'zgaruvchilarning mos yozuvlar qiymatlarini
chiqarish, xotirani taqsimlash xususiyatlarini o'rganish va assembler
kodini ko'rish imkonini beradigan bir qator yordamchi dasturlarini
taqdim etadi.
TO'XTASH NUQTALARI
- bu tuzatuvchi uchun mo'ljallangan buyruqlar
va dastur belgilangan qatorni bajarishdan oldin to'xtashi kerakligini
anglatadi. Ushbu vosita dasturni to'xtash nuqtasi o'rnatilgan joyga
odatdagidek bajarish orqali disk raskadrovka paytida vaqtni tejashga
imkon beradi. Dasturning bajarilishini to'xtatgandan so'ng, siz
o'zgaruvchilarning joriy qiymatlarini tahlil qilishingiz yoki dasturni
bosqichma-bosqich davom ettirishingiz mumkin.

O'ZGARUVCHILAR QIYMATLARINI TAHLIL QILISH


Nosozliklarni tuzatuvchiga ma'lum bir o'zgaruvchining qiymatini
ko'rsatish yoki berilgan o'zgaruvchi o'qilganda yoki yozilganda
dasturning qolgan qismini ko'rsatish mumkin.
Tuzatuvchi hatto dasturni bajarish jarayonida o'zgaruvchining
qiymatini o'zgartirishga imkon beradi.
ASSEMBLER KODI
Ba'zida xatoni aniqlash uchun dastur kodini o'qish yetarli bo‘lsada,
tuzatuvchiga dastur kodining har bir satri uchun yaratilgan haqiqiy
assembler kodini ko'rsatish mumkin. Siz xotira registrlari qiymatlarini
ko'rishingiz mumkin va agar xohlasangiz, mashina kodiga kerakli
darajada chuqurroq kirishingiz mumkin.

Nazorat savollari va topshiriqlar:


1. Istisno nima?
2. Try bloki nima uchun?
3. Catch operatori nima uchun ishlatiladi?
4. Istisno qanday ma'lumotlarni o'z ichiga olishi mumkin?
5. Istisno obyekti qachon yaratiladi?
6. Istisnolarni qiymatlar yoki havolalar sifatida o'tkazish kerakmi?
7. Catch operatori, agar u asosiy istisno sinfiga o'rnatilgan bo'lsa,
istisno hosilalarini ushlab turadimi?

307
8. Agar ikkita catch operatori ishlatilsa, ulardan biri asosiy xabarga,
ikkinchisi esa hosilaga sozlangan bo'lsa, unda ular qanday tartibda
joylashtirilishi kerak?
9. Catch ( ... ) operatori nimani anglatadi?
10. To'xtash nuqtasi nima?
11. Oddiy istisnoni kuzatish va qayta ishlash uchun try blokini va
catch operatorini yozib oling.
12. 11-mashqda olingan istisnoga a'zo o'zgaruvchisi va kirish
usulini qo'shing va ularni catch operator blokida ishlating.
13. 12-mashqda olingan istisnodan yangi istisnoni meros qilib
oling. Catch operator blokini shunday o'zgartiringki, u ham lotin, ham
asosiy istisnolarni qayta ishlaydi.
14. Uch darajali funksiya chaqiruvini olish uchun 13-mashq kodini
o'zgartiring.
15. Xatolar: quyidagi koddagi xatolikni toping?
#include "string"
// qatorlar sinfi
class xOutOfMemory
{
public:
xOutOfMemory()( theMsg = new char[20];
stropy(theMsg, "error in memory");}
xOutOfMemory(){ delete [] theMsg;
cout<< "Memory restored. " << endl; }
char * Message() { return theMsg;
private:
char * theMsg;
main()
{
try
{
char * var = new char;
if ( var == 0 )
{
x0ut0fMemory * px =
new x0ut0fMemory;
throw px;
}
308
}
catch( x0utOfMemory * theException )
cout << theException->Message() <<endl;
delete theException;
return 0;}

309
NAZORAT UCHUN TEST SAVOLLARI

1. Identifikator nima?
a) katta va kichik lotin harflari, sonlar va tag chiziq (‘_’) belgilaridan
tashkil topgan va sondan boshlanmaydigan belgilar ketma-ketligi
b) katta va kichik lotin harflari, sonlar va tag chiziq (‘_’) belgilaridan
tashkil topgan va faqat sondan boshlanuvchi belgilar ketma-ketligi
c) katta va kichik lotin harflaridan tashkil topgan ketma-ketlik
d) katta va kichik lotin harflari, sonlar va tag chiziq (‘_’) belgilaridan
tashkil topgan va tag chiziq (‘_’) bilan boshlanmaydigan belgilar ketma-
ketligi

2. Blok bu –
a) '{' va '}' belgi oralig’iga olingan operatorlar ketma-ketligi, u
kompilyator
b) '(' va ')' belgi oralig’iga olingan operatorlar ketma-ketligi, u
kompilyator tomonidan yaxlit ir operator deb qabul qilinadi
c) '/*' va '*/' belgi oralig’iga olingan operatorlar ketma-ketligi, u
kompilyator tomonidan yaxlit ir operator deb qabul qilinadi
d) '[' va ']' belgi oralig’iga olingan operatorlar ketma-ketligi, u
kompilyator tomonidan yaxlit ir operator deb qabul qilinadi

3. C++ tilida konsol rejimda ishlash jarayonida ma’lumotlarni ekranga


chiqarish formati to’g’ri ko’rsatilgan javobni toping.
a) cout<<<ifoda>
b) cin>><o’zgaruvchi>
c) cout>><ifoda>
d) To’g’ri javob keltirilmagan

4. C++ tilida konsol rejimda ishlash jarayonida berilganlarni o’qish


formati to’g’ri ko’rsatilgan javobni aniqlang.
a) cin>><o’zgaruvchi>
b) cout<<<ifoda>
c) cin<<<o’zgaruvchi>
d) cout>><o’zgaruvchi>

5. C++ tilida haqaqiy sonning butun va kasr qismlari qaysi belgi


yordamida ajratiladi?
a) Nuqta “.”
b) Vergul “,”

310
c) Nuqta vergul “;”
d) Slash “/”
e)

6. Quyidagi programma qismi nima natija chiqaradi?


float a=1234; cout<<a/100;
a) 12.34
b) 12
c) 34
d) 1.234

7. Quyidagi programma qismi nima natija chiqaradi?


int a=6789; cout<<a/100;
a) 67
b) 6789
c) 89
d) 678

8. Quyidagi programma qismi nima natija chiqaradi?


a) 46
b) 68
c) 468
d) 6

9. Identifikator sifatida foydalanish mumkin bo’lmagan javobni


ko’rsating.
a) Int
b) a
c) A7
d) Pi

10. Identifikator sifatida foydalanish mumkin bo’lmagan javobni


ko’rsating.
a) float
b) abc
c) A3
d) kiCHik

311
Test savollari
1. C++ tilida quyidagi amallar bajarilganda javob nechchi chiqadi?
int c=25/3;
a) 8
b) 9
c) 8.(3)
d) 8.3

2. C++ tilidagi quyidagi dastur qismidagi sintaktik xato kodni toping?


int c=25/3; x = 5; z = 3; y = x – z; z = 2 * y + 3;
a) x = 5;
b) y = x – z;
c) z = 2 * y + 3;
d) int c=25/3;

3. x=2, u=5 va z=6 ga teng bo’lsa, Quyidagi amallar ketma-ketligini


bajarilishi natijasida ekranga nima chiqadi?
cout << "x = " << x << ", y = " << y << ", z = " << z;
a) x = 2, y = 5, z = 6
b) x = 22, y = 52, z = 62
c) x = <2, y = <5, z = <6
d) x=2 y=5 z=6

4. x=2, u=5 va z=6 ga teng bo’lsa, Quyidagi amallar ketma-ketligini


bajarilishi natijasida ekranga nima chiqadi?
cout << "x + y = " << x + y;
a) x+y=7
b) x + y = 11
c) 7
d) 25

5. x=22, u=5 va z=6 ga teng bo’lsa, Quyidagi amallar ketma-ketligini


bajarilishi natijasida ekranga nima chiqadi?
cout << "x / z = " << x / y;
a) x/z=4
b) x/z=3
c) x / z = 3.7
d) x/z= x/y

312
6. x=13, u=2 va z=11 ga teng bo’lsa, Quyidagi amallar ketma-ketligini
bajarilishi natijasida ekranga nima chiqadi?
cout << (x + z) % y;
a) 0
b) 12
c) 1
d) 2

7. x=13, u=2 va z=11 ga teng bo’lsa, Quyidagi amallar ketma-ketligini


bajarilishi natijasida ekranga nima chiqadi?
cout << x + z % y;
a) 14
b) 0
c) 1
d) 2

8. x=13, u=2 va z=11 ga teng bo’lsa, Quyidagi amallar ketma-ketligini


bajarilishi natijasida ekranga nima chiqadi?
cout << (y + z) % y;
a) 2
b) 1
c) 0
d) 112

9. x=13, u=2 va z=11 ga teng bo’lsa, Quyidagi amallar ketma-ketligini


bajarilishi natijasida ekranga nima chiqadi?
cout << (x % y) % z ;
a) 1
b) 12
c) 0
d) 2

10. C++ tilidagi quyidagi dastur qismidagi sintaktik xato kodni toping?
int c=25/3, x = 5; z = 3; y = x – z; z = 2 * y + 3;
a) z = 3;
b) y = x – z;
c) z = 2 * y + 3;
d) int c=25/3;

313
Test savollari
1. short turidagi o’zgaruvchining qabul qiladigan qiymatlar oralig’i?
a) -32768...32767
b) 0..65535
c) 0..32767
d) -2147483648.. 2147483647

2. C++ tilida char turidagi o’zgaruvchilarning qabul qiladigan qiymatlar


oralig’i to’g’ri ko’rsatilgan javobni aniqlang.
a) 0..255
b) -128..127
c) 0..32
d) -32768..32767

3. C++ tilida double turidagi o’zgaruvchilar xotirada qancha joy


egallaydi?
a) 8bayt
b) 4 bayt
c) 2 bayt
d) 1 bayt

4. Identifikator sifatida foydalanish mumkin bo’lmagan javobni


ko’rsating.
a) While
b) katta
c) kichik
d) B12

5. Identifikator sifatida foydalanish mumkin bo‘lgan javobni


ko’rsating.
a) dasTuR
b) int
c) double
d) char

6. C++da operatorlar qanday belgi bilan ajratiladi?


a) ;
b) “ ” (probel)
c) :
d) ,

314
7. 32 razryadli tizimda int tipi kompyuter xotirasidan qancha joy
egallaydi.
a) 4 bayt
b) 2 bayt
c) 6 bayt
d) 8 bayt
8. Qaysi toifa formatdagi qiymat kompyuter xotirasidan eng katta joy
egallaydi.
a) long double
b) double
c) int
d) float

9. C++ tilida butun son turidagi o’zgaruvchilar qaysi kalit so’z


yordamida aniqlanadi?
a) int
b) float
c) void
d) double

10. C++ tilida belgi turidagi o’zgaruvchilar qaysi kalit so’z yordamida
aniqlanadi?
a) char
b) string
c) double
d) void

Test savollari
1. C++ da quyidagi operatorlar ketma-ketligi bajarinishi natijasida
ekranga nima chiqadi? cout<< "3 / 2 + 5.5 = " << 3 / 2 + 5.5 <<endl;
a) 3 / 2 + 5.5 = 6.5
b) 6.0
c) 2 + 5.5
d) 6.5

2. C++ da quyidagi operatorlar ketma-ketligi bajarinishi natijasida


ekranga nima chiqadi? cout<<static_cast<int>(7.9);
a) 7
b) 7.0

315
c) 0.9
d) 7.9

3. C++ da quyidagi operatorlar ketma-ketligi bajarinishi natijasida


ekranga nima chiqadi? cout<<static_cast<int>(7.8 + static_cast<double>(15
/ 2));
a) 14
b) 15
c) 14.5
d) 15.3

4. Quyidagi dastur kodining natijasini toping.


num2 = 4 * 5 - 11; cout<< "num2 = " << num2 <<endl;
a) num2 = 9
b) 4 * 5 – 11 = 9
c) num2 = -24
d) num2 = 19

5. Quyidagi dastur kodining natijasini toping.


num2 = 4 / 5 - 11; cout<< num2 <<endl;
a) -11
b) 10.2
c) -10.2
d) 11

6. Quyidagi dastur kodining natijasini toping.


num2 = 4 % 5 + 5%4; cout<< num2 <<endl;
a) 5
b) 0
c) 9
d) 2.05

7. Quyidagi dastur kodining natijasini toping.


num2 = 4 / 5 – 4 % 5; cout<< num2 <<endl;
a) -4
b) 4
c) 5
d) 11

8. Quyidagi dastur kodining natijasini toping.

316
num2 = 4 *3 + 7 / 5 – 25.5; cout<< num2 <<endl;
a) -12.5
b) 10.5
c) -12
d) 12

9. Quyidagi dastur kodining natijasini toping.


num = 6; num = num + 2; cout<< num <<endl;
a) 8
b) 10
c) -2
d) 2
10. Quyidagi ifodalarning ichidan xato ifodani aniqlang.
a) q = % a + b + c + d / 4;
b) c = (a % b) * 6;
c) d = c / b;
d) e = (a + b + c + d) / 4;

317
Test savollari
1. C++ tilida konsol rejimda ishlash jarayonida berilganlarni standart
oqimdan o’qish formati to’g’ri ko’rsatilgan javobni aniqlang.
a) cin>> <o’zgaruvchi>
b) cout<< <ifoda>
c) cin<< <o’zgaruvchi>
d) cout>><o’zgaruvchi>

2. C++ tilida konsol rejimda ishlash jarayonida ma’lumotlarni standart


oqimga (ekranga)chiqarish uchun to’g’ri format keltirilgan javobni toping.
a) cout<< <ifoda>
b) cin>> <o’zgaruvchi>
c) cout>> <ifoda>
d) To’g’ri javob keltirilmagan

3. Quyidagi programma ishlashi natijasida ekranda qanday qiymat aks


etadi?
#include <iostream.h>
int main (){
int a=10, b;
b=a%10;
cout<<b;
return 0; }
a) *0
b) 1
c) 10
d) 100

4. Quyidagi programma ishlashi natijasida ekranda qanday qiymat aks


etadi?
#include <iostream.h>
int main (){
int a=10, b;
if (a%2==0) b=a*a;
else
b=-a;
cout<<b;
return 0; }
a) *100
b) -10

318
c) 10
d) 0
5. Quyidagi programma ishlashi natijasida ekranda qanday qiymat aks
etadi?
#include <iostream.h>
int main (){
int a=10, b=23;
switch(a){
case 1: c=a+b; break;
case 2: c=a*b; break;
default: c=(a+b)*b; break;
}
cout<<c;
return 0; }
a) *759
b) 33
c) 230
d) xatolik haqida habar beradi

6. Oqimdan satrni o’qishga mo’ljallangan gets() funksiyasining


prototipi to’g’ri ko’rsatilgan javobni aniqlang.
a) *char* gets(char *s);
b) char gets(char *s);
c) char* gets(char s);
d) string* gets(string *s);
7. C++ tilida belgi turidagi o’zgaruvchilar qaysi kalit so’z yordamida
anilanadi?
a) *char
b) string
c) double
d) int
8. C++ tilida belgi turidagi o’zgaruvchilar qaysi kalit so’z yordamida
anilanadi?
a) *char
b) string
c) double
d) int
9. C++ tilida char turidagi o’zgaruvchilarning qabul qiladigan qiymatlar
oralig’i to’g’ri ko’rsatilgan javobni aniqlang.
a) *0..255

319
b) -128..127
c) 0..32
d) -32768..32767
10. Agar o’qsih muvafaqiyatli bo’lsa getc() funksiyasi qanday qiymat
qaytaradi?
a) *ishorasiz int ko’rinishidagi qiymatni
b) EOF ni qaytaradi
c) ishorasli int ko’rinishidagi qiymatni
d) Haqiqiy sonni

Test savollari
1. Quyidagi programma qismi ishlashi natijasida ekranga qanday
qiymat chiqadi?
int a=4, b=8, y; y=a>b?a:b; cout<<y;
a) 8
b) 5
c) 12
d) 0.5

2. Quyidagi programma qismi ishlashi natijasida ekranga qanday


qiymat chiqadi?
int a=10, b=23;
switch(a){
case 1: c=a+b; break;
case 2: c=a*b; break;
default: c=(a+b)*b; break;
}
cout<<c;
a) 759
b) 33
c) 230
d) Xatolik haqida xabar beradi

3. Quyidagi programma qismi ishlashi natijasida ekranga qanday


qiymat chiqadi?
int a = 7, b = 8;
if (a == b++)
a += a;
else if(a % 2 == 0)
a += b * b;

320
else
a += b; cout<<a;
a) 16
b) 15
c) 56
d) 1

4. Quyidagi programma qismi ishlashi natijasida ekranga qanday


qiymat chiqadi?
int a=1, b=2, s=4;
if (a+b==fabs(a-b)) s=s+a;
if (a-b==fabs(a-b)) s=s-a;
cout << s;
a) 4
b) 3
c) 2
d) 1

5. Quyidagi programma qismi ishlashi natijasida ekranga qanday


qiymat chiqadi?
int k=8786, s,b=10,b1=1000;
if(k%b+k%b1>10) s=(k%b+k/b1)/2;
else s=10-k%b;
cout<<s;
a) 7
b) 8
c) 6
d) 3

6. Quyidagi programma qismi ishlashi natijasida ekranga qanday


qiymat chiqadi?
int a;
bool t = true, T = false;
if(t && T)
a = 100;
else
a =200;
cout <<a<<endl;
a) 200
b) 50

321
c) 150
d) 300

7. Quyidagi programma qismi ishlashi natijasida ekranga qanday


qiymat chiqadi?
int a;
bool t = false, T = false;
if(t && T)
a = 100;
else
a =200;
cout <<a<<endl;
a) 200
b) 100
c) 400
d) 500

8. Quyidagi programma qismi ishlashi natijasida ekranga qanday


qiymat chiqadi?
int a;
bool t = false, T = true;
if(t || T)
a = 500;
else
a =800;
cout <<a<<endl;
a) 500
b) 1000
c) 800
d) 1300

9. Quyidagi programma qismi ishlashi natijasida ekranga qanday


qiymat chiqadi?
#include <iostream.h>
int main (){
int a=10, b;
b=a%10;
cout<<b;
return 0;
}

322
a) 0
b) 1
c) 10
d) 100

10. Quyidagi programma qismi ishlashi natijasida ekranga qanday


qiymat chiqadi?
#include <iostream.h>
int main (){
int a=10, b;
if (a%2==0) b=a*a;
else
b=-a;
cout<<b;
return 0;
}
a) 100
b) -10
c) 10
d) 0

11. Quyidagi programma qismi ishlashi natijasida ekranga qanday


qiymat chiqadi?
#include <iostream.h>
int main (){
int a=10, b=23;
switch(a){
case 1: c=a+b; break;
case 2: c=a*b; break;
default: c=(a+b)*b; break;
}
cout<<c;
return 0;
}
a) 759
b) 33
c) 230
d) xatolik haqida habar beradi

323
12. Quyidagi programma qismi ishlashi natijasida ekranga qanday
qiymat chiqadi?
#include <iostream.h>
int main(){
int x=1;
x+=5;
cout<<x;
return 0;
}
a) 6
b) 5
c) 0
d) Xatolik haqidagi habar

13. Quyidagi programma qismi ishlashi natijasida ekranga qanday


qiymat chiqadi?
int main() { float x=1.5, y=-2.6; y=y+x*y; if
(y<x) goto nishon; y=y-x*2; nishon: cout<<y;
return 0; }
a) -6.5
b) 0.5
c) -2.82
d) -6.5

14. Quyidagi programma qismi ishlashi natijasida ekranga qanday


qiymat chiqadi?
int a;
bool t = true, T = true;
if(t && T)
a = 50;
else
a =200;
cout <<a<<endl;
a) 50
b) 100
c) 200
d) 150

324
15. Quyidagi programma qismi ishlashi natijasida ekranga qanday
qiymat chiqadi?
int a;
bool t = true, T = false;
if(t && T)
a = 100;
else
a =200;
cout <<a<<endl;
a) 200
b) 50
c) 150
d) 300

16. Quyidagi programma qismi ishlashi natijasida ekranga qanday


qiymat chiqadi?
int a;
bool t = false, T = false;
if(t && T)
a = 100;
else
a =200;
cout <<a<<endl;
a) 200
b) 100
c) 400
d) 500

17. Quyidagi programma qismi ishlashi natijasida ekranga qanday


qiymat chiqadi?
int a;
bool t = false, T = true;
if(t || T)
a = 500;
else
a =800;
cout <<a<<endl;
a) 500
b) 1000
c) 800

325
d) 1300

18. Quyidagi programma qismi ishlashi natijasida ekranga qanday


qiymat chiqadi?
int i = 0, s = 0;
bool t = true, T = true;
for(;t&&T;){
i+=20;
s += i;
if (100 < i)
t = !T;
}
cout <<s<<endl;
a) 420
b) 530
c) 100
d) 890

19. Quyidagi programma qismi ishlashi natijasida ekranga qanday


qiymat chiqadi?
int i = 0, s = 0;
bool t = false, T = true;
while(t||T){
i+=10;
s += i;
if (i > 100)
T = t;
}
cout <<s<<endl;

a) 660
b) 100
c) 444
d) 290

20. Quyidagi programma qismi ishlashi natijasida ekranga qanday


qiymat chiqadi?
int i = 0, s = 0;
bool t = false, T = true;
while(t||T){

326
i+=50;
s += i;
if (i > 500)
T = t;
}
cout <<s<<endl;
a) 3300
b) 1200
c) 2000
d) 600

Test savollari:
1. for (<ifoda >1; <ifoda>2;<ifoda>3) uchun noto’g’ri tavsifni
ko’rsating?
a) <ifoda>2 – takrorlash sanagichi vazifasini bajaruvchi o’zgaruvchiga
boshlang’ich qiymat berishga xizmat qiladi
b) <ifoda>2 – takrorlashni bajarish yoki yo’qligini aniqlab beruvchi
mantiqiy ifoda, agar shart rost bo’lsa takrorlash davom etadi
s) <ifoda>3 – odatda takrorlash sanagichi qiymatini oshirish
(kamaytirish) uchun xizmat qiladi yoki bu yerda takrorlash shartiga ta’sir
qiluvchi boshqa amallar bo‘lishi mumkin.
d) <ifoda>1 - takrorlash sanagichi vazifasini bajaruvchi o’zgaruvchiga
boshlang’ich qiymat berishga xizmat qiladi

2. int n=10; while(n-=1, n2=n*n, n>0); Dastur kodida takrorlashni


to’xtashiga ta’sir qiluvchi shartini toping?
a) n>0
b) n-=1
s) n2=n*n
d) n-=1, n2=n*n

3. Cheksiz takrorlashdan qaysi operator yordamida chiqib ketish


mumkin?
a) break;
b) continue;
s) return;
d) switch

4. C++ tilida for takrorlash operatorining sintaksisi to’g’ri berilgan


qatorni toping?

327
a) for(<ifoda1>;<ifoda2>; <ifoda3>)<operator yoki blok>
b) for(<ifoda>)operator yoki blok>
s) for(<ifoda1>,<ifoda2>, <ifoda3>)<operator yoki blok>
d) for(<ifoda1>;<ifoda2>; <ifoda3>)<operator
5. Quyidagi programma qismi ishlashi natijasida ekranga qanday
qiymat chiqadi?
#include <iostream.h>
int main (){
int s=0,i;
for(i=1;i<10;i++)
s+=i;
cout<<s;
return 0; }
a) 45
b) 55
s) 10
d) 1

6. C++ tilida cheksiz takrorlash while operatori yordamida qanday


tasvirlanadi?
a) while(1)
b) while(0)
s) while()
d) while(false)

7. C++ tilida oldin operatorni yoki blokni bajarib, keyin shartni


tekshiruvchi operator qaysi?
a) do-while
b) while
s) for
d) switch

8. Quyidagi programma qismi ishlashi natijasida ekranga qanday


qiymat chiqadi? int i,s=0;
for (i=1;i<10;i++){
s+=i;
i++;
}
cout<<s;
a) 25

328
int s = 1;
for(int i = 0; i <= 6; i += 2)
s+=i;
b) 45
s) 1
d) 10

9. Quyidagi programma qismi ishlashi natijasida ekranga qanday


qiymat chiqadi? I
nt i, s=0;
for(i = 0; i < 6; i++)
{
s *= i;
}
cout << s ;
a) 0
b)120
s)720
d) 24

10. Quyidagi programma qismi ishlashi natijasida ekranga qanday


qiymat chiqadi?
int i, s=1;
for(i = 0; i < 6; i++)
{
s *= i;
}
cout << s ;
a) 0
b)720
s)24
d) 120

11. Quyidagi programma qismi ishlashi natijasida ekranga qanday


qiymat chiqadi?
cout << s ;
a) 13
b)12
s)22

329
d) 21

12. Quyidagi programma qismi ishlashi natijasida ekranga qanday


qiymat chiqadi?
int n=7;
bool k;
k=n%2;
cout << k;
a)1
b)True
s)False
d)0

13. Quyidagi programma qismi ishlashi natijasida ekranga qanday


qiymat chiqadi?
int n=123,a;
a=n%100;
cout << a;
a)23
b)12
s)3
d)0.3

14.Quyidagi programma qismi ishlashi natijasida ekranga qanday


qiymat chiqadi?
int n = 20, s = 0;
for (int i = 1; i <= 20; i++)
if (n % i == 0)
s += i;
cout << s << endl;
a)42
b)100
s)55
d)45

15. Quyidagi programma qismi ishlashi natijasida ekranga qanday


qiymat chiqadi?
int s= 0;
for (int i = 1; i <= 10; i++)
switch ( i % 5 )

330
{ case 0: s += i;
break;
default : C++;
}
cout << s << endl;
a)23
b)43
s)24
d)21

16. Quyidagi programma qismi ishlashi natijasida ekranga qanday


qiymat chiqadi?
int s = 0, i = 0, n=10;
dastur_uz : i++;
s += i;
if (i != n)
goto dastur_uz;
else
s *= 2;
cout << s << endl;
a)110
b)120
s)125
d)250

17. Quyidagi programma qismi ishlashi natijasida ekranga qanday


qiymat chiqadi?
int n=10, s = 0, i = 0;
while (1 > 0)
{ i++; s += i;
if ( i >= n ) break;}
cout << s << endl;
a)55
b)45
s)0
d)Cheksiz takrorlanib qoladi

18. Quyidagi programma qismi ishlashi natijasida ekranga qanday


qiymat chiqadi?
int a=24, b=18;

331
while (a != b)
if (a > b) a -= b;
else b -= a;
cout << a << endl;
a)6
b)2
s)12
d)1

19. Quyidagi programma qismi ishlashi natijasida ekranga qanday


qiymat chiqadi?
int i = 0, j = 0;
bool b = true;
while(b){
i += 2; if (i == 10)
b = false; j = j + i;}
cout << j << endl;
a)30
b)40
s)50
d)20

20. Quyidagi programma qismi ishlashi natijasida ekranga qanday


qiymat chiqadi?
int s = 0, a = 100, b = 120;
bool t = true;
do{
if(a > b){ t = false; s = a + b;
} else b = a/2;
} while(t);
cout <<s << endl;
a)150
b)200
s)250
d)100

Test savollari:
1. Quyidagi dastur qismi ishlashi natijasida ekranga nima chiqadi?
int a[]={10,11,12,13,14};
int s=0;

332
for (int i=0;i<4;i++)
s=s+a[i];
cout << s;
a) 46
b) 55
c) 21
d) 60

2. Quyidagi dastur qismi ishlashi natijasida ekranga nima chiqadi?


int a[]={10,11,12,13,14};
int s=0;
for (int i=0;i<4;i++)
if (a[i]%2) s=s+a[i];
cout << s;
a) 22
b) 46
c) 60
d) 24

3. Quyidagi dastur qismi ishlashi natijasida ekranga nima chiqadi?


int a[]={-20,30,-40,43,64};
int s=6;
for (int i=0;i<5;i++)
if (a[i]<0) s=s+a[i];
a) -54
b) 60
c) -60
d) -24

4. Quyidagi dastur qismi ishlashi natijasida ekranga nima chiqadi?


int a[]={-20,30,-40,43,64};
int s=0;
for (int i=0;i<5;i++)
if (a[i]<0) s=s+a[0];
cout << s;
a) -20
b) -40
c) -60
d) 40

333
5. Quyidagi dastur qismi ishlashi natijasida ekranga nima chiqadi?
int a[]={-20,30,-40,43,64};
int s=0;
for (int i=0;i<3;i++)
if (a[i]>0) s=s+a[i];
s=s+a[2];
cout << s;
a) -10
b) 30
c) -70
d) 40

6. Quyidagi dastur qismi ishlashi natijasida ekranga nima chiqadi?


double a[]={2.5, 3.9, 4.8, 6.2};
int s=0;
for (int i=0;i<4;i++)
s=s+a[i];
cout << s;
a) 15
b) 17.4
c) 16.4
d) 15.4

7. Quyidagi dastur qismi ishlashi natijasida ekranga nima chiqadi?


double a[]={2.5, 3.9, 4.8, 6.2};
int m = 0;
for (int i = 1; i < 4; i++)
if (a [m] < a [i])
m = i;
cout << a [m];
a) 6.2
b) 4.8
c) 3.9
d) 2.5

8. Quyidagi dastur qismi ishlashi natijasida ekranga nima chiqadi?


double a[]={2.5, 3.9, 4.8, 6.2};
double s=0;
for ( int i=0;i<4;i++)
s=s+a[i];

334
cout << s;
a) 17.4
b) 15
c) 16.4
d) 15.4

9. Quyidagi dastur qismi ishlashi natijasida ekranga nima chiqadi?


double a[]={2.5, 3.9, 4.8, 6.2};
int m = 0;
for ( int i = 1; i < 4; i++)
if (a [m] > a [i])
m = i;
cout << a [m];
a) 2.5
b) 4.8
c) 3.8
d) 6.2

10. Quyidagi dastur qismi ishlashi natijasida ekranga nima chiqadi?


int list[] ={6, 8, 2, 14, 13};
for (int i = 0; i < 4; i++)
list[i] = list[i] - list[i + 1];
for (int i = 0; i < 5; i++)
cout << list[i];
a) -26-12113
b) 6821413
c) 2612311
d) 3141286

11. Quyidagi dastur qismi ishlashi natijasida ekranga nima chiqadi?


int list[] ={{1,2,3},{4,5,6},{7,8,9}};
int s=0, j=0;
for (int i = 0; i < 3; i++)
s=s+a[i][j];
cout << s;
a) 12
b) 15

335
c) 45
d) 6

12. Quyidagi dastur qismi ishlashi natijasida ekranga nima chiqadi?


double a[]={12.53, 23.49, 4.8, 6.29};
int m = 0;
for ( int i = 1; i < 4; i++)
if (a [m] > a [i])
m = i;
cout << m;
a) 2
b) 1
c) 3
d) 0

13. Quyidagi dastur qismi ishlashi natijasida ekranga nima chiqadi?


int list[] ={{1,2,3},{4,5,6},{7,8,9}};
int s=0, j=1;
for (int i = 0; i < 3; i++)
s=s+a[j][i];
cout << s;
a) 15
b) 6
c) 12
d) 45
14. Quyidagi dastur qismi ishlashi natijasida ekranga nima chiqadi?
int list[] ={{1,2,3},{4,5,6},{7,8,9}};
int s=0;
for (int i = 0, j=0; i < 3; i++, j++)
s=s+a[i][j];
cout << s;
a) 15
b) 6
c) 45
d) 12

15. Quyidagi dastur qismi ishlashi natijasida ekranga nima chiqadi?


double a[]={12.53, 23.49, 4.8, 6.29};
int m = 0;
for ( int i = 1; i < 4; i++)

336
if (a [m] < a [i])
m = i;
cout << m;
a) 1
b) 2
c) 3
d) 0

16. Qaysi javobda massiv e’loni to’g’ri berilgan?


a) double d[]={2,4,6,4}
b) double d={2,4,6,4}
c) double d[2]={2,4,6,4}
d) double d[]={2, ,6,4}
17. Quyidagi dastur qismi ishlashi natijasida ekranga nima chiqadi?
int list[] ={{1,2,3},{4,5,6},{7,8,9}};
int s=0;
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
s=s+a[i][j];
cout << s;
a) 45
b) 6
c) 15
d) 12

18. Quyidagi dastur qismi ishlashi natijasida ekranga nima chiqadi?


int list[] ={{21,2,43}, {31,5,26}, {7,18,22}};
int s=0, min=0;
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
if (min>a[i][j]) min=a[i][j]
cout << min;
a) 0
b) 2
c) min
d) 43

19. Quyidagi dastur qismi ishlashi natijasida ekranga nima chiqadi?


int list[] ={{21,2,43}, {31,5,26}, {7,18,22}};
int s=0, min=a[0][0];

337
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
if (min<a[i][j]) min=a[i][j]
cout << min;
a) 43
b) 2
c) min
d) 0

20. Quyidagi dastur qismi ishlashi natijasida ekranga nima chiqadi?


int list[] ={{21,2,43}, {31,5,26}, {7,18,22}};
int s=0, min=j=2;
for (int i = 0; i < 3; i++)
if (min>a[i][j]) min=a[i][j]
cout << min;
a) 2
b) 22
c) min
d) 7
Test savollari:
1. Quyidagi dastur kodining natijasini toping.
int x;
int *p = &x;
*p = 35;
cout << x;
a) 35
b) 4
c) 0
d) 39

2. Quyidagi dastur kodining natijasini toping.


int x;
int y;
int *p = &x;
int *q = &y;
*p = 35;
*q = 98;
*p = *q;
cout << x << "
" << y << endl;

338
a) 98 98
b) 35 98
c) 98 35
d) 35 35

3. Quyidagi dastur kodining natijasini toping.


int x;
int y=13;
int *p = &x;
int *q = &y;
*p = 35;
cout << x << " " << *q << endl;
a) 35 13
b) 13 35
c) 35 0
d) 0 35

4. Quyidagi dastur kodining natijasini toping.


int y=13;
int *q = &y;
y = 23;
cout << *q << endl;
a) 23
b)14
c) 0
d) 0x0bbff

5. Quyidagi dastur kodining natijasini toping.


int a = 0, b = 10;
if (pow(b,a) == 1)
a = b * (++b);
else
a = b * (--b);
cout<<a;
a) 121
b) 111
c) 100
d) 81

6. Quyidagi dastur kodining natijasini toping.

339
28 << 3 & 22 - 17 | 30 >> 2
a) 7
b) 8
c) 9
d) 10

7. Quyidagi dastur kodining natijasini toping.


int a = 7, b = 8;
if (++a == ++b) a += a;
else if(a % 2 == 0) a += b * b;
else if(a % 2 != 0) a += b;
cout<<a;
a) 89
b) 98
c) 91
d) 90

8. Quyidagi dastur kodining natijasini toping.


int a = 16, b = 5;
if (sqrt(a) == b) a *= ++a;
else a *= ++b;
cout<<a;
a) 96
b) 80
c) 36
d) 81

9. Quyidagi dastur kodining natijasini toping.


int a=6,b=4;
while(a/b==1)
{
a++;
if (b) a++;
b--;
a=b*3;
}
cout << a;
a) 9

340
b) 10
c) 6
d) 4

10. Quyidagi dastur kodining natijasini toping.


int a = 0;
for (int i = 0; i < 50; i+=5)
{
if (i / 10 >= 3)
if (i % 10 != 5)
a += i;
}
cout<<a;
a) 70
b) 50
c) 10
d) 150

Test savollari:
1. Funksiya e’loni to’g’ri ko’rsatilgan javobni toping.
a) void F(int t=1)
b) void F(int t=1, int s)
c) void F(int t=int q)
d) void F(int t=double)

2. Funksiya e’loni to’g’ri ko’rsatilgan javobni topin?


a) void F(int t, double d)
b) void F(int t=1, double s)
c) void F(int t, double d=t)
d) void F(int t=doubled)s

3. Funksiya e’loni to’g’ri ko’rsatilgan javobni toping


a) void F(char c=99, int t=99)
b) void F(char c=99, int t)
c) void F(char c=t, int t)
d) void F(char c, int c)

4. Programma ishlashi natijasida ekranga nima chiqadi?


double SUM(double *a, int n)
{

341
double t=0;
t=t+a[0];
for (int i=1;i<n;i++)t=t+a[i]/a[i-1];
return t;
}
void main()
{
double a[]={7,1,3,5,3},c;
c=SUM(a,3);
cout << c;
}
a) 10
b) 20
c) 30
d) 50

5. Programma ishlashi natijasida ekranga nima chiqadi?


int F(int n, int k=3, int t=13)
{
n=5;
for (int i=0; i<=k;i++)
t=t+n;
return n;
}
void main()
{
int a[]={3,6,5,7,9,1}, n=a[0], k=a[1], t=a[3];
for (int i=0;i<6;i++)
if (F(a[i])>a[i]) t=t+F(a[i],a[2],a[0]);
cout << t;
}
a) 17
b) 18
c) 19
d) 20

6. Programma ishlashi natijasida ekranga nima chiqadi?


int F(double &a)

342
{
a=13;
int b=a+41;
}
void main()
{
double b=15;
F(b);
cout << b;
}
a) 13
b) 54
c) 41
d) 22

7. Programma ishlashi natijasida ekranga nima chiqadi?


int F(int n, int k, int t)
{
for (int i=0; t; )
{t--;n=n+k;}
return n;
}
void main()
{
int a[]={2,5,2,6,7}, n=2, k=1, t=3;
for (int i=0;i<3;i++)
if (2*F(a[i], a[i], a[0])>t) t=t+F(a[i],t,a[0]);
cout << t;
}
a) 38
b) 41
c) 25
d) 57

8. Programma ishlashi natijasida ekranga nima chiqadi?


int F(int a)
{
a=5;
return a;
}

343
void main()
{
int a=7;
F(a)+F(a+5);
cout << a;
}
A)7
b) 8
c) 5
d) 75

9. Programma ishlashi natijasida ekranga nima chiqadi?


int F(int n, int k, int t)
{
for (int i=0; t; )
{t--;n=n+k;}
return n;
}
void main()
{
int a[]={3,3,3,6,7}, n=2, k=1, t=3;
for (int i=0;i<1;i++)
if (2*F(a[i], a[i], a[0])>t) t=t+F(a[i],t,a[0]);
cout << t;
}
a) 15
b) 25
c) 3
d) 21

10. Ushbu funksiya qanday qiymat qaytaradi?


int funksiya(int n)
{
int k = 0;
while(n > 0)
{
k++;
n /= 10;
}

344
return k;
}
a) n niing sonlari sonini
b) n ning sonlari yig’indisini
c) Har doim nol qiymat qaytaradi
d) Qiymat qaytarmaydi

11. Ushbu funksiya qanday qiymat qaytaradi?


int funksiya(int n)
{ int s=0;
while(n > 0)
{
int a=n%10;
s=s+a;
n /= 10;
}
return s;
}
a) n niing sonlari yig’indisini
b) n ning sonlari yig’indisini
c) Har doim nol qiymat qaytaradi
d) n niing sonlari sonini

12. Ushbu funksiya qanday qiymat qaytaradi?


int funksiya(int n)
{
int s=0;
while(n > 0)
{
int a=n%10;
s=s*10+a;
n=n/10;
}
return s;
a) n soniniing teskarisini
b) n ning sonlari yig’indisini
c) n niing sonlari sonini
d) Qiymat qaytarmaydi

13. Programma ishlashi natijasida ekranga nima chiqadi?

345
int F(int n, int k=15, int t=12)
{
return n*k/t;
}
void main()
{
int n=7, a[]={5,2,-3,2,4}, c=2, k=2;
for (int i=0;i<5;i++)
if (2*F(a[i])-F(n-a[i],c)>F(a[i], a[i], a[i/2])) c=c+F(a[i], n);
cout << c;
}
a) 7
b) 8
c) 15
d) 12

14. Programma ishlashi natijasida ekranga nima chiqadi?


int F(int n, int k=5)
{
k=3;
return n-k;
}
void main()
{
int n=7, a[]={5,2,3,2,4}, c=2, k=2;
for (int i=0;i<5;i++)
if (2*F(a[i])-F(n-a[i],c)>0) c=c+F(a[i], n);
cout << c;
}
a) 5
b) 6
c) 7
d) 8

15. Programma ishlashi natijasida ekranga nima chiqadi?


int F(int n, int k=2, int t=6)
{
for (;t;)t=t-2;
return (n+t)/k;
}

346
void main()
{
int n=8, a[]={5,2,-3,2,4}, c=2, k=2;
for (int i=0;i<5;i++)
if (2*F(a[i])-F(c-a[i],n)>F(a[i], a[i], n)) c=c+F(a[i]);
cout << c;
}
a) 8
b) 9
c) 10
d) 11

16. Programma ishlashi natijasida ekranga nima chiqadi?


int F(int a, int b)
{
return (a+b);
}
void main()
{
int a=3, b=4, c=7;
cout << F(b,c);
}
a) 11
b) 7
c) 10
d) 34
17. Programma ishlashi natijasida ekranga nima chiqadi?
int F(int a, int b)
{
return (a+b);
}
void main()
{
int a=3, b=4, c=7;
cout << F(a+b,c+7);
}
a) 11
b) 7
c) 10
d) 34

347
18. Programma ishlashi natijasida ekranga nima chiqadi?
bool F(int a, int b)
{
return (a+b);
}
void main()
{
int a=3, b=4;
cout << F(a,b);
}
a) 1
b) 7
c) 0
d) 34

19. Programma ishlashi natijasida ekranga nima chiqadi?


bool F(int a, int b)
{
return a?b:0;
}
void main()
{
int a=3, b=4;
cout << F(b,c);
}
a) 1
b) 4
c) 0
d) 7

20. Programma ishlashi natijasida ekranga nima chiqadi?


int F(int a, int b)
{
return a?b:0;
}
void main()
cout << F(b,c);
}
a) 4

348
b) 1
c) 0
d) 7

Test savollari
1. Quyidagi rekursiv funksiya bajarilishi natijasida ekranga nima
chiqadi.
long F(int n)
{ if(!n) return 1;
else return n*F(n-1);
}
int main()
{long s; int n=5;
s=F(n);
cout<<”s=”<<s;
}
a) 120
b) 130
c) 24
d) 620

2. Quyidagi rekursiv funksiya bajarilishi natijasida ekranga nima


chiqadi.
long F(int n)
{ if(!n) return 1;
else return n+F(n-1);
} int main()
{ long s; int n=10;
s=F(n);
cout<<”s=”<<s;
}
a) 56
b) 45
c) 46
d) 55

3. Quyidagi rekursiv funksiya bajarilishi natijasida ekranga nima


chiqadi.
double rec(double x, int n)
{ if(!n) return 1;

349
else return x*rec(x,n-1);
} int main()
{ long s; int x=4;
s=rec(x,4);
cout<<”s=”<<s;
}
a) 256
b) 64
c) 16
d) 4

4. Quyidagi rekursiv funksiya bajarilishi natijasida ekranga nima


chiqadi.
double rec(double x, int n)
{ if(!n) return 1;
else return x*rec(x,n-1); }
int main()
{ long s; int x=4;
s=rec(1,4);
cout<<”s=”<<s;
}
a) 1
b) 4
c) 64
d) 256

5. Ushbu funksiya nima javob qaytaradi?


int funksiya(int n)
{ int k = 0;
while(n > 0)
{
k++;
n /= 10;
}
return k;
}
a)Butun son qaytaradi
b) Haqiqiy son qaytaradi
c) Mantiqiy qiymat qaytaradi
d) Qiymat qaytarmaydi

350
6. Quyidagi rekursiv funksiya bajarilishi natijasida ekranga nima
chiqadi.
long F(int n)
{
if(n==1) return 1;
else return n+F(n-1);
}
int main()
{long s; int n=10;
s=F(n);
cout<<”s=”<<s;
}
a) 55
b) 57
c) 56
d) 47

7. Quyidagi rekursiv funksiya bajarilishi natijasida ekranga nima


chiqadi.
float F(int n)
{ if(!n) return 0;
else return 1./n+F(n-1);
}
int main()
{float s; int n=2;
s=F(n);
cout<<”s=”<<s;}
a) 1.5
b) 2.5
c) 0.5
d) 1

8. Quyidagi rekursiv funksiya bajarilishi natijasida ekranga nima


chiqadi.
float F(int n)
{ if(!n) return 1;
else return 1./n*F(n-1);
}
int main()

351
{float s; int n=2;
s=F(n);
cout<<”s=”<<s;}
a) 0.5
b) 1.5
c) 1
d) 2

9. Quyidagi rekursiv funksiya bajarilishi natijasida ekranga nima


chiqadi.
float F(int n)
{ if(!n) return 0;
else return n+F(n-1);
}
int main()
{float s; int n=4;
s=F(n);
cout<<”s=”<<s;}
a) 10
b) 15
c) 20
d) 5

10. Quyidagi rekursiv funksiya bajarilishi natijasida ekranga nima


chiqadi.
float F(int n)
{ if(!n) return 0;
else return n+F(n-1);
}
int main()
{float s; int n=6;
s=F(n);
cout<<”s=”<<s;}
a) 21
b) 20
c) 15
d) 28

Test savollari
1. |x| C++ da haqiqiy sonlar uchun qanday yoziladi?

352
a) fabs(x)
b) abs(x)
c) labs(x)
d) absf(x)

2. 10 darajasi x C++ da qanday yoziladi?


a) pow10(x)
b) pow(10,x)
c) pow(x,10)
d) 10^x

3. Oqimdan satrni o’qishga mo’ljallangan gets() funksiyasining


protatipi to’g’ri yozilgan javobni tanlang
a) char* gets(char *s);
b) char gets(char *s);
c) char* gets(char s);
d) string* gets(string *s);

4. C++ tilida char turidagi satrni nusxalovchi funksiyani aniqlang.


a) strcpy()
b) strcat()
c) strcmp()
d) strrev()

5. C++ tilida ixtiyoriy turning xotiradagi o’lchamini aniqlash


funksiyasini ko’rsating
a) sizeof
b) length
c) strlen
d) size

6. C++ tilida x soning absolyut qiymatini aniqlash funkchiyasini


ko’rsating
a) abs(x)
b) fabs(x)
c) exp(x)
d) ceil(x)

7. C++tilida satr uzunligini qaytaruvchi funksiyani aniqling.


a) strlen()

353
b) malloc()
c) ceil()
d) To’g’ri javob yo’q

8. sin2x + 2cosy ifodasi c++ da qanday ifodalanadi?


a) sin(2*x)+2*cos(y)
b) sin(2x)+2cos(y)
c) sin 2*x +2*cosy
d) sin*2*x+2*cos*y

9. arcsin2x + 2arccosy ifodasi c++ da qanday ifodalanadi?


a) asin(2*x)+2*acos(y)
b) sin(2x)+2acos(y)
c) asin(2x)+2cos(y)
d) sin*2*x+2*cos*y

10. ln2x + ln2cosy ifodasi c++ da qanday ifodalanadi?


a) log(2*x)+log(2*cos(y))
b) ln(2*x)+ln(2*acos(y))
c) lg(2*x)+lg(2*acos(y))
d) log (2*x)+ln(2*acos(y))

Test savollari:
1. Quyidagi dastur qismi ishlashi natijasida ekranga nima chop etiladi?
int f(int a[],int n)
{
int m=a[0];
for(int i=1;i<n;i++)
if(a[i]>m) m=a[i];
return m;
}
int main()
{
int a[]={23,23,45,12,34};
int n=5;
cout<<f(a,n);
}
a) 45
b) 23
c) 12

354
d) 34

2. Quyidagi dastur qismi ishlashi natijasida ekranga nima chop etiladi?


int f(int a[],int n)
{
int m=a[0];
for(int i=1;i<n;i++)
if(a[i]<m) m=a[i];
return m;
}
int main()
{int a[]={23,23,45,12,34};
int n=5;
cout<<f(a,n);
}
a) 12
b) 23
c) 34
d) 45

3. Quyidagi dastur qismi ishlashi natijasida ekranga nima chop etiladi?


int f(int a[],int n)
{ int m=0;
for(int i=0;i<n;i++) m+=a[i];
return m; }
int main()
int a[]={0,1,2,3,4};
int n=5;
cout<<f(a,n);}
a) 10
b) 0
c) 6
d) 4
4. Quyidagi dastur qismi ishlashi natijasida ekranga nima chop etiladi?
int f(int a[],int n)
{ int m=0;
for(int i=0;i<n;i++)
if(a[i]%2) m+=a[i];
return m; }
int main(){

355
int a[]={0,1,2,3,4};
int n=5;
cout<<f(a,n);}
a) 4
b) 10
c) 6
d) 0

5. Quyidagi dastur qismi ishlashi natijasida ekranga nima chop etiladi?


int len(char s[])
{ int m=0;
while(s[m++]);
return m-1; }
int main()
{char z[]="Ushbu satr uzunligi = ";
cout<<z<<len(z);}
a) Ushbu satr uzunligi =22
b) 22
c) Ushbu satr uzunligi
d) 0

6. Quyidagi dastur qismi ishlashi natijasida ekranga nima chop etiladi?


float sum(int n,float *x)
{ float s=0;
for (int i=0;i<n;i++)s+=x[i];
return s; }
void main()
{ float E[]={1.2,2.0,3.0,4.5,-4.0};
cout<<sum(5,E); }
a) 6.7
b) 1.2
c) 6.2
d) 0

7. Quyidagi dastur qismi ishlashi natijasida ekranga nima chop etiladi?


void vector(int n,int x[],int y[])
{ for (int i=0;i<n;i++)
y[i]=x[i]>0?1:0;}
void main()
{ int a[]={1,2,-4,3,-5,0,4};

356
int c[7];
vector(7,a,c);
for(int i=0;i<7;i++) cout<<' '<<c[i];}
a) 1 1 0 1
b) 1 1 1 0
c) 1 0 0 0
d) 1 1 1 1

8. Quyidagi dastur qismi ishlashi natijasida ekranga nima chop etiladi?


void vector(int n,int x[],int y[])
{ for (int i=0;i<n;i++)
y[i]=x[i]>0?1:0; }
void main()
{ int a[]={1,2,-4,3,-5,0,4};
int c[7];
vector(7,a,c);
int s=0;
for(int i=0;i<7;i++) s+=c[i];
cout<<s;}
a) 4
b) 6.7
c) 0
d) 1

9. Quyidagi dastur qismi ishlashi natijasida ekranga nima chop etiladi?


void vector(int n,int x[])
{ int s=0;
for (int i=0;i<n;i++) s+=x[i]>0?1:0;
cout<<s;
}
void main()
{
int a[]={1,2,-4,3,-5,0,4};
vector(7,a);}
a) 4
b) 6.7
c) 0
d) 1

357
10. Quyidagi dastur qismi ishlashi natijasida ekranga nima chop etiladi?
void vector(int n,int x[])
{ int s=0;
for (int i=0;i<n;i++) if(x[i]<0) s+=x[i];
cout<<s;
}
void main()
{
int a[]={1,2,-4,3,-5,0,4};
vector(7,a);}
a) -9
b) 4
c) 10
d) 11

Test savollari
1. Struktura maydonlariga qanday murojaat qilinadi?
a. ‘.’ belgisi orqali
b. ‘->.’ orqali
c. ‘::’ orqali
d. ‘-’ belgisi orqali

2. Ko’rsatkich orqali e’lon qilingan struktura maydonlariga qanday


murojaat qilinadi?
a. ‘.’ belgisi orqali
b. ‘->.’ orqali
c. ‘::’ orqali
d. ‘-’ belgisi orqali

3. Struktura maydoni o’lchami aniq ko’rsatilgan ko’rinishi qaysi


javobda to’g’ri berilgan?
a. unsigned int Yil:7;
b. unsigned int Yil-7;
c. unsigned int Yil.7;
d. unsigned int Yil::7;

4. Strukturalar massivi to’g’ri ko’rsatilgan javobni belgilang.


a. const int n=25;
Talaba talabalar[n];
b. const int n=25;

358
Talaba [n]talabalar;
c. const int n=25;
Talaba talabalar*[n];
d. const int n=25;
Talaba talabalar{{n}};

5. Strukturaga ko’rsatkich to’g’ri e’lon qilingan javobni toping.


a. Talaba * k_talaba;
b. Talaba -> k_talaba;
c. Talaba & k_talaba;
d. Talaba >> k_talaba;

6. Quyidagi dastur qismi bajarilishi natijasida ekranga nima chiqadi.


struct Vaqt{unsigned int h,m,s;};
int main(int argc, char* argv[])
{
Vaqt a={0,59,59},b={0,5,5}; a.m=b.h+b.s;
cout<<a.h<<":"<<a.m<<":"<<a.s<<endl;
return 0;
}
a. 0:5:59
b. 0:5:61
c. 0:6:4
d. 0:5:44;
7. Quyidagi dastur qismi bajarilishi natijasida ekranga nima chiqadi.
struct Racional{int surat,maxraj;};
void main(int argc, char* argv[])
{
Racional a={52,33}, b={12,4};
b.surat=(a.surat+4)/a.maxraj;
a.surat=(a.surat+b.maxraj)/b.surat;
cout<<b.surat<<"/"<<a.maxraj<<endl;
}
a. 1/33
b. 41/33
c. 5/33
d. 52/33

8. Quyidagi dastur qismi bajarilishi natijasida ekranga nima chiqadi.


struct A{int x;};

359
void f(int a){a=a*a;};
int main(int argc, char* argv[])
{
A a; a.x=5;
f(a.x); cout<<a.x<<endl;
return 0;
}
a. 5
b. 6
c. 4
d. 8

9. Quyidagi dastur qismi bajarilishi natijasida ekranga nima chiqadi.


struct Vaqt{unsigned int soat,minut,sekund;};
int main(int argc, char* argv[])
{
Vaqt a={2,34,11},b={1,12,5}; b.minut=a.minut+9;
a.sekund=b.sekund+a.minut;
cout<<b.minut<<":"<<a.sekund<<":"<<b.soat<<endl;
return 0;
}
a. 43:39:1
b. 44:25:61
c. 30:26:44
d. 50:55:44;

10. Quyidagi dastur qismi bajarilishi natijasida ekranga nima chiqadi.


struct Ishchi{unsigned int Yoshi; float Vazni;};
int main(int argc, char* argv[])
{
Ishchi Eshmat={20,77.8},Toshmat={25,100};
if(Eshmat.Vazni<Toshmat.Vazni) cout<<"Eshmat!"<<endl;
else cout<<"Toshmat!"<<endl;
return 0;
}
a. Eshmat!
b. Toshmat!
c. Eshmat! Toshmat!
d. Toshmat! Eshmat!

360
Test savollari:
1. Quyidagi programma qismi ishlashi natijasida ekranga qanday
qiymat chiqadi?
char s1[]="ABBA", s2[]="BC", s3[]="CCBA";
strncat(s2,s3,2);
strcpy(s1,s2);
cout << s2;
a) ABC
b) BCCC
c) CBBB
d) BCCA

2. Quyidagi programma qismi ishlashi natijasida ekranga qanday


qiymat chiqadi?
char s1[]="BAB", s2[]="ABC", s3[]="CBA";
string a="ABC";
if (s1[0]==s1[1] && s2[0])
cout<<s3;
else cout << a[1];
a) B
b) C
c) A
d) AB

3. Quyidagi programma qismi ishlashi natijasida ekranga qanday


qiymat chiqadi?
string s1="AB", s2="BCC", s3="CAC";
int i=1;
s1.insert(i,s3);
s2.append(s3);
s2.erase(1,2);
s3.erase(2,1);
s3=s1+s2.substr(1,1);
cout<<s3;
a) ACACBC
b) ABACAB
c) BCBABC
d) ABCABC

4. Quyidagi programma qismi ishlashi natijasida ekranga qanday

361
qiymat chiqadi?
char s1[]="BAB", s2[]="ABC", s3[]="CBA";
if (s1[0]==s1[1] && s3[0])
cout<<s3;
else cout << s2;
a) ABC
b) CBA
c) BAC
d) ACB

5. Quyidagi programma qismi ishlashi natijasida ekranga qanday


qiymat chiqadi?
char c[]={'a','i','o','e','\0'};
char matn[] = "Programmalash asoslati va kompyuter texnologiyalari";
int k=0;
for(int i=0; i<strlen(c);i++){
k=0;
for(int j=0;j<strlen(matn);j++)
if(matn[j]==c[i])
k++;
cout<<k<<"\t";
}
a) 8 3 5 2
b) 2 3 5 8
c) 0 3 5 8
d) a i o e

6. Quyidagi programma qismi ishlashi natijasida ekranga qanday


qiymat chiqadi?
char s1[]="BAB", s2[]="ABC", s3[]="ABA";
string a="lalalal";
if (strrev(s3)==s3)
cout<<strrev(strcpy(s2,strrev(s1)));
else cout << a.find("al");
a) BAB
b) ABA
c) ABC
d) CBA

7. Quyidagi programma qismi ishlashi natijasida ekranga qanday

362
qiymat chiqadi?
int s=0, m=0 ;
char matn[] = "Programmalash asoslari fani 2015 - yil";
for(int i=0;i<strlen(matn);i++)
if(isdigit(matn[i])) C++;
else if (isalpha(matn[i])) m++;
cout<<s<<"\t"<<m;
a) 4 28
b) 2 31
c) 5 29
d) 6 23

8. Quyidagi programma qismi ishlashi natijasida ekranga qanday


qiymat chiqadi?
char s1[]="ABBA", s2[]="BABC", s3[]="CCBA";
strncpy(s2,s3,2);
strncpy(s1,s2,1);
cout << s1;
a) CBBA
b) ABBC
c) ACCB
d) BAAC

9. Quyidagi programma qismi ishlashi natijasida ekranga qanday


qiymat chiqadi?
string s1="A", s2="B", s3="C";
int i=1;
s1.insert(i,s3);
s1.append(s2);
s2.insert(i,s3);
s1.erase(1,2);
s3=s1+s2;
cout<<s3;
a) ABC
b) CAB
c) ACB
d) BBC

10. Quyidagi programma qismi ishlashi natijasida ekranga qanday


qiymat chiqadi?

363
char matn[] = "d2as#3!";
for(int i=0;i<strlen(matn)-2;i++)
if(!isdigit(matn[i]) && isalpha(matn[i]))
cout<<matn[i];
a) das
b) asd
c) 2#3
d) 23

Test savollari
1. Formatli yozish uchun qanday funksiya ishlatiladi?
a. scanf()
b. printf()
c. gets()
d. puts()

2. Belgini o’qish funksiyasi to’ғri ko’rsatilgan qatorni toping


a. gets()
b. puts()
c. getc()
d. putc()

3. Belgini yozish funksiyasi to’ғri ko’rsatilgan qatorni toping


a. gets()
b. puts()
c. getc()
d. putc()

4. To‘ldiruvchi-belgilar to’ғri ko’rsatilgan javobni toping


a. probel, ‘\t’, ‘\n’ belgilari
b. ‘a’, ‘\t’, ‘\n’ belgilari
c. Enter, Esc, ‘\t’, ‘\n’ belgilari
d. ‘a’, ‘b’, ‘c’, ‘d’ belgilari
Test savollari
1. Fayl deb nimaga aytiladi?
a. Bir xil tipdagi qiymatlar joylashgan tashqi xotiradagi nomlangan sohadir
b. har xil tipdagi qiymatlar joylashgan tashqi xotiradagi nomlangan sohadir
c. Bir xil tipdagi qiymatlar joylashgan tashqi xotiradagi nomlanmagan
sohadir
d. har xil tipdagi qiymatlar joylashgan tashqi xotiradagi nomlanmagan
sohadir

2. Fayl ko’rsatkichi ... ko’rsatib turadi?

364
a. ayni paytda fayldan o’qilayotgan yoki unga yozilayotgan joyni
b. fayldan belgi o’qish jarayonini
c. fayldan satr o’qish jarayonini
d. ayni paytda fayldan o’qilayotgan belgining ASCII jadvalidagi kodini

3. Fayldan i - yozuvni o’qilgandan keyin, ko’rsatkich nechanchi yozuvni


ko’rsatib turadi?
a. i+1
b. i+2
c. i-1
d. i

4. C++ tilida mantiqiy fayl bu ...


a. fayl turidagi o’zgaruvchi
b. fayl joylashgan joy
c. fayldagi belgilar soni
d. faylning kengaytmasi

5. Matn fayl - ...


a. ASCII kodidagi belgilar bilan berilganlar majmuasi
b. C++ da ochish mumkin bo‘lgan ixtiyoriy fayl
c. Sonlardan tashkil topgan fayl
d. Kengaytmasi “txt” bo‘lgan fayl
6. Formatli o’qish uchun qanday funksiya ishlatiladi?
a. scanf()
b. printf()
c. gets()
d. puts()

7. Formatli yozish uchun qanday funksiya ishlatiladi?


a. scanf()
b. printf()
c. gets()
d. puts()

8. Belgini o’qish funksiyasi to’g’ri ko’rsatilgan qatorni toping


a. gets()
b. puts()
c. getc()
d. putc()

9. Belgini yozish funksiyasi to’g’ri ko’rsatilgan qatorni toping


a. gets()

365
b. puts()
c. getc()
d. putc()

10. To‘ldiruvchi-belgilar to’g’ri ko’rsatilgan javobni toping


a. probel, ‘\t’, ‘\n’ belgilari
b. ‘a’, ‘\t’, ‘\n’ belgilari
c. Enter, Esc, ‘\t’, ‘\n’ belgilari
d. ‘a’, ‘b’, ‘c’, ‘d’ belgilari

Test savollari
1. Fayl oqimi turi to’g’ri berilgan javobni belgilang?
a. fstream
b. int
c. FILE*
d. fopen

2. Quyida keltirilgan turlarning qaysi biri fayllar bilan ishlash uchun


o’ljallangan?
a. FILE*
b. double
c. fopen
d. double

3. Matn faylni o’qish uchun ochish rejimi qanday belgilanadi?


a. rt+
b. rb+
c. wb+
d. wt+

4. Binar faylni o’qish uchun ochish rejimi qanday belgilanadi?


a. rt+
b. rb+
c. wb+
d. at+

5. Matn faylni yozish uchun ochish rejimi qanday belgilanadi?


a. rt+
b. rb+
c. wb+
d. wt+

6. Binar faylni yozish uchun ochish rejimi qanday belgilanadi?

366
a. rt+
b. rb+
c. wb+
d. at+

7. Faylga satr yozish uchun quyidagi funksiyalarning qaysi biri ishlatiladi?


a. fgets()
b. fputs()
c. fgetc()
d. fopen()
8. Faylga belgi yozish uchun quyidagi funksiyalarning qaysi biri ishlatiladi?
a. fgets()
b. fputs()
c. fgetc()
d. feof()

9. Fayldan belgi o’qish uchun quyidagi funksiyalarning qaysi biri ishlatiladi?


a. fgets()
b. fputs()
c. fgetc()
d. feof()

10. Fayldan satr o’qish uchun quyidagi funksiyalarning qaysi biri ishlatiladi?
a. fgets()
b. fputs()
c. fgetc()
d. feof()

367
GLOSSARIY

1. Algoritm - maʼlum bir turga oid masalalarni yechishda


ishlatiladigan amallarning muayyan tartibda bajarilishi haqidagi aniq qoida
(dastur).
2. Blok-sxema (oqim diagrammasi) - ish jarayonini aks ettiruvchi
diagramma turidir. Sxemani algoritmning diagrammatik tasviri, vazifani
bosqichma-bosqich hal qilish usuli sifatida ham aniqlash mumkin.
3. Dastur:
 biror-bir faoliyat, ishning mazmuni va rejasi;
 siyosiy partiyalar, tashkilotlar, alohida arboblar faoliyatining
asosiy qoidalari va maqsadlari bayoni;
 oʻquv fani mazmunining qisqacha izohi;
4. Dasturlash - kompyuterlar va boshqa mikroprotsessorli elektron
mashinalar uchun dasturlar tuzish, sinash va oʻzgartirish jarayonidan iborat.
Odatda dasturlash yuqori saviyali dasturlash tillari (PHP,Java,C++,Python)
vositasida amalga oshiriladi. Bu dasturlash tillarining semantikasi odam
tiliga yaqinligi tufayli dastur tuzish jarayoni ancha oson kechadi.
5. Funksiya - (lotincha: functio — „bajarish“, „amalga oshirish“) -
muayyan til, til birligi, lisoniy shaklning u yoki bu vazifani bajarish
qobiliyati; tilning kishilik jamiyatidagi roli, vazifasi; til tizimining barcha
sathlarida uning birliklari oʻrtasidagi bogʻliqlik yoki munosabatlar.
6. Massiv - bir xil ma'lumot turiga ega bo'lib bir nechta
o'zgaruvchini har birini alohida e'lon qilish o'rniga bir o'zgaruvchiga bir
nechta qiymat saqlash uchun ishlatiladi.
7. Obyektga yo‘naltirilgan dasturlash(Object Oriented
Programming) - bu biror bir maqsadga yo'naltirilgan dasturlash
degan ma'noni anglatadi.(OOP)
8. Protseduraviy dasturlash - bu ma'lumotlarga ishlov
beradigan protseduralar yoki funksiyalarni yozish, obyektga
yo'naltirilgan dasturlash esa ma'lumot va funksiyalarni o'z ichiga
olgan obyektlarni yaratish haqida.
9. Parametr - (yunoncha: parametron — oʻlchaydigan) matematik
formula va ifodalarda qoʻllaniladigan kattalik.
10. Rekursiya - funksiya oʻziga oʻzi toʻgʻridan-toʻgʻri yoki
qandaydir vosita orqali murojaat qilish jarayoni.
11. Assembler dasturlash tili - ( yoki Assembly tili, yoki belgili
mashina kodi), binar( ya'ni ikkilik) tilga eng yaqin til bo'lib, unda tildagi
koʻrsatmalar va arxitektura koʻrsatmalari oʻrtasida juda kuchli muvofiqlik

368
mavjud. Assembler dasturlash tilida odatda bitta mashina ko'rsatmasi
bo'ladi, lekin konstantalar, izohlar, assembler yo'naltirmalari, belgili teglar,
xotira joylari, registerlar va makroslarni ham qo'llab-quvvatlaydi.
12. Fortran - bu umumiy maqsadli kompilyatsiya qilingan imperativ
dasturlash tili bo'lib, u ayniqsa sonli hisoblash va ilmiy hisoblash uchun juda
mos keladi.
13. Paskal (inglizcha: Pascal) —Ushbu dasturlash tili boshqa bir
qator tillar uchun asos boʻlib xizmat qiladi. Paskal imperativ va Protsedurali
dasturlash tili hisoblanadi.
14. C (talaffuzi: si) — kompilyatsiyalanuvchi statik dasturlash
tili boʻlib, 1969—1973-yillarda Bell laboratoriyasi xodimi Dennis
Ritchie tomonidan yaratilgan. Ushbu dasturlash tili B tilining
takomillashgan koʻrinishi sifatida yaratilgan.
15. Kompilyator – bu o‘zgartirish degan ma’noni beradi. Ya’ni
dasturlash tilida yozilgan dastur(C++ bo‘lsa, *.c, *.cpp)ni kompyuter
tushunadigan tilga o‘zgartirib, uni ishlashini ta’minlaydi. Bu degani dastur
kompyuterda to‘liq ishlaydi. Bundan ko‘rinib turibdiki, C++ da dastur
tuzish uchun kompilyator o‘rnatish zarur.
16. Kompilyatsiya – o‘zgaruvchi jarayon, ya’ni yuqori pog‘onali
dastur kodlari(misol uchun C++ da tuzilgan kod)ni quyi pog‘onali
ishlovchi kodga aylantirish jarayoni.
17. Abstraksiya – bu identifikatorlardan farqli bo‘lgan istalgan
dasturlash tili ifodasi
18. Izoh - bu dasturchilar o'rtasida qayta tushuntirish uchun hojat
qolmasligi uchun dastur qismiga sharh sifatida qoldiriladigan izohlar
hisoblanadi.
19. O'zgaruvchi - xotiraning nomlangan qismi bo’lib, o’zida ma’lum
bir toifadagi qiymatlarni saqlaydi. O‘zgaruvchining nomi va qiymatlari
bo’ladi. O‘zgaruvchining nomi orqali qiymat saqlanayotgan xotira qismiga
murojaat qilinadi. Dastur ishlashi jarayonida o‘zgaruvchining qiymatini
o‘zgartirish mumkin. Har qanday o‘zgaruvchini ishlatishdan oldin, uni e’lon
qilish lozim.
20. Xotira manzili - bu kompyuterda saqlanadigan joy nomi
hisoblanadi. Xotira manzilini olish uchun & dan foydalanib olishimiz
mumkin. Bundan tashqari o'zgaruvchi xotira manzilini olish uchun ham
foydalanish mumkin.
21. Enum – yangi ma’lumotlar turlarini yaratish va qiymatlari
o’zgarmas bo‘lgan o’zgaruvchilar to’plami.

369
22. O‘zgarmas - bu konstanta hisoblanadi. C++ dasturlash tilida
o'zgarmaslarni e'lon qilish uchun const kalit so'zidan foydalanib ushbu
o'zgaruvchini o'zgarmas deb e'lon qilinadi.
23. Ifoda - ma’lumotlar bo‘yicha amallarni bajarish tartibini
belgilaydi, ular operatorlardan (o‘zgarmaslar, o‘zgaruvchilar, funksiyalar),
qavslar va amal belgilaridan iborat.
24. Operator -o'zgaruvchilar va qiymatlar bo'yicha amallarni
bajarish uchun ishlatiladi.
25. Encapsulation(Enkapsulatsiya)- ning ma'nosi , "sezgir"
ma'lumotlar foydalanuvchilardan yashirilganligiga ishonch hosil qilishdir.
26. Massiv indekslari - massiv elementlarini bir biridan farqlash va
ularga murojaat qilishda ishlatiladi. Ular 0 dan boshlanadi: [0] birinchi
element. [1] ikkinchi element va boshqalar.
27. Meros - bu odatda bitta sinf dan qayta-qayta foydalanish
imkoniyatini beradi. Yangi sinf yaratishda sinf attributlaridan foydalanish
imkoniyati.
28. Polimorfizm - ko'p shakllar ma`nosini anglatadi. Umuman
olganda, polimorfizm sinflar ierarxiyasi mavjud bo'lganda paydo bo'ladi va
ular meros bilan bog'liq. C ++ polimorfizmi shuni anglatadiki, a'zo
funksiyasini chaqirish ushbu funksiyani chaqiradigan obyekt turiga qarab
boshqa funksiyani bajarishga olib keladi.
29. Global o‘zgaruvchilar - ham asosiy dasturda, ham funksiyada
ishlatish mumkin bo'lgan o‘zgaruvchilar global o'zgaruvchilar deyiladi.
Global o'zgaruvchilar asosiy dasturda e`lon qilishi kerak.
30. Lokal o‘zgaruvchilar - faqat funksiyada ishlatish mumkin
bo'lgan o'zgaruvchilarga lokal o'zgaruvchilar deyiladi. Ular funksiya ichida
e`lon qilinadi.
31. Spetsifikator - sinf a'zolariga (atributlari va usullari) qanday
kirish mumkinligini belgilaydi.
32. Modellashtirish tili - har qanday sun'iy til ifodalash uchun
ishlatilishi mumkin ma`lumot yoki bilim tuzilishi, bu izchil qoidalar
to'plami bilan belgilanadi. Qoidalar tarkibidagi tarkibiy qismlarning
ma'nosini izohlash uchun ishlatiladi.
33. Konstruktor - sinf bilan bir xil nomga ega, u doimo public
bo'ladi va u hech qanday qiymat qaytarmaydi.
34. Konstruktor parametrlari - konstruktorlar parametrlarni
(odatdagi funksiyalar kabi) ham olishi mumkin, bu esa atributlar
uchun boshlang'ich qiymatlarni o‘zlashtirishda foydali bo‘lishi
mumkin.

370
35. Istisnolar – dastur yozish davomida keltirib chiqaradigan
xatoliklarni bartaraf etish ishlatiladi va uch guruhga bo’linadi.
36. try - agar kiritilgan blok kodi to'g'ri bo'lgan holda boshlanishi
kerak bo'ladigan kalit so'zi.
37. throw - maxsus xatolikni kutish uchun ishlatish mumkin
38. catch - agar yuqoridagi kalit so'zlar tarkibidagi blok kod xatolik
yuzaga kelsa ushbu kalit so'zdan foydalaniladi.
39. Interpretator - dasturlash tilida yozilgan kodni bosqichma-
bosqich mashina kodiga aylantirib, tahlil qiladi va berilgan buyruqlarni
ketma-ketlikda bajaradi. Agar xatolik sodir bólsa, ósha zahoti xabar beradi.
40. Preprotsessorlar - ko'rsatmalar bo'lib, ular kompilyatorga
haqiqiy kompilyatsiya boshlanishidan oldin ma'lumotni qayta ishlash
bo'yicha ko'rsatmalar beradi.
41. Return - funksiyani tugatadi va boshqaruvni chaqirilayotgan
funksiyaga qaytaradi (yoki boshqaruv asosiy funksiyadan uzatilsa
operatsion tizimga qaytaradi).
42. RAM (random access memory -tasodifiy kirish xotirasi) - bu
kompyuterning qisqa muddatli xotirasi bo'lib, u yerda protsessor hozirda
foydalanayotgan ma'lumotlar saqlanadi. Sizning kompyuteringiz RAM
xotirasiga qattiq disk, SSD yoki boshqa uzoq muddatli saqlash qurilmasidagi
ma'lumotlarga qaraganda tezroq kirishi mumkin, shuning uchun RAM hajmi
tizim ishlashi uchun juda muhimdir.
43. Ichki sinf (nested class) - boshqa sinf ichida joylashgan sinf.
Odatda, ichki sinflar faqat tashqi sinf obyekti ichida mavjud bo‘lishi
mumkin bo'lgan obyektlarni tavsiflash uchun ishlatiladi.
44. Intellektual tizim – sun’iy intellekt metodlari asosida aniq bir
predmetli sohaga tegishli intellektual masalalarni yechishga mo‘ljallangan
dasturiy yoki texnik tizimlar.
45. Jamiyatni axborotlashtirish – jamiyatning har bir a’zosiga
davlat siridan tashqari istalgan axborot manbalaridan erkin foydalanish
imkoniyatini taqdim etuvchi o‘zaro bog‘liq siyosiy, ijtimoiy-iqtisodiy va
ilmiy omillar to‘plami.
46. Matn muharriri – istalgan maqsaddagi (oddiy hujjat matni,
dastur matni va h.k.) matnni yaratish va tahrirlash uchun mo‘ljallangan
kompyuter dasturi.
47. Matn protsessori – asosan matniy hujjat bilan ishlash dasturlari
bo‘lib, ular matn muharirlari uchun ishni tashkil etuvchi muhit vazifasini
ham bajaradi.

371
XULOSA

Xulosa o‘rnida, C++ dasturlash tilining imkoniyatlari va


yutuqlarini sanab o‘tish lozim. Bular quyidagilar:
1. Portativlik
C++ foydalanuvchiga bir xil dasturni turli xil operatsion tizimlarda
yoki interfeyslarda bemalol ishlashga imkon beradigan portativlik yoki
platforma mustaqilligi xususiyatini taklif etadi. Aytaylik, siz LINUX
OS-da dastur yozasiz va biror bir sababga ko'ra siz WINDOWS OS-ga
o'tasiz, xuddi shu dasturni WINDOWS da ham xatosiz ishlatishingiz
mumkin. Bu xususiyat dasturchi uchun katta qulaylik ekanligini
isbotlaydi.
2. Obyektga yo'naltirilgan dasturlash
C++ ning eng katta afzalliklaridan biri bu sinflar, meros, polimorfizm,
ma'lumotlarni abstraktsiyalash va inkapsulyatsiya kabi tushunchalarni
o'z ichiga olgan obyektga yo'naltirilgan dasturlash xususiyati bo'lib,
kodni qayta ishlatishga imkon beradi va dasturni yanada ishonchli
qiladi. Nafaqat bu, balki ma'lumotlarni obyekt sifatida ko'rib chiqish
orqali real muammolarni hal qilishga yordam beradi. C ++ da
ma'lumotlarni inkapsulyatsiya qilish tushunchasini o'zlashtiramiz
3. Ko'p paradigma
C++ - ko'p paradigmali dasturlash tili. "Paradigma" atamasi
dasturlash uslubini anglatadi. U dasturning mantig'i, tuzilishi va
tartibini o'z ichiga oladi. Umumiy, imperativ va obyektga yo'naltirilgan
C++ning uchta paradigmasi. Keling, umumiy dasturlash nimani
anglatishini tushunishga harakat qilaylik. Umumiy dasturlash bir nechta
maqsadlarga xizmat qilish uchun bitta g'oyadan foydalanishni
anglatadi.
4. Past darajadagi manipulyatsiya
C++ mashina tili bilan chambarchas bog'liq bo'lgan protsessual til
bo'lgan C bilan chambarchas bog'liq bo'lganligi sababli, C++ ma'lum
darajada ma'lumotlarni past darajada manipulyatsiya qilishga imkon
beradi. O'rnatilgan tizimlar va kompilyator C++yordamida yaratiladi.
5. Xotirani Boshqarish
C++ dasturchiga xotirani boshqarish ustidan to'liq nazoratni
ta'minlaydi. Buni ham aktiv, ham majburiyat sifatida ko'rib chiqish
mumkin, chunki bu Foydalanuvchining xotirani axlat yig'uvchi
tomonidan boshqarilishidan ko'ra boshqarish mas'uliyatini oshiradi.
372
Ushbu konsepsiya ko'rsatgichlar yordamida DMA (dinamik xotira
ajratish) yordamida amalga oshiriladi.
6. Katta Jamoatchilikni Qo'llab-Quvvatlash
C++ da pullik va bepul onlayn kurslar va ma'ruzalar bilan
ta'minlash orqali uni qo'llab-quvvatlaydigan katta hamjamiyat mavjud.
Statistik aytganda, C++ Stackoverve va GitHub bo‘yicha eng ko'p
ishlatiladigan til hisoblanadi.
7. C bilan moslik
Deyarli har bir xatosiz C dasturi haqiqiy C++ dasturidir. Amaldagi
kompilyatorga qarab, C++ ning har bir dasturi .cpp kengaytmali faylda
ishlashi mumkin.
8. Miqyosi
O'lchovlilik dasturning masshtablash qobiliyatini anglatadi. Bu
shuni anglatadiki, C++ dasturi kichik hajmdagi va katta hajmdagi
ma'lumotlarni ishlashga qodir. Shuningdek, biz resurslarni talab
qiladigan dasturlarni yaratishimiz mumkin.
Ta`kidlash kerakki, C++ dasturlash tili (1-qism) kelajakda OTM
talabalari uchun dasturlash tilini o‘rganishda “ko‘makdosh” vazifasini
o‘taydi.
Hozirgi zamonda dasturchi eng zamonaviy, eng hamyonbop va
ilg`or kasblardan biri. Dasturchilik kasblariga Web-masalachi, Sistema
adminstratori, IT operator, Flash animator va hokazolar kiradi. Yaxshi
dasturchi bo‘lish uchun nima talab qilinadi deb o‘ylaysiz? Buyuk
dasturchilarimiz fikricha, dasturlashni o‘rganishning eng yaxshi usuli
qiyinroq dasturlar kodlarini o‘rganib, ishlatib ko‘rishdir.Darslik tadbiq
qilingandan so‘ng o‘rganuvchilarning dastur tuzish ko‘nikmasi
shakllanib, mustaqil dasturchi bo‘la olishiga zamin yaratiladi.

373
FOYDALANILGAN ADABIYOTLAR RO‘YXATI

1. O‘zbekiston Respublikasi Prezidentining 2018 yil 13 dekabrdagi


“O‘zbekiston Respublikasi davlat boshqaruviga sonli iqtisodiyot,
elektron hukumat hamda axborot tizimlarini joriy etish bo‘yicha
qo‘shimcha chora-tadbirlar to‘g‘risida”gi PF-5598-son Farmoni.
2. A.A.Xaldjigitov, Sh.F.Madraximov, U.E.Adamboev, Informatika
va programmalash. O’quv qo’llanma, O’zMU, 2005 yil, 145 bet.
3. Algorithms, Fourth Edition (Deluxe): Book and 24-Part Lecture
Series 1st Edition , Addison-Wesley Professional , USA, 2015.
4. Mirsanov U.M., Toxirov F.J., Norbekov A.O., Djurayeva D.R.
Dasturlash. // O‘quv qo‘llanma. Toshkent, 2021. – 152 b.
5. O.Shukurov, F.Qorayev, E.Eshboyev, B.Shovaliyev
“Programmalashdan masalalar to’plami”, Toshkent 2008,160 bet.
6. Ro‘ziyev R.A. Dasturlash asoslari // O‘quv qo‘llanma. - Toshkent,
2020. –159 b.
7. Б. Страуструп, “Язык программирования С++. Специальное
издание”,-М.:ООО «Бином-Пресс», 2006.-1104 с.
8. Герберт Шилдт: С++ базовый курс.
9. Глушаков С.В., Коваль А.В., Смирнов С.В. Язык
программирования С++: Учебный курс.- Харьков: Фолио; М.:
ООО «Издательство АСТ», 2001.-500с.
10. Джес Либерти “Освой самостоятельно С++ за 21 день”, Моска,
819 стр.
11. Никита Культин, “Microsoft Visual C++ в задачах и примерах”,
БХВ-Петербург - Петербург.:2010.
12. Сидхарма Рао, «Освой самостоятельно С++ за 21 день»,
Вильямс - М.: 2013.
13. Стенли Липпман. Язык программирование С++. Базовой курс.
Вильямс - М.: 2014.
14. Стефан Р. Дэвис, “C++ для "чайников", 4-е издание.
15. Харви Дейтел, Пол Дейтел “КАК ПРОГРАММИРОВАТЬ НА
C++”.
16. Ш.Ф. Мадрахимов, С. М. Гайназаров С++ тилида
программалаш асослари. Т. 2009.

374
Internet resurslari:
17. www.gov.uz – O‘zbekiston Respublikasi hukumat portali.
18. www.lex.uz - O‘zbekiston Respublikasi Qonun hujjatlari milliy
bazasi.
19. www.ziyonet.uz – Axborot ta’lim portali.
20. www.edu.uz – Oliy va o‘rta maxsus ta’lim vazirligi portali.
21. www.buxdu.uz – buxdu rasmiy sayti.
22. http://www.uzbekcoders.uz - bir million o‘zbek dasturchisi loyihasi
23. http://cppstudio.com/
24. www.w3resource.com
25. https://metanit.com/cpp/tutorial/1.1.php
26. https://uzbekdevs.uz/darsliklar/cpp/cpp-da-kirish
27. www.Intuit.ru. Интернет-Университет информационных техно-
логий.

375
M. A. Bobojonova

DASTURLASH ASOSLARI 1-QISM


(Darslik)

60610200-Axborot tizimlari va texnologiyalari


(tarmoqlar va sohalar bo‘yicha)

Muharrir: E.Eshov
Tex. muharrir: D.Abduraxmonova
Musahhih: M.Shodiyeva
Badiiy rahbar: M.Sattorov

Nashriyot litsenziyasi № 022853. 08.03.2022.


Original maketdan bosishga ruxsat etildi: 30.11.2023. Bichimi
60x84. Kegli 16 shponli. “Times New Roman” garnitura 1/16.
Ofset bosma usulida. Ofset bosma qog‘ozi.
Bosma tabog‘i 23,5. Adadi 100. Buyurtma № 231

“BUXORO DETERMINANTI” MCHJ


bosmaxonasida chop etildi.
Buxoro shahar Namozgoh ko‘chasi 24 uy
Tel:. + 998 91 310 27 22
376

You might also like