1. KIRISH
C++ dasturlash tili C tiliga asoslangan. C esa o'z navbatida B va BCPL tillaridan kelib chiqqan. BCPL 1967 yilda Martin Richards tomonidan tuzilgan va operatsion sistemalarni yozish uchun mo'ljallangan edi. Ken Thompson o'zining B tilida BCPL ning ko'p hossalarini kiritgan va B da UNIX operatsion sistemasining birinchi versiyalarini yozgan.
BCPL ham, B ham tipsiz til bo'lgan. Yani o'garuvchilarning ma'lum bir tipi bo'lmagan - har bir o'zgaruvchi kompyuter hotirasida faqat bir bayt yer egallagan. O'zgaruvchini qanday sifatda ishlatish esa, yani butun sonmi, kasrli sonmi yoki harfdekmi, dasturchi vazifasi bo'lgan.
C tilini Dennis Ritchie B dan keltirib chiqardi va uni 1972 yili ilk bor Bell Laboratories da, DEC PDP-11 kompyuterida qo'lladi. C o'zidan oldingi B va BCPL tillarining juda ko'p muhim tomonlarini o'z ichiga olish bilan bir qatorda o'zgaruvchilarni tiplashtirdi va bir qator boshqa yangiliklarni kiritdi. Boshlanishda C asosan UNIX sistemalarida keng tarqaldi. Hozirda operatsion sistemalarning asosiy qismi C/C++ da yozilmoqda. C mashina arhitekturasiga bog'langan tildir. Lekin yahshi rejalashtirish orqali dasturlarni turli kompyuter platformalarida ishlaydigan qilsa bo'ladi.
1983 yilda, C tili keng tarqalganligi sababli, uni standartlash harakati boshlandi. Buning uchun Amerika Milliy Standartlar Komiteti (ANSI) qoshida X3J11 tehnik komitet tuzildi. Va 1989 yilda ushbu standart qabul qilindi. Standartni dunyo bo'yicha keng tarqatish maqsadida 1990 yilda ANSI va Dunyo Standartlar Tashkiloti (ISO) hamkorlikda C ning ANSI/ISO 9899:1990 standartini qabul qilishdi.
Shu sababli C da yozilgan dasturlar kam miqdordagi o'zgarishlar yoki umuman o'zgarishlarsiz juda ko'p kompyuter platformalarida ishlaydi.
C++ 1980 yillar boshida Bjarne Stroustrup tomonidan C ga asoslangan tarzda tuzildi. C++ juda ko'p qo'shimchalarni o'z ichiga olgan, lekin eng asosiysi u ob'ektlar bilan dasturlashga imkon beradi.
Dasturlarni tez va sifatli yozish hozirgi kunda katta ahamiyat kasb etmoda. Buni ta'minlash uchun ob'ektli dasturlash g'oyasi ilgari surildi. Huddi 70-chi yillar boshida strukturali dasturlash kabi, programmalarni hayotdagi jismlarni modellashtiruvchi ob'ektlat orqali tuzish dasturlash sohasida inqilob qildi.
C++ dan tashqari boshqa ko'p ob'ektli dasturlshga yo'naltirilgan tillar paydo bo'ldi. Shulardan eng ko'zga tashlanadigani Xerox ning Palo Altoda joylashgan ilmiy-qidiruv markazida (PARC) tuzilgan Smalltalk dasturlash tilidir. Smalltalk da hamma narsa ob'ektlarga asoslangan. C++ esa gibrid tildir. Unda C ga o'hshab strukturali dasturlash yoki yangicha, ob'ektlar bilan dasturlash mumkin. Yangicha deyishimiz ham nisbiydir. Ob'ektli dasturlash falsafasi paydo bo'lganiga ham yigirma yildan oshayapti.
C++ funksiya va ob'ektlarning juda boy kutubhonasiga ega. Yani C++ da dasturlashni o'rganish ikki qismga bo'linadi. Birinchisi bu C++ ni o'zini o'rganish, ikkinchisi esa C++ ning standart kutubhonasidagi tayyor ob'ekt/funksiyalarni qo'llashni o'rganishdir.
C++ DA DASTURLASHNING ASOSIY QISMLARI
C++ sistemasi asosan quyidagi qismlardan iborat. Bular dasturni yozish redaktori, C++ tili va standart kutubhonalardir. C++ dasturi ma'lum bir fazalardan o'tadi. Birinchisi dasturni yozish va tahrirlash, ikkinchisi preprosessor amallarini bajarish, kompilyatsiya, kutubhonalardagi ob'ekt va funksiyalarni dastur bilan bog'lash (link), hotiraga yuklash (load) va bajarish (execute).
C++ DA BIRINCHI PROGRAMMA
//C++ dagi ilk dasturimiz
/*Ekranga yozuv chiqarish*/
# include
int main()
{
cout << "Hello World!\n";
return 0; //Dastur kutulganidek tugaganinig belgisi.
}
Ekranda:
Hello World!
Dasturni satrma-satr tahlil qilaylik. C++ da ikki tur sharhlar mavjud. /* bilan boshlanib, */ bilan tugaydigani bir necha satrni egallashi mumkin. Yani bu belgilar orasida qolgan hamma yozuv sharh hisoblanadi. Bu tur sharh C dan qolgan. C++ yangi ko'rinishdagi sharhlar ham kiritilgan. Bu // bilan boshlanadi va kuchi shu satr ohirigacha saqlanadi. Sharhlar yoki boshqacha qilib aytganda kommentariylar kompilyator tomonidan hisobga olinmaydi va hech qanday mashina ijro kodiga aylantirilmaydi. Sharhlar kerakli joyda, funksiyalardan oldin, o'zgaruvchilar e'lonidan keyin yozilganda, dasturni tushunish ancha osonlashadi va keyinchalik programma ishlash mantig'ini esga solib turadi.
# include bu preprosessorga beriladigan buyruqdir. Preprosessor kompilyatsiyadan oldin fayllarni ko'rib chiqadi va kerakli amallarni bajaradi. Unga tegishli bo'lgan buyruqlar # belgisi bilan boshlanadi lekin buyruq ohiriga nuqta-vergul (;) qoyilmaydi. Bu yerda include (kiritmoq, qamrab olmoq) buyrug'i iostream.h faylini asosiy dasturimiz ichiga kiritadi. Bu fayl ichida biz ishlatayotgan cout oqim (stream) ob'ektining e'loni berilgan. C++ stilida ekran yoki klaviaturadan kirish/chiqishni bajarmoqchi bo'lgan barcha dasturlar ushbu boshliq (header) faylni yoki uning yangi ko'rinishini include bilan o'z ichiga olishi kerak. Bu kabi fayllarni biz bundan keyin e'lon fayllari deb ataymiz. Chunki bu fayllar ichida funksiya va ob'ektlarning o'zi, yani tanasi berilmay faqatgina e'loni beriladi.
include buyrug'i ikki hil yo'l bilan qo'llanilishi mumkin.
1. include
2. include "meningfaylim.h"
Birinchi usulda e'lon fayli <> qavslari ichida yoziladi. Bunda C++ sistemasi
ushbu faylni oldindan belgilangan kataloglar ichidan qidiradi. Bu usul bilan
asosan standart kutubhona fayllari qo'llaniladi. Ikkinchi usulda, fayl nomi
qo'shtirnoqlarga olinganda, kiritilishi kerak bo'lgan fayl joriy katalogdan
qidiriladi. Bu yo'l bilan dasturchi o'zi yozgan e'lon fayllarini kiritadi.
Shuni aytib o'tish kerakki, C++ ning 1998 yili qabul qilingan standartiga
ko'ra, ushbu e'lon fayllari yangi ko'rinishga ega, ular .h bilan tugamaydi.
Bunda, misol uchun, bizning iostream.h faylimiz iostream, C dan kelgan math.h
esa cmath nomiga ega. Biz bu o'zgarishlarga keyinroq qaytamiz, hozircha esa
eski tipdagi e'lon fayllaridan foydalanib turamiz.
int main() har bir C++ dasturining qismidir. main dan keyingi () qavslar
C++ ning funksiya deb ataluvchi blokining boshlangangini bildiradi. C++ dasturi
bir yoki bir necha funksiyalardan iborat. Va shulardan aniq bitta funksiya
main deb atalishi shart. Bunda main dastur ichida keladigan birinchi funksiya
bo'lmasligi ham mumkin. Operatsion sistema dastur ijrosini main() funksiyasidan
boshlaydi.
main() dan oldin kelgan int esa main funksiyasidan qaytish qiymati tipini
belgilaydi. Bunda int integer, yani butun son deganidir. main() ning qaytargan
qiymati operatsion sistemaga boradi.
{ qavs funksiya va boshqa bloklar tanasini boshlaydi. Blokni yopish uchun }
qavsi ishlatilinadi.
cout << "Hello World!\n"; satri C++ da ifoda deb ataladi. C++ dagi har bir
ifoda ; (nuqta-vergul) bilan tugatilishi shart. Ortiqcha ; bo'sh ifoda
deyiladi. Uni qo'yish dastur tezligiga ta'sir qilmaydi.
Kirish va chiqish (Input/Output), yani dasturga kerakli ma'lumotlarni kiritish
va ular ustida dastur tomonidan bajarilgan amallar natijalarini olish C++ da
oqim ob'ektlari orqali bajarilishi mumkin. Lekin kirish/chiqishni C dagi kabi
funksiyalar bilan ham amalga oshirsa bo'ladi.
C++ falsafasiga ko'ra har bir kirish/chiqish jihozi (ekran, printer,
klaviatura...) baytlar oqimi bilan ishlagandek qabul qilinadi.
Yuqoridagi ifoda bajarilganda bizning "Hello World!" gapimiz standart chiqish
oqimi ob'ekti cout ga (cout - console out) jo'natiladi. Normal sharoitda bu
oqim ekranga ulangandir.
C++ da satrlar (string) qo'shtirnoqlar (") orasida bo'ladi. Bitta harfli
literalar esa bitta tirnoq - apostrof (') ichiga olinadi. Misol uchun: 'A',
'$'. Bitta harf yoki belgini qo'shtirnoq ichiga olsa u satr kabi qabul
qilinadi.
<< operatori oqimga kiritish operatori deyiladi. Programma ijro etilganda <<
operatorining o'ng tomonidagi argument ekranga yuboriladi. Bunda ekranga
qo'shtirnoq ("...") ichidagi narsa bosib chiqariladi. Lekin e'tibor bersak, \n
belgisi bosilmadi. \ (teskari kasr - backslash) belgisi mahsus ma'noga ega.
U o'zidan keyin kelgan belgi oqim buyrug'i yoki manipulyatori ekanligini
bildiradi. Shunda \ belgisi bilan undan keyin kelgan belgi buyruq
ketma-ketligida aylanadi. Bularning ro'hatini beraylik.
\n - Yangi satr. Kursor yangi qator boshidan joy oladi.
\t - Gorizontal tabulyatsiya (kursor bir-necha harf o'nga siljiydi).
\v - Vertikal tabulyatsiya (bir-necha satr tashlanib o'tiladi).
\r - Qaytish. Kursor ayni satr boshiga qaytadi, yani yangi satrga o'tmaydi.
\a - Kompyuter dinamiki chalinadi.
\\ - Ekranga teskari kasr belgisini bosish uchun qo'llaniladi.
\" - Ekranga qo'shtirnoq belgisini bosish uchun qo'llaniladi.
return 0; (return - qaytmoq) ifodasi main() funksiyasidan chiqishning asosiy
yo'lidir. 0 (nol) qiymatining qaytarilishi operatsion sistemaga ushbu dastur
normal bajarilib tugaganini bildiradi. return orqali qaytadigan qiymat tipi
funksiya e'lonidagi qaytish tipi bilan bir hil bo'lishi kerak. Bizda bu
e'lon int main(){...} edi. Va 0 int tipiga mansubdir. Bundan keyin return
orqali qaytarilayotgan ifodani qavs ichiga olamiz. Misol uchun return (6).
Bu qavslar majburiy emas, lekin bizlar ularni programmani o'qishda qulaylik
uchun kiritamiz.
BOSHQA BIR DASTUR
//Ushbu dastur ikki butun sonni ko'paytiradi.
# include
int main()
{
int sonA, sonB; //o'zgaruvchi e'lonlari
int summa; //e'lon
cout << "Birinchi sonni kiriting: ";
cin >> sonA; //Birinchi sonni o'qish...
cout << "Ikkinchi sonni kiriting: ";
cin >> sonB; //Ikkinchi sonni o'qish...
summa = sonA * sonB;
cout << summa << endl;
cout << "sonA * sonB = " << sonA * sonB << endl;
return (0);
}
Ekranda:
Birinchi sonni kiriting: 4
Ikkinchi sonni kiriting: 6
24
sonA * sonB = 24
int sonA, sonB; ifodasi int tipidagi, yani integar (butun son) bo'lgan ikkita
o'zgaruvchini e'lon (declaration) qildik. Agar o'zgaruvchilar tipi bir hilda
bo'lsa, yuqoridagi kabi ularni ketma-ket, vergul bilan ayirib yozsak bo'ladi.
Keyingi satrda esa int summa; bilan summa nomli o'zgaruvchini e'lon qildik.
cout << "Birinchi sonni kiriting: "; ifodasi bilan ekranga nima qilish
kerakligini yozib chiqdik. cin >> sonA; amali cin kirish oqimi ob'ekti orqali
sonA o'zgaruvchisiga klaviaturadan qiymat kiritmoqda. Sonni yozib bo'lgandan
so'ng Enter ni bosamiz. Normal sharoitda kirish oqimi klaviaturaga bog'langan.
Shu tariqa sonB ga ham qiymat berdik. Keyin esa summa = sonA * sonB; bilan biz
ikki o'zgaruvchini ko'paytirib, ko'paytma qiymatini summa ga beryapmiz. Bu
yerdagi "=" va "*" operatorlar ikki argumentli operatorlar deyiladi, chunki
ular ikkita operand yoki boshqacha qilib etkanda kirish qiymatlari bilan
ishlaydi. Operatorlardan oldin va keyin bo'sh yer qoldirsak, o'qishni
osonlashtirgan bo'lamiz.
Ekranga javobni chiqarganda, cout ga tayyor natijani (summa) yoki matematik
ifodaning o'zini berishimiz mumkin. Ohirgi cout ga bir-necha argumentni berdik.
endl (end line - satrni tugatish) bu oqim manipulyatoridir
(stream manipulator). Ba'zi bir sistemalar chiqish oqimiga yo'naltirilgan
ma'lumotlarning ma'lum bir miqdori yig'ilguncha ushbu ma'lumotlarni ekranga
bosib chiqarmay, buferda saqlashadi. Va o'sha chiqish buferi to'lgandan
keyingina ma'lumotlarni ekranga yuborishadi. Buning sababi shuki, ekranga
bosish nisbatan vaqt jihattan qimmat amaldir. Agar ma'lumotlar yig'ilib turib,
bittada chiqarilsa, dastur ancha tez ishlaydi. Lekin biz yuqoridagi dasturdagi
kabi qo'llanuvchi bilan savol-javob qiluvchi programmada yo'l-yo'riqlarimizni
berilgan paytning o'zida ekranga bosib chiqarilishini hohlaymiz. Shu sababli
biz endl ni ishlatishimiz kerak.
endl ni biz "\n" buyrug'iga tenglashtirishimiz mumkin. Yani endl ni
ishlatganimizda, bufer yoki boshqacha qilib aytganda, hotiradagi ma'lumotni
vaqtinchalik saqlanish joyidagi informatsiya ekranga bosib chiqarilgandan
so'ng, kursor yangi satr boshiga ko'chadi. Agar biz buferni bo'shatmoqchi-yu,
lekin kursorni joyida saqlab qolmoqchi bo'lsak, flash manipulyatorini
ishlatishimiz lozim.
Ifodamizga qaytaylik. cout << "sonA * sonB = " << sonA * sonB << endl;
ifodasida chiqish ob'ekti bitta, lekin biz unga uchta narsani yubordik. Buni
biz oqimga ma'lumotlarni chiqarishni kaskadlash, zanjirlash yoki
konkatenatsiya qilish deb ataymiz. Ayni amalni cin (console in) kirish oqimi
uchun ham bajara olamiz.
Hisob-kitoblar chiqish ifodasi ichida ham bajarilishi mumkin,
cin << sonA *sonB << endl; bunga misol. Agar bu yo'lni tutganimizda, summa
o'zgaruvchisi kerakmas bo'lib qolardi.
Ushbu dasturda bizda yangi bo'lgan narsalardan biri bu o'zgaruvchi (variable)
tushunchasidir. O'zgaruvchilar kompyuter hotirasidagi joylarga ko'rsatib
turishadi. Har bir o'zgaruvchi ism, tip, hotirada egallagan joy kattaligi va
qiymatga egadir. O'zgaruvchi ismi katta-kichik harf, son va past tiredan
( _ - underscore) iboratdir. Lekin sondan boshlana olmaydi. C/C++ da
katta-kichik harf, yani harflar registri farqlanadi. Misol uchun A1 va a1
farqli ismlardir.
C++ DA ARIFMETIK AMALLAR
Ko'p programmalar ijro davomida arifmetik amallarni bajaradi. C++ dagi amallar
quyidagi jadvalda berilgan. Ular ikkita operand bilan ishlatdi.
C++ dagi amal Arifmetik operator Algebraik ifoda C++ dagi ifodasi
Qo'shish + h+19 h+19
Ayirish - f-u f-u
Ko'paytirish * sl s*l
Bo'lish / v/d, vod v/d
Modul olish % k mod 4 k%4
Bularning ba'zi birlarinig hususiyatlarini ko'rib chiqaylik. Butun sonli
bo'lishda, yani bo'luvchi ham, bo'linuvchi ham butun son bo'lganda, javob
butun son bo'ladi. Javob yahlitlanmaydi, kasr qismi tashlanib yuborilib,
butun qismining o'zi qoladi.
Modul operatori (%) butun songa bo'lishdan kelib chiqadigan qoldiqni beradi.
x%y ifodasi x ni y ga bo'lgandan keyin chiqadigan qoldiqni beradi. Demak, 7%4
bizga 3 javobini beradi. % operatori faqat butun sonlar bilan ishlaydi.
Vergulli (real) sonlar bilan ishlash uchun "math.h" kutubhonasidagi fmod
funksiyasini qollash kerak.
C++ da qavslarning ma'nisi huddi algebradagidekdir. Undan tashqari boshqa
boshqa algebraik ifodalarning ketma-ketligi ham odatdagidek. Oldin
ko'paytirish, bo'lish va modul olish operatorlari ijro ko'radi. Agar bir necha
operator ketma-ket kelsa, ular chapdan o'nga qarab ishlanadi. Bu
operatorlardan keyin esa qo'shish va ayirish ijro etiladi.
Misol keltiraylik. k = m * 5 + 7 % n / (9 + x);
Birinchi bo'lib m * 5 hisoblanadi. Keyin 7 % n topiladi va qoldiq (9 + x) ga
bo'linadi. Chiqqan javob esa m * 5 ning javobiga qo'shiladi. Qisqasini aytsak,
amallar matematikadagi kabi. Lekin biz o'qishni osonlashtirish uchun va hato
qilish ehtimolini kamaytirish maqsadida qavslarni kengroq ishlatishimiz
mumkin. Yuqoridagi misolimiz quyidagi ko'rinishga ega bo'ladi.
k = ( m * 5 ) + ( ( 7 % n ) / ( 9 + x ) );
MANTIQIY SOLISHTIRISH OPERATORLARI
C++ bir necha solishtirish operatorlariga ega.
Algebraik ifoda C++ dagi operator C++ dagi ifoda Algebraik ma'nosi
tenglik guruhi
= == x==y x tengdir y ga
teng emas != x!=y x teng emas y ga
solishtirish guruhi
> > x>y x katta y dan
< < x
katta-teng >= x>=y x katta yoki teng y ga
kichik-teng <= x<=y x kichik yoki teng y ga
==, !=, >= va <= operatorlarni yozganda oraga bo'sh joy qo'yib ketish
sintaksis hatodir. Yani kompilyator dasturdagi hatoni ko'rsatib beradi va uni
tuzatilishini talab qiladi. Ushbu ikki belgili operatorlarning belgilarining
joyini almashtirish, masalan <= ni =< qilib yozish ko'p hollarda sintaksis
hatolarga olib keladi. Gohida esa != ni =! deb yozganda sintaksis hato vujudga
ham, bu mantiqiy hato bo'ladi. Mantiqiy hatolarni kompilyator topa olmaydi.
Lekin ular programma ishlash mantig'ini o'zgartirib yuboradi. Bu kabi
hatolarni topish esa ancha mashaqqatli ishdir (! operatori mantiqiy inkordir).
Yana boshqa hatolardan biri tenglik operatori (==) va tenglashtirish, qiymat
berish operatorlarini (=) bir-biri bilan almashtirib qo'yishdir. Bu ham juda
ayanchli oqibatlarga olib keladi, chunki ushbu hato aksariyat hollarda mantiq
hatolariga olib keladi.
Yuqoridagi solishtirish operatorlarini ishlatadigan bir dasturni ko'raylik.
//Mantiqiy solishtirish operatorlari
# include
int main()
{
int s1, s2;
cout << "Ikki son kiriting: " << endl;
cin >> s1 >> s2; //Ikki son olindi.
if (s1 == s2) cout << s1 << " teng " << s2 << " ga" << endl;
if (s1 < s2) cout << s1 << " kichik " << s2 << " dan" << endl;
if (s1 >= s2) cout << s1 << " katta yoki teng " << s2 << " ga" << endl;
if (s1 != s2) cout << s1 << " teng emas " << s2 << " ga" << endl;
return (0);
}
Ekranda:
Ikki sonni kiroting: 74 33
74 katta yoki teng 33 ga
74 teng emas 33 ga
Bu yerda bizga yangi narda bu C++ ning if (agar) strukturasidir. if ifodasi
ma'lum bir shartning to'g'ri (true) yoki noto'g'ri (false) bo'lishiga qarab,
dasturning u yoki bu blokini bajarishga imkon beradi. Agar shart to'g'ri
bo'lsa, if dan so'ng keluvchi amal bajariladi. Agar shart bajarilmasa, u holda
if tanasidagi ifoda bajarilmay, if dan so'ng kelunchi ifodalar ijrosi davom
ettiriladi. Bu strukturaning ko'rinishi quyidagichadir:
if (shart) ifoda;
Shart qismi qavs ichida bo'lishi majburiydir. Eng ohirida keluvchi
nuqta-vergul (;) shart qismidan keyin qo'yilsa ( if (shart); ifoda; ) mantiq
hatosi vujudga keladi. Chunki bunda if tanasi bo'sh qoladi. ifoda qismi esa
shartning to'g'ri-noto'g'ri bo'lishiga qaramay ijro ko'raveradi.
C++ da bitta ifodani qo'yish mumkin bo'lgan joyga ifodalar guruhini ham
qo'yish mumkin. Bu guruhni {} qavslar ichida yozish kerak. if da bu bunday
bo'ladi:
if (shart) {
ifoda1;
ifoda2;
...
ifodaN;
}
Agar shart to'g'ri javobni bersa, ifodalar guruhi bajariladi, aksi taqdirda
blokni yopuvchi qavslardan keyingi ifodalardan dastur ijrosi davom ettiriladi.
YANGI STILDAGI E'LON FAYLLARI VA ISMLAR SOHASI TUSHUNCHASI
C++ ning standarti .h bilan tugaydigan (stdio.h ...) standart kutubhona e'lon
fayllarini yangittan nomlab chiqdi. Bunda .h qo'shimchasi olib tashlandi.
C dan qolgan fayllar ismiga esa c harfi qo'shildi.
Misol uchun:
iostream.h -> iostream
string.h -> cstring
stdlib.h -> cstdlib
time.h -> ctime
C dan meros qolgan kutubhona 18 ta e'lon fayli orqali berilgan. C++ ga
tegishli standart kutubhonada esa 32 ta e'lon fayl bor.
Fayllarni yangittan belgilashdan maqsad kutubhodadagi funksiya va ob'ektlarni
std deb ataluvchi ismlar sohasiga (namespace) kiritishdir.
Ismlar sohasining o'zi ham nisbatan yangi tushuncha. Ismlar sohasini alohida
dastur qismlari deb faraz qilsak boladi. Boshqa-boshqa sohalarda ayni ismli
funksiya, o'zgaruvchi nomlari va ob'ektlar berilishi mumkin. Va bunda hech
qanday ismlar to'qnashuvi sodir bo'lmaydi. Misol uchun bizda global, std va
fun::obj degan ism sohalari bo'lsin. Ularning har birining ichida esa cout
nomli ob'ekt aniqlangan bo'lsin. C++ da to'liq aniqlangan ism
(fully qualified name) degan tushuncha bor. Shunga ko'ra har bir cout
ob'ektinig to'liq ismi quyidagicha bo'ladi:
Ismlar sohasi ob'ekt
global ::cout
std std::cout
fun::obj fun::obj::cout
:: operatori sohalarni bog'lash uchun qo'llaniladi. fun::obj nomli ismlar
sohasida obj fun ichida joylashgan ism sohasidir. Global ismlar sohasida
aniqlangan funksiya va boshqa turdagi dastur birliklariga programmaning
istalgan yeridan yetishsa bo'ladi. Masalan global ismlar sohasida e'lon
qilingan int tipidagi k ismli o'zgaruvchimiz bol'sa, uning ustidan
dasturning hohlagan blokida amal bajarsak bo'ladi.
Ismlar sohasi mehanizmi dasturchilarga yangi kutubhonalarni yozish ishini
ancha osonlashtiradi. Chunki yangi kutubhonada ayni ismlar qo'llanishiga
qaramay, ismlar konflikti yuz bermaydi. Dastur yoki kutubhona yozganda yangi
ismlar sohasini belgilash uchun
namespace istalgan_ism {
...
foo();
int k;
String str;
...
}
deb yozamiz. Dasturimizda ushbu ismlar sohasida aniqlangan o'zgaruvchilarni
ishlatish uchun ularning to'liq ismini yozishimiz kerak. Masalan:
istalgan_ism::foo();
Ammo bu usul ancha mashaqqatli bo'ladi. Har bir funksiya yoki o'zgaruvchi
oldiga uning to'liq aniqlangan ismini yozish ko'p vaqt oladi. Buning o'rniga
biz
using namespace istalgan_ism;
deb yozib o'tsak kifoya. using (ishlatish, qo'llash) buyrug'i bizning ismlar
sohamizni dasturimiz ichiga tanishtiradi. Eng asosiysi biz bu amalni sohada
aniqlangan va biz qo'llamoqchi bo'lgan ismlarning ilk chaqirig'idan oldin
yozishimiz kerak. C++ ning standart kutubhonasida aniqlangan ifodalarni
qo'llash uchun biz
using namespace std;
deymiz. Va albatta qo'llanilayotgan e'lon fayllari yangi tipda bo'lishi kerak.
Endi bu tushunchalarni ishlatadigan bir dasturni keltiraylik.
//Yangi tipdagi e'lon fayllari va ismlar sohasini qo'llash.
# include
using namespace std;
int main()
{
std::cout << "Hello!\n";
cout << "Qale!";
return (0);
}
Ekranda:
Hello!
Qale!
std::cout << "Hello\n"; satrida biz chiqish oqimi ob'ekti cout ning to'liq
ismini qo'lladik. Keyingi satrda esa biz yana ayni ob'ektni ishlatdik, lekin
endi uni to'liq atab o'tirmadik, chunki biz std ismlar sohasini using bilan
e'lon qilib bo'ldik.
Ismlarni global ismlar sohasida e'lon qilish uchun ularni blok va funkisiyalar
tashqarisida aniqlash kerak. Masalan:
# include
int i;
int main()
{
...
int k;
...
return (0);
}
Bu yerda i global ismlar sohasida joylashgan, k esa main() funksiyasiga
tegishli. O'zgaruvchilarni global ism sohasida aniqlashning boshqa yo'li,
ularni nomsiz ismlar sohasida belgilashdir. Yani:
namespace {
int j;
}
j o'zgaruvchisi global boldi. Uni ishlatish uchun:
::j = ::j + 7;
:: operatorini qo'llashimiz mumkin, yoki oddiygina qalib faqat o'zini:
j = j * 9;
kabi yozishimiz mumkin. Ammo agar biz ishlayatgan dastur blokida ayni ismli
o'zgaruvchi bo'lsa, masalan j, unda ushbu lokal aniqlangan j bizning global
j imizni berkitib qo'yadi. Biz j ni o'zini qo'llasak, lokal j ga murojat
qilgan qilgan bo'lamiz. Global j ni ishlatish uchun endi :: operatorini
qo'llashga majburmiz. Bu mulohazalar umuman olganda boshqa ismlar sohalarini
ishlatganimizda ham o'rinlidir.
2. BOSHQARUV IFODALARI
Bu bo'limda biz strukturali dasturlashning asosiy prinsip va qismlarini ko'rib
chiqamiz. Ma'lum bir dasturni yozish uchun belgilangan qadamlarni bosib o'tish
kerak. Masala aniqlangandan so'ng uni yechish uchun mo'ljallangan algoritm
tuziladi. Keyin esa psevdokod yoziladi. Psevdokod algoritmda bajariladigan
qadamlarni ko'rsatadi. Bunda faqat bajariladigan ifodalar ko'rib chiqiladi.
Psevdokodda o'zgaruvchi e'lonlari yoki boshqa ma'lum bir dasturlash tiliga
mansub bo'lgan yordamchi amallar bo'lmaydi.
Psevdokodni yozish dasturlashni ancha osonlashtiradi, algoritm mantig'ini
tushunishga va uni rivojlanritishga katta yordam beradi. Misol uchun bir
dasturning rejasi va psevdokodi 3-4 oy yozilgan bo'lsa va yuqori darajada
detallashtirilgan bo'lsa, ushbu dasturning C++ yoki boshqa tildagi kodini
yozish 2-3 hafta vaqt oladi halos. Bu yozilgan programmada hato ancha kam
bo'ladi, uni keyinchalik takomillashtirish arzonga tushadi. Hozirgi paytda
dastur o'zgarishi fafqulotda hodisa emas, balki zamon talabidir.
DASTUR IJRO STRUKTURALARI
Asosan dasturdagi ifodalar ketma-ket, navbatiga ko'ra ijro etiladi. Gohida
bir shart bajarilishiga ko'ra, ijro boshqa bir ifodaga o'tadi. Navbatdagi
emas, dasturning boshqa yerida joylashgan ifoda bajariladi. Yani sakrash yoki
ijro ko'chishi vujudga keladi.
60-chi yillarga kelib, dasturlardagi ko'pchilik hatolar aynan shu ijro
ko'chishlarining rejasiz ishlatilishidan kelib chiqishi ma'lum bo'ldi. Bunda
eng katta aybdor deb bu ko'shishlarni amalga oshiruvchi goto (...ga bor)
ifodasi belgilandi. goto dastur ijrosini deyarli istalgan yerga ko'chirib
yuborishi mumkin. Bu esa programmani o'qishni va uning strukturasini
murakkablashtirib yuboradi. Shu sababli "strukturali dasturlash" atamasi
"goto ni yo'q qilish" bilan tenglashtirilardi. Shuni aytib o'tish kerakki,
goto kabi shartsiz sakrash amallarini bajaruvchi ifodalar boshqa dasturlash
tillarida ham bor.
Tadqiqotlar shuni ko'rsatdiki, istalgan programma goto siz yozilishi mumkin
ekan. goto siz yozish uslubi strukturali dasturlash deb nom oldi. Va bunday
dastur yozish metodi katta iqtisodiy samara beradi.
Strukturali dasturlash asosi shundan iboratki, har bir programma faqatgina uch
hil boshqaruv strukturalaridan iboratdir.Bular ifodalarni ketma-ket ijro etish
strukturasi (sequence structure), tanlash strukturasi (selection structure) va
amalni qayta ijro etish strukturasidir (repetition structure).
Ifodalarni ketma-ket ijro etish strukturasi C++ tomonidan ta'minlanadi. Normal
sharoitda C++ ifodalari dasturdagi navbatiga ko'ra bajariladi.
Tanlash buyruqlari uchtadir. Bular if, if/else va switch dir. Qayta ijro etish
buyruqlari gurugiga ham uchta a'zo bor, bular while, do/while va for. Bularni
har birini keyinroq tahlil qilib chiqamiz.
Yuqoridagi buyruqlar nomlari C++ dasturlash tilining mahsus so'zlaridir.
Dasturchi bu so'zlarni o'zgaruvchi yoki funksiyalar nomi sifatida qo'llashi
ta'qiqlanadi. Quyida C++ ning ajratilgan so'zlarining to'liq ro'yhati
berilgan.
C++ va C ga tegishli:
auto do goto signed unsigned
break double if sizeof void
case else int static volatile
char enum long struct while
const extern register switch
continue float return typedef
default for short union
Faqat C++ ga qarashli:
asm explicit operator this virtual
bool false private throw wchar_t
catch friend protected true
class inline public try
const_cast mutable reinterpret_cast typeid
delete namespace static_cast typename
dynamic_cast new template using
C++ dagi yetita boshqaruv strukturasini aytib o'tdik. Ular bittagina
boshlanish nuqtasiga va bittagina chiqish nuqtasiga egadirlar. Demak biz bu
dastur bo'laklarini ketma-ket ulab ketishimiz mumkin. Boshqaruv
strukturalarining bu kabi ulanishini devorning g'ishtlarini ustma-ust
qalashga ham taqqoslasak bo'ladi. Yoki biz bu bloklarni bir-birining ichiga
joylashtirishimiz mumkin. Bu kabi qo'llashish ikkinchi uslub bo'ladi. Mana
shu ikki yo'l bilan bog'langan yetita blok yordamida biz istalgan dasturimizni
yoza olamiz.
if STRUKTURASI
Biz shartga ko'ra bir necha harakat yo'lidan bittasini tanlaymiz. Misol uchun
agar bolaning yoshi 7 ga teng yoki katta bo'lsa u maktabga borishi mumkin
bo'lsin. Buni C++ da if ni qo'llab yozaylik.
if (yosh >= 7)
maktab();
Bu yerda shart bajarilishi yoki bajarilmasligi mumkin. Agar yosh
o'zgaruvchisi 7 ga teng yoki undan katta bo'lsa shart bajariladi va maktab()
funksiyasi chaqiriladi. Bu holat true (to'g'ri) deyiladi. Agar yosh 7 dan
kichik bo'lsa, maktab() tashlab o'tiladi. Yani false (noto'g'ri) holat yuzaga
keladi. Biz shart qismini mantiqiy operatorlarga asoslanganligini ko'rib
chiqqan edik. Aslida esa shartdagi ifodaning ko'rinishi muhim emas - agar
ifodani nolga keltirish mumkin bo'lsa false bo'ladi, noldan farqli javob
bo'lsa, musbatmi, manfiymi, true holat paydo bo'ladi va shart bajariladi.
Bunga qo'shimcha qilib o'tish kerakki, C++ da mahsus bool tipi mavjud. Bu
tipdagi o'zgaruvchilarning yordamida bul (mantiqiy) arifmetikasini amalga
oshirish mumkin. bool o'zgaruvchilar faqat true yoki false qiymatlarini
olishlari mumkin.
if/else STRUKTURASI
if ni qo'llaganimizda ifoda faqat shart haqiqat bo'lgandagina bajariladi, aks
holda tashlanib o'tiladi. if/else yordamida esa shart bajarilmaganda
(false natija chiqqanda) else orqali boshqa bir yo'ldan borishni belgilash
mumkin. Misolimizni takomillashtirsak. Bola 7 yosh yoki undan katta bo'lsa
maktabga, 7 dan kichkina bo'lsa bog'chaga borsin.
if (yosh >= 7)
maktab(); //nuqta-vergul majburiydir
else
bogcha();
Yuqorida if ga tegishli bo'lgan blok bitta ifodadan (maktab()) iborat. Shu
sababli nuqta-vergul qo'yilishi shart. Buni aytib o'tishimizning sababi,
masal Pascalda hech narsa qo'yilmasligi shart.
C++ da bitta ifosa turgan joyga ifodalar guruhini {} qavslarda olingan holda
qo'ysa bo'ladi. Masalan:
if (yosh >= 7){
cout << "Maktabga!\n";
maktab();
}
else{
cout << "Bog'chaga!\n";
bogcha();
}
Aslida har doim {} qavslarni qo'yish yahshi odat hisoblanadi; keyinchalik bir
ifoda turgan joyga qo'shimcha qilinganda qavslardan biri unutilib qolmaydi.
Strukrurali dasturlashning yana bir harakterli joyi shundaki tabulyatsiya,
bo'sh joy va yangi satrlar ko'p qo'llaniladi. Bu programmani o'qishni
osonlashtirish uchun qilinadi. C++ uchun bo'sh joyning hech ahamiyati yo'q,
lekin dasturni tahrir qilayatgan odamga buyruqlar guruhini, bloklarni
tabulyatsiya yordamida ajratib bersak, unga katta yordam bo'ladi. Yuqoridagini
quyidagicha ham yozish mumkin:
if(yosh>=7){cout<<"Maktabga!\n";maktab()}else{cout<<"Bog'chaga!\n";bogcha()};
Biroq buni o'qish ancha murakkab ishdir.
C++ da if/else strukturasiga o'hshash ?: shart operatori (conditional
operator) ham bordir. Bu C++ ning bittagina uchta argument oluvchi operatori.
Uch operand va shart operatori shart ifodasini beradi. Birinchi operand orqali
shartimizni beramiz. Ikkinchi argument shart true (haqiqat) bo'lib chiqqandagi
butun shart ifodasining javob qiymatidir. Uchinchi operand shartimiz
bajarilmay (false) qolgandagi butun shart ifodasining qiymatidir. Masalan:
bool bayroq;
int yosh = 10;
bayroq = ( yosh >= 7 ? true : false );
Agar yosh 7 ga teng yoki katta bo'lsa, bool tipidagi o'zgaruvchimiz true
qiymatini oladi, aks taqdirda false bo'ladi. Shart operatori qavslar ichida
bo'lishi zarur, chunki uning kuchi katta emas. Javob qiymatlar bajariladigan
funksiyalar ham bo'lishi mumkin:
yosh >= 7 ? maktab() : bogcha();
if/else strukturalarini bir-birining ichida yozishimiz mumkin. Bunda ular
bir-biriga ulanib ketadi. Misol uchun tezlikning kattaligiga qarab jarimani
belgilab beruvchi blokni yozaylik.
if (tezlik > 120)
cout << "Jarima 100 so'm";
else if (tezlik > 100)
cout << "Jarima 70 so'm";
else if (tezlik > 85)
cout << "Jarima 30 so'm";
else
cout << "Tezlik normada";
Agar tezlik 120 dan katta bo'lsa birinchi if/else strukturasining haqiqat
sharti bajariladi. Va bu holda albatta tezlik o'zgaruvchimizning qiymati
ikkinchi va uchinchi if/else imizni ham qoniqtiradi. Lekin solishtirish
ulargacha bormaydi, chunki ular birinchi if/else ning else qismida, yani
noto'g'ri javob qismida joylashgandir. Solishtirish birinchi if/else da
tugashi (aynan shu misolda) tanlash amalini tezlashtiradi. Yani bir-biriga
bog'liq if/else lar alohida if strukturalari blokidan tezroq bajarilishi
mumkin, chunki birinchi holda if/else blokidan vaqtliroq chiqish imkoni bor.
Shu sababli ich-ichiga kirgan if/else lar guruhida true bo'lish imkoni
ko'proq bo'lgan shartlarni oldinroq tekshirish kerak.
switch STRUKTURASI
if-else-if yordami bilan bir necha shartni test qilishimiz mumkin. Lekin
bunday yozuv nisbatan o'qishga qiyin va ko'rinishi qo'pol bo'ladi. Agar shart
ifoda butun son tipida bo'lsa yoki bu tipga keltirilishi mumkin bo'lsa, biz
switch (tanlash) ifodalarini ishlata olamiz.
switch strukturasi bir necha case etiketlaridan (label) va majburiy bo'lmagan
default etiketidan iboratdir. Etiket bu bir nomdir. U dasturnig bir
nuqtasidaga qo'yiladi. Programmaning boshqa yeridan ushbu etiketga o'tishni
bajarish mumkin. O'tish yoki sakrash goto bilan amalga oshiriladi, switch
blokida ham qo'llaniladi.
5 lik sistemadagi bahoni so'zlik bahoga o'tqizadigan blokni yozaylik.
int baho;
baho = 4;
switch (baho) {
case 5: cout << "A'lo";
break;
case 4: cout << "Yahshi";
break;
case 3: cout << "Qoniqarli";
break;
case 2:
case 1: cout << "A'lo";
break;
default: cout << "Baho hato kiritildi!";
break;
}
switch ga kirgan o'zgaruvchi (yuqorigi misolda baho) har bir case
etiketlarining qiymatlari bilan solishtirilib chiqiladi. Solishtirish
yuqoridan pastga bajariladi. Shartdagi qiymat etiketdagi qiymat bilan teng
bo'lib chiqqanda ushbu case ga tegishli ifoda yoki ifodalar bloki bajariladi.
So'ng break (buzmoq, tugatmoq) sakrash buyrug'i bilan switch ning tanasidan
chiqiladi. Agar break qo'yilmasa, keyingi etiketlar qiymatlari bilan
solishtirish bajarilmasdan ularga tegishli ifodalar ijro ko'raveradi. Bu
albatta biz istamaydigan narsa. default etiketi majburiy emas. Lekin shart
chegaradan tashqarida bo'lgan qiymatda ega bo'lgan hollarni diagnostika qilish
uchun kerak bo'ladi.
case va etiket orasida bo'sh joy qoldirish shartdir. Chunki, masalan, case 4:
ni case4: deb yozish oddiy etiketni vujudga keltiradi, bunda sharti test
qilinayotgan ifoda 4 bilan solishtirilmay o'tiladi.
while TAKRORLASH STRUKTURASI
Takrorlash strukturasi bir ifoda yoki blokni ma'lum bir shart to'g'ri (true)
bo'lishi davomida qaytarish imkonini beradi. Qaytarilayatgan ifoda shartga
ta'sir ko'rsatishishi kerak. Ma'lum bir vaqt o'tkandan keyin shart false ga
o'zgartilishi kerak. Bo'lmasam while (davomida) tugatilmaydi. while faqat
o'zidan keyin kelgan ifodaga ta'sir qiladi. Agar biz bir guruh amallarni
qaytarmoqchi bo'lsak, ushbu blokni {} qavslar ichiga olishimiz kerak. Shart
takrorlanuvchi blokning boshida tekshirilgani sababli, agar shart noto'g'ri
bo'lib chiqsa, blokni hech ijro ko'rmasligi ham mumkin.
10 ning faktorialini hisoblovchi dastur blokini keltiraylik.
int factorial = 1;
int son = 1;
while (son < 11) {
factorial = factorial * son;
son = son + 1;
}
Bu yerda javobimiz factorial o'zgaruvchimizda saqlanmoqda. son o'zgaruvchimiz
har takrorlanishda birga orttirilmoqda. son 11 ga yetganida while dagi shart
false bo'ladi va takrorlanish tugatiladi. Yani son ning 11 qiymati javobga
ta'sir ko'rsatmaydi. Biz qo'llagan son o'zgaruvchimiz sanovchi (counter)
vazifasini bajaradi. Bu kabi o'zgaruvchilar vazifasiga ko'ra 1 yoki 0 ga
tenglashtiriladi. Buni biz initsializatsiya deymiz. Initsializatsiya
qilinmagan o'zgaruvchilar qiymatlari hotiradagi oldinroq ishlagan programmalar
qoldiqlariga teng bo'ladi. Bu esa hatoga olib keladi. Shu sababli
sanovchilarga boshlangish qiymat berib o'tilishi kerak.
do/while TAKRORLASH STRUKTURASI
do/while ifodasi while strukturasiga o'hshashdir. Bitta farqi shundaki while
da shart boshiga tekshiriladi. do/while da esa takrorlanish tanasi eng kamida
bir marta ijro ko'radi va shart strukturaning so'ngida test qilinadi. Shart
true bo'lsa blok yana takrorlanadi. Shart false bo'lsa do/while ifodasidan
chiqiladi. Agar do/while ichida qaytarilishi kerak bo'lgan ifoda bir dona
bo'lsa {} qavslarning keragi yo'qdir. Quyidagicha bo'ladi:
do
ifoda;
while (shart);
Lekin {} qavslarning yo'qligi dasturchini adashtirishi mumkin. Chunki qavssiz
do/while oddiy while ning boshlanishiga o'hshaydi. Buni oldini olish uchun {}
qavslarni har doim qo'yishni tavsiya etamiz.
int k = 1;
do {
k = k * 5;
} while ( !(k>1000) );
Bu blokda 1000 dan kichik yoki teng bo'lgan eng katta 5 ga karrali son
topilmoqda. while shartini ozroq o'zgartirib berdik, ! (not - inkor)
operatorining ishlashini misolda ko'rsatish uchun. Agar oddiy qilib yozadigan
bo'lsak, while shartining ko'rinishi bunday bo'lardi: while (k<=1000);
Cheksiz takrorlanishni oldini olish uchun shart ifodasining ko'rinishiga katta
e'tibor berish kerak. Bir nuqtaga kelib shart true dan false qiymatiga o'tishi
shart.
QIYMAT BERISH OPERATORLARI
Bu qismda keyingi bo'limlarda kerak bo'ladigan tushunchalarni berib o'tamiz.
C++ da hisoblashni va undan keyin javobni o'zgaruvchiga beruvchi bir necha
operator mavjuddir. Misol uchun:
k = k * 4; ni
k *= 4;
deb yozsak bo'aladi.
Bunda *= operatorining chap argumenti o'ng argumentga qo'shiladi va javob chap
argumentda saqlanadi. Biz har bir operatorni ushbu qisqartirilgan ko'rinishda
yoza olamiz (+=, -=, /=, *= %=). Ikkala qism birga yoziladi. Qisqartirilgan
operatorlar tezroq yoziladi, tezroq kompilyatsiya qilinadi va ba'zi bir
hollarda tezroq ishlaydigan mashina kodi tuziladi.
1 ga OSHIRISH VA KAMAYTIRISH OPERATORLARI (INCREMENT and DECREMENT)
C++ da bir argument oluvchi inkrenet (++) va dekrement (--) operatorlari
mavjuddir. Bular ikki ko'rinishda ishlatilinadi, biri o'zgaruvchidan oldin
(++f - preinkrement, --d - predekrement), boshqasi o'zgaruvchidan keyin
(s++ - postinkrement, s-- - postdekrement) ishlatilgan holi. Bularning
bir-biridan farqini aytin o'taylik. Postinkrementda o'zgaruvchining qiymati
ushbu o'zgaruvchi qatnashgan ifodada ishlatilinadi va undan keyin qiymati birga
oshiriladi. Preinkrementda esa o'zgaruvchining qiymati birga oshiriladi,
va bu yangi qiymat ifodada qo'llaniladi. Predekrement va postdekrement ham
aynan shunday ishlaydi lekin qiymat birga kamaytiriladi. Bu operatorlar
faqatgina o'zgaruvchining qiymatini birga oshirish/kamaytirish uchun ham
ishlatilinishi mumkin, yani boshqa ifoda ichida qo'llanilmasdan. Bu holda pre
va post formalarining farqi yo'q. Masalan:
++r;
r++;
Yuqoridagilarning funksional jihattan hech qanday farqi yo'q, chunki bu ikki
operator faqat r ning qiymatini oshirish uchun qo'llanilmoqda.
Bu operatorlarni oddiy holda yozsak:
r = r + 1;
d = d - 1;
Lekin bizning inkrement/dekrement operatorlarimiz oddiygina qilib
o'zgaruvchiga bir qo'shish/ayirishdan ko'ra tezroq ishlaydi.
Yuqoridagi operatorlarni qo'llagan holda bir dastur yozaylik.
//Postinkremet, preinkrement va qisqartirilgan teglashtirish operatrlari
# include
int main()
{
int k = 5, l = 3, m = 8;
cout << k++ << endl; //ekranga 5 yozildi, k = 6 bo'ldi.
l += 4; // l = 7 bo'ldi.
cout << --m << endl; // m = 7 bo'ldi va ekranga 7 chiqdi.
m = k + (++l); // m = 6 + 8 = 14;
return (0);
}
Dasturdagi o'zgaruvchilar e'lon qilindi va boshqangich qiymatlarni olishdi.
cout << k++ << endl; ifodasida ekranga oldin k ning boshlangich qiymati
chiqarildi, keyin esa uning qiymati 1 da oshirildi. l += 4; da l ning
qiymatiga 4 soni qo'shildi va yangi qiymat l da saqlandi.
cout << --m << endl; ifodasida m ning qiymati oldin predekrement qilindi, va
undan so'ng ekranga chiqarildi. m = k + (++l); da oldin l ning qiymati birga
ishirildi va l ning yangi qiymati k ga qo'shildi. m esa bu yangi qiymatni
oldi. Oshirish va kamaytirish operatorlari va ularning argumentlari orasida
bo'shliq qoldirilmasligi kerak. Bu operatorlar sodda ko'rinishdagi
o'zgaruvchilarga nisbatan qo'llanilishi mumkin halos. Masalan:
++(f * 5);
ko'rinish noto'g'ridir.
MANTIQIY OPERATORLAR
Bosqaruv strukturalarida shart qismi bor dedik. Shu paytgacha ishlatgan
shartlarimiz ancha sodda edi. Agar bir necha shartni tekshirmoqchi
bo'lganimizda ayri-ayri shart qismlarini yozardik. Lekin C++ da bir necha
sodda shartni birlashtirib, bitta murakkab shart ifodasini tuzishga yordam
beradigan mantiqiy operatorlar mavjuddir. Bilar mantiqiy VA - && (AND),
mantiqiy YOKI - || (OR) va mantiqiy INKOR - ! (NOT). Bular bilan misol
keltiraylik.
Faraz qilaylik, bir amalni bajarishdan oldin, ikkala shartimiz (ikkitadan
ko'p ham bo'lishi mumkin) true (haqiqat) bo'lsin.
if (i < 10 && l >= 20){...}
Bu yerda {} qavslardagi ifodalar bloki faqat i 10 dan kichkina va l 20 dan
katta yoki teng bo'lgandagina ijro ko'radi.
AND ning (&&) jadvali:
ifoda1 ifoda2 ifoda1 && ifoda2
false (0) false (0) false (0)
true (1) false (0) false (0)
false (0) true (1) false (0)
true (1) true (1) true (1)
Bu yerda true ni yeriga 1, false ni qiymati o'rniga 0 ni qo'llashimiz mumkin.
Boshqa misol:
while (g<10 || f<4){
...
}
Bizda ikki o'zgaruvchi bor (g va f). Birnchisi 10 dan kichkina yoki ikkinchisi
4 dan kichkina bo'lganda while ning tanasi takrorlanaveradi. Yani shart
bajarilishi uchun eng kamida bitta true bo'lishi kerak, AND da (&&) esa hamma
oddiy shartklar true bo'lishi kerak.
OR ning (||) jadvali:
ifoda1 ifoda2 ifoda1 || ifoda2
false (0) false (0) false (0)
true (1) false (0) true (1)
false (0) true (1) true (1)
true (1) true (1) true (1)
&& va || operatorlari ikkita argument olishadi. Bulardan farqli o'laroq,
! (mantiqiy inkor) operatori bitta argumet oladi, va bu argumentidan oldin
qo'yiladi. Inkor operatori ifodaning mantiqiy qiymatini teskarisiga
o'zgartiradi. Yani false ni true deb beradi, true ni esa false deydi.
Misol uchun:
if ( !(counter == finish) )
cout << student_bahosi << endl;
Agar counter o'zgaruvchimiz finish ga teng bo'lsa, true bo'ladi, bu true
qiymat esa ! yordamida false ga aylanadi. false qiymatni olgan if esa
ifodasini bajarmaydi. Demak ifoda bajarilishi uchun bizga counter finish ga
teng bo'lmagan holati kerak. Bu yerda ! ga tegishli ifoda () qavslar ichida
bo'lishi kerak. Chunki mantiqiy operatorlar tenglilik operatorlaridan
kuchliroqdir. Ko'p hollarda ! operatori o'rniga mos keladigan mantiqiy
tenglilik yoki solishtirish operatorlarini ishlatsa bo'ladi, masalan
yuqoridagi misol quyidagi ko'rinishda bo'ladi:
if (counter != finish)
cout << student_bahosi << endl;
NOT ning jadvali:
ifoda !(ifoda)
false (0) true (1)
true (1) false (0)
for TAKRORLASH STRUKTURASI
for strukturasi sanovchi (counter) bilan bajariladigan takrorlashni bajaradi.
Boshqa takrorlash bloklarida (while, do/while) takrorlash sonini kontrol
qilish uchun ham sanovchini qo'llasa bo'lardi, bu holda takrorlanish sonini
o'ldindan bilsa bo'lardi, ham boshqa bir holatning vujudga kelish-kelmasligi
orqali boshqarish mumkin edi. Ikkinchi holda ehtimol miqdori katta bo'ladi.
Masalan qo'llanuvchi belgilangan sonni kiritmaguncha takrorlashni bajarish
kerak bo'lsa biz while li ifodalarni ishlatamiz. for da esa sanovchi
ifodaning qiymati oshirilib (kamaytirilib) borilvuradi, va chegaraviy qiymatni
olganda takrorlanish tugatiladi. for ifodasidan keyingi bitta ifoda
qaytariladi. Agar bir necha ifoda takrorlanishi kerak bo'lsa, ifodalar bloki
{} qavs ichiga olinadi.
//Ekranda o'zgaruvching qiymatini yozuvchi dastur, for ni ishlatadi.
# include
int main()
{
for (int i = 0; i < 5; i++){
cout << i << endl;
}
return (0);
}
Ekranda:
0
1
2
3
4
for strukturasi uch qismdan iboratdir. Ular nuqta-vergul bilan bir-biridan
ajratiladi. for ning ko'rinishi:
for( 1. qism ; 2. qism ; 3. qism ){
takror etiladigan blok
}
1. qism - e'lon va initsalizatsiya.
2. qism - shartni tekshirish (oz'garuvchini chegaraviy
qiymat bilan solishtirish).
3.qism - o'zgaruvchining qiymatini o'zgartirish.
Qismlarning bajarilish ketma-ketligi quyidagichadir:
Boshida 1. qism bajariladi (faqat bir marta), keyin 2. qismdagi shart
tekshiriladi va agar u true bo'lsa takrorlanish bloki ijro ko'radi, va eng
ohirda 3. qismda o'zgaruvchilar o'zgartiriladi, keyin yana ikkinchi qismga
o'tiladi. for strukturamizni while struktura bilan almashtirib ko'raylik:
for (int i = 0; i < 10 ; i++)
cout << "Hello!"<< endl;
Ekranga 10 marta Hello! so'zi bosib chiqariladi. I o'zgaruvchisi 0 dan 9 gacha
o'zgaradi. i 10 ga teng bo'lganda esa i < 10 sharti noto'g'ri (false) bo'lib
chiqadi va for strukturasi nihoyasiga yetadi. Buni while bilan yozsak:
int i = 0;
while ( i<10 ){
cout << "Hello!" << endl;
i++;
}
Endi for ni tashkil etuvchi uchta qismninig har birini alohida ko'rib chiqsak.
Birinchi qismda asosan takrorlashni boshqaradigan sanovchi (counter)
o'zgaruvchilar e'lon qilinadi va ularga boshlangich qiymatlar beriladi
(initsalizatsiya). Yuqoridagi dastur misolida buni int i = 0; deb berganmiz.
Ushbu qismda bir necha o'zgaruvchilarni e'lon qilishimiz mumkin, ular vergul
bilan ajratilinadi. Ayni shu kabi uchinchi qismda ham bir nechta
o'zgaruvchilarning qiymatini o'zgartirishimiz mumkin. Undan tashqari birinchi
qismda for dan oldin e'lon qilingan o'zgaruvchilarni qo'llasak bo'ladi.
Masalan:
int k = 10;
int l;
for (int m = 2, l = 0 ; k <= 30 ; k++, l++, ++m) {
cout << k + m + l;
}
Albatta bu ancha sun'iy misol, lekin u bizga for ifodasining naqadar
moslashuvchanligi ko'rsatadi. for ning qismlari tushurib qoldirilishi mumkin.
Masalan:
for(;;) {}
ifodasi cheksiz marta qaytariladi. Bu for dan chiqish uchun break operatorini
beramiz. Yoki agar sanovchi sonni takrorlanish bloki ichida o'zgartirsak,
for ning 3. qismi kerak emas. Misol:
for(int g = 0; g < 10; ){
cout << g;
g++;
}
Yana qo'shimcha misollar beraylik.
for (int y = 100; y >= 0; y-=5){
...
ifoda(lar);
...
}
Bu yerda 100 dan 0 gacha 5 lik qadam bilan tushiladi.
for(int d = -30; d<=30; d++){
...
ifoda(lar);
...
}
60 marta qaytariladi.
for strukrurasi bilan dasturlarimizda yanada yaqinroq tanishamiz. Endi
1. qismda e'lon qilinadigan o'zgaruvchilarning hususiyati haqida bir og'iz
aytib o'taylik. Standartga ko'ra bu qismda e'lon qilingan o'zgaruvchilarning
qo'llanilish sohasi faqat o'sha for strukturasi bilan chegaralanadi. Yani
bitta blokda joylashgan for strukturalari mavjud bo'lsa, ular ayni ismli
o'zgaruvchilarni qo'llana ololmaydilar. Masalan quyidagi hatodir:
for(int j = 0; j<20 ; j++){...}
...
for(int j = 1; j<10 ; j++){...} //hato!
j o'zgaruvchisi birinchi for da e'lon qilinib bo'lindi. Ikkinchi for da
ishlatish mumkin emas. Bu masalani yechish uchun ikki hil yo'l tutish mumkin.
Birinchisi bitta blokda berilgan for larning har birida farqli
o'zgaruvchilarni qo'llashdir. Ikkinchi yo'l for lar guruhidan oldin sanovchi
vazifasini bajaruvchi bir o'zgaruvchini e'lon qilishdir. Va for larda bu
o'zgaruvchiga faqat kerakli boshlangich qiymat beriladi halos.
for ning ko'rinishlaridan biri, bo'sh tanali for dir.
for(int i = 0 ; i < 1000 ; i++);
Buning yordamida biz dastur ishlashini sekinlashtirishimiz mumkin.
BOSHQARUV STRUKTURALARIDA continue VA break IFODALARINI QOLLASH
while, do/while, switch va for strukturalarida break operatorini
qo'llaganimizda ushbu dastur bajarilishi ushbu strukturalaridan chiqib ketadi
va navbatdagi kelayatgan ifodadan davom etadi. Bunda boshqaruv
strukturalaridagi breakdan keyin keluvchi ifodalar ijro ko'ra olmay qoladi.
Buni misolda ko'rsataylik.
//break va for ni qo'llash
# include
int main()
{
int h, k = 3;
for(h = 0; h < 10 ; h++){
cout << h << " ";
if (k == 6)
break;
cout << k++ << endl;
}
cout << "for dan tashqarida: " << h << " " << k << endl;
return (0);
}
Ekranda:
0 3
1 4
2 5
3
for dan tashqarida 3 6
if ning sharti bajarilgandan so'ng break dan keyin joylashgan
cout << k++ << endl; ifodasi ijro ko'rmadi. Biz o'zgaruvchilarni for dan
tashqarida ham qollamoqchi bo'lganimiz uchun, ularni for dan oldin e'lon
qildik.
continue ifodasi while, do/while yoki for ichida qo'llanilganda, takrorlanish
tanasida continue dan keyin kelayatgan ifodalar tashlanib o'tilib,
takrorlanishning yangi sikli (iteratisyasi) boshlanadi. Buni programma qismi
misolida ko'rib chiqaylik.
...
for (int e = 1 ; e<=10 ; ++e){
if ( (e%2) == 0 ) //juft son bo'sa siklni o'tqizvor
continue;
cout << e << " ";
}
...
Ekranda:
1 3 5 7 9
Bu yerda bir-ikkita aytib o'tiladigan nuqtalar bor. continue va break ni
ishlatish strukturali dasturlash falsafasiga to'g'ri kelmaydi. Ular dasturni
analiz qilishni murakkablashtirib yuboradi. Bular o'rniga strukturali
dasturlash amallarini qo'llagan holda boshqaruv strukturalarining harakatini
o'zgartirish mumkin. Lekin boshqa tarafdan albatta bu sakrash ifodalari ayni
ishni bajaradigan strukturali dasturlash iboralaridan ko'ra ancha tezroq
ishlaydi.
Boshqaruv strukturalarini qo'llanilgan bir misol keltiraylik. Dastur futbol
o'yinlarining nechtasida durang, nechtasida birinchi va nechtasida ikkinchi
komanda yutganini sanaydi.
// while - switch - cin.get - EOF ga misol
# include
int main()
{
int natija = 0, // O'yin natijasi
durang = 0, // duranglar soni
birinchi = 0, // birinchi komanda yutug'i
ikkinchi = 0; // ikkinchi komanda yutug'i
cout << "Durang - d, birinchi komanda yutug'i - b,
ikkinchi komanda yutug'i - i\n"
<< "Tugatish uchun - EOF." << endl;
while ( ( natija = cin.get() ) != EOF ) {
switch (natija) {
case 'D': // Katta harf uchun
case 'd': // kichkina harf uchun
durang++;
break; //
case 'B':
case 'b':
birinchi++;
break;
case 'I':
case 'i':
ikkinchi++;
break;
case '\n': //yangi satr
case '\t': //tabulaytsiya
case ' ' : //va bo'shliqlarga etibor bermaslik
break;
default: // qolgan hamma harflarga javob:
cout << "Noto'g'ri ahrf kiritildi. Yangittan kiriting..."
break; // eng ohirida chart emas.
}//end switch - switch bloki tugaganligi belgisi
}//end while
cout << "\n\n\nHar bir hol uchun o'yinlar soni:"
<< "\nDurang: " << durang
<< "\nBirinchi komanda yutug'i: " << birinchi
<< "\nIkkinchi komanda yutug'i: " << ikkinchi
<< endl;
return (0);
}
Bu dasturda uch hil holat uchun qo'llanuvchi harflarni kiritadi. while
takrorlash strukturasining shart berilish qismida () qavslarga olingan
( natija = cin.get() ) qiymat berish amali birnchi bo'lib bajariladi.
cin.get() funksiyasi klaviaturadan bitta harfni o'qib oladi va uning
qiymatini int tipidagi natija o'zgaruvchisida saqlaydi. harflar (character)
odatda char tipidagi o'zgaruvchilarda saqlanadi. Lekin C++ da harflar
istalgan integer (butun son) tip ichida saqlanishi mumkin, chunki kompyuter
ichida harflar bir baytlik butun son tiplarida saqlanadi. Qolgan butun son
tiplari esa bir baytdan kattadir. Shu sababli biz harflarni butun son (int)
sifatida yoki harf sifatida ishlatishimiz mumkin.
cout << "L harfi int tipida " << static_cast('L') << " ga teng." << enl;
Ekranda:
L harfi int tipida 76 ga teng.
Demak L harfi komputer ichida 76 qiymatiga egadir. Hozirgi kunda
kompyuterlarning asosiy qismi ASCII kodirovkada ishlaydi. (American Standard
Code for Information Interchange - informatsiya ayrboshlash uchun amerika
standart kodi) ASCII da 256 ta belgining raqami berilgan. Bu kodirovka
8 bit - bir bayt joy oladi. Va ichida asosan lotin alofbosi harflari berilgan.
Milliy alifbolarni ifodalash uchun (arab, hitoy, yahudiy, kiril) uangi
kodirovka - UNICODE ishlatilmoqda. Bunda bitta simvol yki belgi ikkita bayt
orqali beriladi. Ifodalanishi mumkin bo'lgan harflar soni 65536 tadir
(2 ning 16 chi darajasi). UNICODE ning asosiy noqulayligi - uning hajmidir.
U asosan Internetga mo'ljallangan edi. Oldin ASCII bilan berilgan tekst hozir
UNICODE da berilsa, uning hajmi ikki baravar oshib ketadi, yani aloqa
tarmoqlariga ikki marta ko'proq og'irlik tushadi.
Tenglashtirish ifodasining umumiy qitmati chap argumentga berilayatgan qiymat
bilan tengdir. Buning qulaylik tarafi shundaki, biz
d = f = g = 0;
deb yozishimiz mumkin. Bunda oldin g nolga tenglashtiriladi keyin g = 0
ifodasining umumiy qiymati - 0 f va d larga zanjir ko'rinishida uzatilinadi.
Demak, natija = cin.get() ifodasining umumiy qiymati EOF (End Of File - file
ohiri) constantasi qiymati bilan solishtiriladi, va unga teng bo'lsa while
takrorlash strukturasidan chiqiladi. EOF ning qiymati ko'pincha -1 bo'ladi.
Lekin ANSI standarti EOF ni manfiy son sifatida belgilagan, yani uning qiymati
-1 dan farqli bo'lishi mumkin. Shu sababli -1 ga emas, EOF ga tenglikni test
qilish programmaning universalligini, bir sistemadan boshqasiga osonlik bilan
o'tishini taminlaydi. EOF ni kiritish uchun qo'llanuvchi mahsus tugnalar
kombinatsiayasini bosadi. Bu bilan u "boshqa kiritishga ma'lumot yo'q"
deganday bo'ladi. EOF qiymati da aniqlangan. DOS va DEC VAX VMS
sistemalarida EOF ni kiritish uchun tugmalari bir vaqtda bosiladi.
UNIX sistemalarida esa kiritiladi.
Qo'llanuvchi harfni kiritib, ENTER (RETURN) tugmasini bosgandan so'ng,
cin.get() funksiyasi harfni o'qiydi. Bu qiymat EOF ga teng bo'lmasa, while
tanasi bajariladi. natija ning qiymati case etiketlarining qiymatlari bilan
solishtiriladi. Masalan natija 'D' yoki 'd' ga teng bolda durang
o'zgaruvchisining qiymati bittaga oshiriladi. Keyin esa break orqali switch
tanasidan chiqiladi. switch ning bir hususiyati shundaki, ifodalar bloki {}
qavslarga olinishi shart emas. Blokning kirish nuqtasi case etiketi, chiqish
nuqtasi esa break operatoridir.
case '\n':
case '\t':
case ' ' :
break;
Yuqoridagi dastur bloki qo'llanuvchi yanglish kiritgan yangi satr,
tabulyatsiya va bo'shliq belgilarini filtrlash uchun yozilgan.
Eng ohirgi break ning majburiy emasligining sababi shuki, break dan so'ng
boshqa operatorlar yo'q. Demak break qo'yilmagan taqdirda ham hech narsa
bajarilmaydi.
EOF kiritilgandan so'ng while tugaydi, o'zgaruvchilar ekranga bosib
chiqariladi.
3 . FUNKSIYALAR
C++ da dasturlashning asosiy bloklaridan biri funksiyalardir. Funksiyalarning
foydasi shundaki, katta masala bir necha kichik bo'laklarga bo'linib, har
biriga alohida funksiya yozilganda, masala yechish algoritmi ancha
soddalashadi. Bunda dasturchi yozgan funksiyalar C++ ning standart kutubhonasi
va boshqa firmalar yozgan kutubhonalar ichidagi funksiyalar bilan
birlashtiriladi. Bu esa ishni osonlashtiradi. Ko'p holda dasturda takroran
bejariladigan amalni funksiya sifatida yozish va kerakli joyda ushbu
funksiyani chaqirish mumkin. Funksiyani programma tanasida ishlatish uchun u
chaqiriladi, yani uning ismi yoziladi va unga kerakli argumentlar beriladi.
() qavslar ushbu funksiya chaqirig'ini ifodalaydi. Masalan:
foo();
k = square(l);
Demak, agar funksiya argumentlar olsa, ular () qavs ichida yoziladi.
Argumentsiz funksiyadan keyin esa () qavslarning o'zi qo'yiladi.
MA'LUMOTLAR TIPI (DATA TYPES)
Shu paytgacha ma'lumotlar tipi deganda butun son va kasrli son bor deb kegan
edik. Lekin bu bo'limda maylumotlar tipi tushunchasini yahshiroq ko'rib
chiqish kerak bo'ladi. Chunki funksiyalar bilan ishlaganda argument kiritish
va qiymat qaytarishga to'g'ri keladi.
Agar boshidan boshlaydigan bo'lsak, kompyterda hamma turdagi ma'lumotlar
0 va 1 yordamida kodlanadi. Buning sababi shuki, elektr uskunalar uchun ikki
holat tabiyidir, tok oqimi bor yoki yo'q, kondensatorda zaryad bor yoki yo'q
va hakozo. Demak biz bu holatlarni oladigan jihozlarni bir quti deb faraz
qilsak, quti ichida yo narsa bo'ladi, yo narsa bo'lmaydi. Mantiqan buni biz
bir yoki nol deb belgilaymiz. Bu kabi faqat ikki holatga ega bo'lishi mumkin
bo'lgan maylumot birligiga biz BIT deymiz. Bu birlik kichik bo'lgani uchun
kompyuterda bitlar guruhi qo'llaniladi. Bittan keyingi birlik bu BAYT (byte).
Baytni sakkizta bit tashkil etadi. Demak bir bayt yordamida biz 256 ta holatni
kodlashimiz mumkin bo'ladi. 256 soni ikkining sakkizinchi darajasiga tengdir.
Bitimiz ikki holatga ega bo'lgani uchun biz kompyuterni ikkili arifmetikaga
asoslangan deymiz. Ammo agar kerak bo'lsa, boshqa sistemaga asoslangan
mashinalarni ham qo'llash mumkin. Masalan uchli sanoq sistemasiga asoslangan
kompyuterlar bor. Informatika faniga ko'ra esa, hisoblash mashinasi uchun eng
optimal sanoq sistemasi e ga teng bo'lar ekan. Demak amaldagi sistemalar ham
shu songa iloji borisha yaqin bo'lishi kerakdir.
C/C++ da baytga asoslangan tip char dir. char tipi butun son tipida bo'lib,
chegaraviy qiymatlari -128 dan +127 gachadir. Bu tip lotin alifbosi harflarini
va y ana qo'shimcha bir guruh simvollarni kodlashga qulay bo'lgan. Lekin
hozirda milliy alifbelarni kodlash uchun 16 bitlik UNICODE qo'llanilmoqda. U
yordamida 65536 ta simvolni ko'rsatish mumkin. char tipida o'zgaruvchi e'lon
qilish uchun dasturda
char g, h = 3, s;
kabi yozish kerak. O'zgaruvchilar vergul bilan ayriladi. E'lon bilan bir
vaqtning o'zida boshlang'ich qiymat ham berish imkoni bor.
Mashina ichida baytdan tashkil topgan boshqa kattaliklar ham bor. Ikki baytdan
tuzilgan kattalik so'z (word) deyiladi, unda 16 bit bo'ladi. 4 ta bayt guruhi
esa ikkili so'z (double word) bo'ladi. Bu birlik 32 bitli mashimalarda
qo'llaniladi. Hozirda qo'llanilmoqda bo'lgan mashinalar asosan 32 bitlidir,
masalan Pentium I/II/III sistemalari. C++ da butun sonlarning ikki tipi bor.
Biri char - uni ko'rib chiqdik. Ikkinchisi int dir. Mashinalarning
arhitekturasi qanday kattalikda bo'lsa, int tipining ham kattakigi huddi
shunday bo'ladi. 16 bitlik mashinalarda int 16 bit edi. Hozirda esa int ning
uzunligi 32 bitdir. int (integer - butun son) tipi charga o'hshaydi. Farqi
bir baytdan kattaligidadir. 16 bitli int ning sig'imi -32768 dan +32767
gachadir. 32 bitli int esa -2 147 483 648 dan +2 147 483 647 gacha o'rin
egallaydi.
Bu ikki butun son tipidan tashqari C++ da ikki tur vergulli, (nuqtali) yani
haqiqiy son tipi mavjud. Bulardan biri float, hotirada 4 bayt joy egallaydi.
Ikkinchisi esa double, 8 bayt kattalikka ega. Bularning harakteristikalari
quyidagi jadvalda berilgan.
Ushbu tiplar bilan ishlaganda unsigned(ishorasiz, +/- siz), signed (ishorali)
long (uzun) va short (qisqa) sifatlarini qo'llasa bo'ladi. unsigned va signed
ni faqat butun son tiplari bilan qo'llasa bo'ladi. unsigned qo'llanganda
sonning ishorat biti bo'lmaydi, ishorat biti sonning kattaligini bildirish
uchun qo'llaniladi. Masalan char tipida 8 chi, eng katta bir odatda ishorat
bitidir. Biz
unsigned char ch;
desak, ch o'zgaruvchimizga faqat 0 va musbat qiymatlarni berishimiz mumkin.
Lekin oddiy char [-128;127] ichida bo'lsa, unsigned char [0;255] orasidagi
qiymatlarni oladi, chunki biz ishorat biti ham qo'llamoqdamiz. Huddi shunday
unsigned int da (4 baytli) qiymatlar [0;4 294 467 296] orasida yotadi.
signed ni ishlatib esa biz ochiqchasiga butun sonimizning ishorati bo'lishi
kerakligini bildiramiz. Normalda agar signed yoki unsigned qo'yilmasa,
tipimizning ishorasi bo'ladi.
long int bilan qo'llanilganda 16 bitli int 32 ga aylanadi. Bu agar mashina
16 bitli bo'lsa, mashina 32 bitli arhitekturaga ega bo'lsa, int ning kattaligi
4 bayligicha qolaveradi. long double tipi esa 10 bayt joy oladi. short
sifati int bilan qo'llanilganda 32 bit emas, 16 bit joy egallashga boshlaydi.
Tezlikni oshirish maqsadida kam joy egallaydigan ma'lumot tiplarini qo'llash
maqsadga muofiqdir. Agar tipning nomi yozilmagan bo'lsa, o'zgaruvchi int tipiga
ega deb qabul qilinadi.
Ma'lumot Sinonimlar Keng tarqalgan
tiplarining nomlari harakteristikalari
long double 10 bayt, +/-3.4e-4932...+/-3.4e4932
double 8 bayt, +/-1.7e-308...+/-1.7e308
float 4 bayt, +/-3.4e-38...+/-3.4e38
unsigned long int unsigned long
long int long
unsigned int unsigned
int
unsigned short int unsigned short
short int short
unsigned char
short
char
char va int dan tashqari C++ da yana bir necha integral tiplar mavjud. Bulardan
biri bool tipidir. bool tipi faqat ikki farqli qiymat olishi mumkin. Bittasi
true (to'g'ri) ikkinchisi false (noto'g'ri). bool tipi mantiqiy arifmetika
amallarini bajarganda juda qo'l keladi. bool tipi boshqa bir integral tipga
asoslangan bo'lishiga qaramasdan (int yoki char), yuqoridagi ikki qiymatdan
tashqari boshqa qiymat ololmaydi. bool tipi o'zgaruvchilari to'g'ri shaklda
initsalizatsiya qilinmagan taqdirda, ularning qiymati hato ravishda na true va
na false bo'lishi mumkin.
Yana boshqa bir integral tip bu wchar_t dir (wide char type - keng simvol
tipi). U ham ko'pincha boshqa bir butun son tipiga asoslanadi - bir baytdan
kattaroq bo'lishi kerakligi uchun short int qo'llaniladi. wchar_t simvollar
kodlanishida qo'llaniladi. Masalan C++ da UNICODE ni odatda wchar_t bilan
kodlaymiz. Hozirda wchar_t ning kattaligi 16 bit, lekin yuqori kattaligi necha
bit bo'lishi kerakligi standartda belgilanmagan.
Butun sonlarni C++ da bir necha asosda berish mumkin. Hech qanday belgi
qo'yilmasdan yozilgan son o'nlik asosda (decimal) deb qabul qilinadi.
Sakkizli asosdagi (octal) sonni berish uchun sondan oldin 0o yoki 0O
belgilarini qo'yish kerak. O'n oltilik sistemadagi (hexadecimal) sonlar
oldiga 0x yoki 0X lar yoziladi. Sakkizli sistemada qo'llaniladin raqamlar
to'plami 0,1,2,3,4,5,6 va 7 dir. O'n oltilik asosda 0 dan 9 gacha sonlar,
10 - a, 11 - b, 12 - c, 13 - d, 14 - e va 15 uchun f qo'llaniladi. Harflar
katta bo'lishi ham mumkin. Harflarning registorining (katta-kichikligi) farqi
yo'q. Misol beraylik:
char d = 10, j = 0o11; // d 10 ga teng, j 9 ga teng.
int f = 0X10; // f 16 ga teng
Butun son va kasr son tiplaridan tashqari C++ da void (bo'sh, hech narsa) tipi
ham mavjud. Bu tipning oladigan qiymatlari bo'sh to'plamga tengdir. void
tipidagi ma'lumot chala tugallangan hisoblanadi. Boshqa turdagi ma'lumotni void
ga keltirish mumkindir. Bu tip bilan ishlashni dasturlarimizda ko'rib chiqamiz.
MA'LUMOTLAR TIPINI KELTIRISH (DATA CASTING)
Gohida bir turdagi o'zgaruvchining qiymatini boshqa tipdagi o'zgaruvchiga
berish kerak bo'ladi. Bu amal ma'lumot tipini keltirish (data type casting)
deyiladi. Ko'p hollarda bu amal avtomatik ravishda, kompilyator tarafidan
bajariladi. Masalan ushbu parchani ko'raylik:
char c = 33;
int k;
k = c;
Bu yerda k ning sig'imi c nikidan kattaroqdir. Shuning uchun c ning qiymatini
k ga berishda hech qanday muammo paydo bo'lmaydi. Quyidagi misolni ko'raylik:
int i = 5;
float f = 9.77;
float result;
result = f + i;
C++ ning kompilyatori ikki turdagi o'zgaruvchilar bilan ishlay olmaydi. Shu
sababli ifodadagi sig'imi kichik bo'lgan o'zgaruvchilar ifodadagi qatnashgan
eng katta sig'imga o'tqaziladi. Bu ham avtomatik tarzda bajariladi.
i o'zgaruvchimiz qiymati vaqtinchalik float tipidagi o'zgaruvchiga beriladi.
Bu vaqtinchalik o'zgaruvchi esa f ga qo'shiladi. Chiqqan javob result ga
beriladi. Yuqorida ko'rib chiqqanlarimiz kompilyator tarafidan bajariladi.
Bu kabi tip o'zgarishlarini avtomatik konversiya (implicit conversion) deymiz.
Lekin gohida to'g'ri kelmaydigan tiplarni birga qo'llashga to'g'ri keladi.
Masalan float tipiga double tipni o'tqazish, char ga int va hokazo. Bu hollarda
ochiq konversiya (explicit conversion) amalini bajarishimiz kerak. Buni
bajarishning ikki uslubi bor. Birinchisi C da qo'llaniladigan yo'l, ikkinchisi
C++ uslubi.
C da tipni keltirish uchun o'zgaruvchi oldiga kerakli tipni () qavslar ichida
yozamiz.
int k = 100;
char s;
s = (char)k;
Yuqorida k ning qiymatini char tipidagi vaqtinchalik o'zgaruvchiga berildi,
keyin s ga ushbu o'zgaruvchi qiymatini berildi. Bu yerda etibor berilishi kerak
bo'lgan narsa shuki, 100 char ga ham to'g'ri keladi. Agar k ning qiymati char
oladigan qiymattan kattaroq/kichikroq bo'ladigan bo'lsa, bu hato olib keladi.
Shu sababli C dagi tip keltirish nisbatan havfli hisoblanadi. Lekin albatta
bilib qo'llanilsa katta yordam beradi.
C++ da ma'lumotlar tipini keltirish uchun mahsus operatorlar kiritildi.
C uslubidagi keltirish hamma sharoitda qo'llanilar edi. C++ ning keltirish
operatorlari esa faqat o'ziga ajratilgan funksiyalarni bajaradi. Undan tashqari
ular C dagi keltirishlardan ko'ra kuchsizroqdir. Shu sababli hato ehtimoli
kamaytirildi. Yana bir afzallik tarafi shundaki, yangi stildagi keltirish
operatorlari tip tekshirishlarini bajarishadi, agar noto'g'ri keltirish
bajarilsa, bu sintaktik hatoga olib keladi.
Ular quyida berilgan:
static_cast
dynamic_cast
const_cast
reinterpret_cast
static_cast ni ko'rib chiqaylik.
int k = 200;
char h;
h = static_cast(k);
static_cast dan keyin kerakli tip nomi <> qavslar ichida beriladi, va tipi
o'zgarishi kerak bo'lgan o'zgaruvchi () qavslar ichida parametr sifatida
beriladi. Static_cast kompilyatsiya davrida tip keltirishlarida qo'llaniladi.
dynamic_cast esa dastur ishlash davrida tip keltirishlari uchun qo'llaniladi.
const_cast esa o'zgaruvchilardan const (o'zgarmas) va volatile (o'zgaruvchan,
uchuvchan) sifatlarini olib tashlashda qo'llaniladi. Odatda const
o'zgaruvchining qiymatini o'zgartirib bo'lmaydi. Ushbu holda const_cast
qo'llaniladi. reinterpret_cast odatiy bo'lmagan keltirishlarni bajarishda
qo'llaniladi (masalan void* ni int ga). reinterpret_cast o'zgaruvchining
bitlarini boshqa ma'noda qo'llashga imkon beredi. Bu operator bilib
ishlatilinishi kerak. Ushbu operatorlar bilan keyinroq yanada yaqin
tanishamiz.
MATEMATIK KUTUBHONA FUNKSIYALARI
Standart kutubhonaning matematik funksiyalari ko'pgina amallarni bajarishga
imkon beradi. Biz bu kutubhona misolida funksiyalar bilan ishlashni ko'rib
chiqamiz.
Masalan bizning dasturimizda quyidagi satr bor bo'lsin:
double = k;
int m = 123;
k = sin(m);
kompilyator uchbu satrni ko'rganida, standart kutubhonadan sin funksiyasini
chaqiradi. Kirish qiymati sifatida m ni berdik. Javob, yani funksiyadan qaytgan
qiymat k ga berildi. Funksiya agumentlari o'zgarmas sonlar (konstanta),
o'zgaruvchilar, ifodalar va boshqa mos keluvchi qiymat qaytaradigan funksiyalar
bo'lishi mumkin. Masalan:
int g = 49, k = 100;
cout << "4900 ning ildizi -> "<< sqrt( g * k );
Ekranda:
4900 ning ildizi -> 70;
Matematik funksiyalar aksariyat hollarda double tipidagi qiymat qaytarishadi.
Kiruvchi argumentning tipi sifatida esa double ga keltirilishi mumkin bo'lgan
tip beriladi. Bu funksiyalarni ishlatish uchun math.h (yangi ko'rinishda cmath)
e'lon faylini include bilan asosiy dastur tanasiga kiritish kerak.
Quyida matematik funksiyalar kutubhonasining bazi bir a'zolarini beraylik.
x va y o'zgaruvchilari double tipiga ega.
Funksiya Aniqlanishi Misol
ceil(x) x ni x dan katta yoki unga teng b-n ceil(12.6) = 13.0
eng kichik butun songacha yahlitlaydi ceil(-2.4) = -2.0
cos(x) x ning trigonometrik kosinusi (x radianda) cos(0.0) = 1.0
exp(x) e ning x chi darajasi (eskponetsial f-ya) exp(1.0) = 2.71828
exp(2.0) = 7.38906
fabs(x) x ning absolut qiymati x>0 => abs(x) = x
x=0 => abs(x) = 0.0
x<0 => abs(x) = -x
floor(x) x ni x dan kichik bo'lgan eng katta floor(4.8) = 4.0
butun songacha yahlitlaydi floor(-15.9) = -16.0
fmod(x,y) x/y ning qoldig'ini kasr son tipida beradi fmod(7.3,1.7) = 0.5
log(x) x ning natural lagorifmi (e asosiga ko'ra) log(2.718282) = 1.0
log10(x) x ning 10 asosiga ko'ra lagorifmi log10(1000.0) = 3.0
pow(x,y) x ning y chi darajasini beradi pow(3,4) = 81.0
pow(16,0.25) = 2
sin(x) x ning trigonometrik sinusi (x radianda) sin(0.0) = 0.0
sqrt(x) x ning kvadrat ildizi sqrt(625.0) = 25.0
tan(x) x ning trigonometrik tangensi (x radianda) tan(0.0) = 0
FUNKSIYALARNING TUZILISHI
Funksiyalar dasturchi ishini juda yengillashtiradi. Funksiyalar yordamida
programma modullashadi, qismlarga bo'limadi. Bu esa keyinchalik dasturni
rivojlantirishni osonlashtiradi. Dastur yozilish davrida hatolarni topishni
yengillashtiradi. Bir misolda funksiyaning asosiy qismlarini ko'rib chiqaylik.
int foo(int k, int t) {
int result;
result = k * t;
return (result);
}
Yuqoridagi foo funksiyamizning ismi, () qavslar ichidagi parametrlar - int
tipidagi k va t lar kirish argumentlaridir, ular faqat ushbu funksiya ichida
ko'rinadi va qo'llaniladi. Bunday o'zgaruvchilar lokal (local - mahalliy)
deyiladi. result foo() ning ichida e'lon qilinganligi uchun u ham
lokaldir. Demak biz funksiya ichida o'zgaruvchilarni va klaslarni (class)
e'lon qilishimiz mumkin ekan. Lekin funksiya ichida boshqa funksiyani e'lon
qilib bo'lmaydi. foo() funksiyamiz qiymat ham qaytaradi. Qaytish qiymatining
tipi foo() ning e'lonida eng boshida kelgan - int tipiga ega. Biz funksiyadan
qaytarmoqchi bo'lgan qiymatning tipi ham funksiya e'lon qilgan qaytish qiymati
tipiga mos kelishi kerak - ayni o'sha tipda bo'lishi yoki o'sha tipga
keltirilishi mumkin bo'lgan tipga ega bo'lishi shart. Funksiyadan qiymatni
return ifodasi bilan qaytaramiz. Agar funksiya hech narsa qaytarmasa e'londa
void tipini yozamiz. Yani:
void funk(){
int g = 10;
cout << g;
return;
}
Bu funksiya void (bo'sh, hech narsasiz) tipidagi qiymatni qaytaradi. Boshqacha
qilib aytganda qaytargan qiymati bo'sh to'plamdir. Lekin funksiya hech narsa
qaytarmaydi deya olmaymiz. Chunki hech narsa qaytarmaydigan mahsus funksiyalar
ham bor. Ularning qaytish qiymati belgilanadigan joyga hech narsa yozilmaydi.
Biz unday funksiyalarni keyinroq qo'rib chiqamiz. Bu yerda bir nuqta shuki,
agar funksiya mahsus bo'lmasa, lekin oldida qaytish qiymati tipi
ko'rsatilmagan bo'lsa, qaytish qiymati int tipiga ega deb qabul qilinadi.
void qaytish tipli funksiyalardan chiqish uchun return; deb yozsak yetarlidir.
Yoki return ni qoldirib ketsak ham bo'ladi.
Funksiyaning qismlari bajaradan vazifasiga ko'ra turlicha nomlanadi. Yuqorida
korib chiqqanimiz funksiya aniqlanishi (function definition) deyiladi, chunki
biz bunda funksiyaning bajaradigan amallarini funksiya nomidan keyin, {}
qavslar ichida aniqlab yozib chiqyapmiz. Funksiya aniqlanishida {} qavslardan
oldin nuqta-vergul (;) qo'yish hatodir. Bundan tashqari funksiya e'loni,
prototipi yoki deklaratsiyasi (function prototype) tushunchasi qo'llaniladi.
Bunda funksiyaning nomidan keyin hamon nuqta-vergul qo'yiladi, funksiya
tanasi esa berilmaydi. C++ da funksiya qo'llanilishidan oldin uning
aniqlanishi yoki hech bo'lmaganda e'loni kompilyatorga uchragan bo'lishi
kerak. Agar funksiya e'loni boshqa funksiyalar aniqlanishidan tashqarida
berilgan bo'lsa, uning kuchi ushbu fayl ohirigacha boradi. Biror bir funksiya
ichida berilgan bo'lsa kuchi faqat o'cha funksiya ichida tarqaladi. E'lon
fayllarda aynan shu funksiya e'lonlari berilgan bo'ladi. Funksiya e'loni va
funksiya aniqlanishi bir-biriga mos tushishi kerak.
Funksiya e'loniga misol:
double square(char, bool);
float average(int a, int b, int c);
Funksiya e'lonlarda kirish parametrlarining faqat tipi yozish kifoya, huddi
square() funksiyasidek. Yoki kiruvchi parametrlarning nomi ham berilishi
mumkin, bu nomlar kompilyator tarafidan etiborga olinmaydi, biroq dasturning
o'qilishini ancha osonlashtiradi.
Bulardan tashqari C++ da funksiya imzosi (function signature) tushunchasi bor.
Funksiya imzosiga funksiya nomi, kiruvchi parametrlar tipi, soni,
ketma-ketligi kiradi. Funksiyadan qaytuvchi qiymat tipi imzoga kirmaydi.
int foo(); //No1
int foo(char, int); //No2
double foo(); //No3 - No1 funksiya bilan imzolari ayni.
void foo(int, char); //No4 - No2 bilan imzolari farqli.
char foo(char, int); //No5 - No2 bilan imzolari ayni.
int foo(void); //No6 - No1 va No3 bilan imzolari ayni,
// No1 bilan e'lonlari ham ayni.
Yuqoridagi misolda kirish parametrlari bo'lmasa biz () qavsning ichiga void
deb yozishimiz mumkin (No6 ga qarang). Yoki () qavslarning quruq o'zini
yozaversak ham bo'ladi (No1 ga qarang).
Yana bir tushuncha - funksiya chaqirig'idir. Dasturda funksiyani chaqirib,
qo'llashimiz uchun uning chaqiriq ko'rinishini ishlatamiz. () qavslari
funksiya chaqirig'ida qo'llaniladi. Agar funksiyaning kirish argumentlari
bo'lmasa, () qavslar bo'sh holda qo'llaniladi. Aslida () qavslar C++ da
operatorlardir.
Funksiya kirish parametrlarini har birini ayri-ayri yozish kerak, masalan
yuqoridagi
float average(int a, int b, int c);
funksiyasini
float average(int a,b,c); // Hato!
deb yozishimiz hatodir.
Hali etib o'tganimizdek, funksiya kirish parametrlari ushbu funksiyaning
lokal o'zgaruvchilaridir. Bu o'zgaruvchilarni funksiya tanasida boshqattan
e'lon qilish sintaksis hatoga olib keladi. Bir dastur yozaylik.
//Funksiya bilan ishlash
# include
int foo(int a, int b); //Funksiya prototipi,
//argumentlar ismi shart emas.
int main()
{
for (int k = 1; k <6; k++){
for (int l = 5; l>0; l--){
cout << foo(k,l) << " "; //Funksiya chaqirig'i.
}//end for (l...)
cout << endl;
}//end for (k...)
return (0);
} //end main()
//foo() funksiyasining aniqlanishi
int foo(int c, int d)
{ //Funksiya tanasi
return(c * d);
}
Ekranda:
5 4 3 2 1
10 8 6 4 2
15 12 9 6 3
20 16 12 8 4
25 20 15 10 5
Bizda ikki sikl ichida foo() funksiyamiz chaqirilmoqda. Funksiyaga k va l
o'zgaruvchilarining nushalari uzatilmoqda. Nushalarning qiymati mos ravishda
funksiyaning aniqlanishida berilgan c va d o'zgaruvchilarga berilmoqda.
k va l ning nushalari deganimizda adashmadik, chunki ushbu o'zgaruvchilarining
qiymatlari funksiya chaqirig'idan hech qanday ta'sir ko'rmaydi.
C++ dagi funksiyalarning bir noqulay tarafi shundaki, funksiyadan faqat bitta
qiymat qaytadi. Undan tashqari yuqorida ko'rganimizdek, funksiyaga berilgan
o'zgaruvchilarning faqat nushalari bilan ish ko'rilarkan. Ularning qiymatini
normal sharoitda funksiya ichida o'zgartirish mumkin emas. Lekin bu muammolar
ko'rsatkichlar yordamida osonlikcha hal etiladi.
Funksiya chaqiriqlarida avtomatik ma'lumot tipining konversiyasi bajariladi.
Bu amal kompilyator tomonidan bajarilganligi sababli funksiyalarni chaqirganda
ehtiyot bo'lish kerak. Javob hato ham bo'lishi mumkin. Shu sababli kirish
parametrlar tipi sifatida katta hajmli tiplarni qo'llash maqsadga muofiq
bo'ladi. Masalan double tipi har qanday sonli tipdagi qiymatni o'z ichiga
olishi mumkin. Lekin bunday qiladigan bo'lsak, biz tezlikdan yutqazishimiz
turgan gap. Avtomatik konversiyaga misol keltiraylik.
int division(int m, int k){
return (m / k);
}
dasturda chaqirsak:
...
float f = 14.7;
double d = 3.6;
int j = division(f,d); //f 14 bo'lib kiradi, d 3 bo'lib kiradi
// 14/3 - butun sonli bo'lish esa 4 javobini beradi
cout << j;
...
Ekranda:
4
Demak kompilyator f va d o'zgaruvchilarining kasr qismlarini tashlab yuborar
ekan. Qiymatlarni pastroq sig'imli tiplarga o'zgartirish hatoga olib keladi.
E'LON FAYLLARI
Standart kutubhona ichidagi funksiyalarni ishlatish uchun ularning
prototiplari joylashgan e'lon fayllarini include preprosessor buyrug'i bilan
dastur ichiga kirgazish kerak.Quyida biz ba'zi bir keng qo'llaniladigan
e'lon fayllarini keltirib o'tamiz, ularning yangi va bor bo'lsa eski ismlarini
beramiz. Quyida yangi bo'lgan atamalarni keyinchalik tushuntirib o'tamiz.
Dastur ishlashini diagnostika qilish uchun kerakli makrolar va
ma'lumotlarni e'lon qiladi. Yangi ismi .
Simvollarni test qilishda va harflar registorini kattadan kichikka
va teskarisiga o'zgartirishda qo'llaniladigan funksiyalar e'lonlarini o'z
ichiga oladi. Yangi ismi .
Kasrli (haqiqiy) sonlarning sistemaga bog'liq limitlari aniqlangan.
Yangi ismi .
Butun sonlarning sistemaga bog'liq limitlari berilgan. Yangi ismi
.
Matematik funksiyalar kutubhonasini e'lon qiladi. Yangi ismi .
Standart kirish/chiqish funksiyalarining e'lonlari berilgan. Yangi
ismi .
Sonlarni tekstga, tekstni songa aylantiruvchi funksiyalar, hotira
bilan ishlaydigan funksiyalar, tasodifiy sonlar generatsiya qiluvchi
funksiyalari va boshqa yordamchi funksiyalar e'lonlarini o'z ichiga oladi.
Yangi ismi .
C uslubida satrlar bilan ishlovchi funksiyalar e'loni berilgan.
Yangi ismi .
Vaqt va sana bilan ishlaydigan funksiylar e'lonlari berilgan. Yangi
ismi .
Standart kirish/chiqish oqimi bilan ishlovchi funksiyalar e'loni
kiritilgan. Yangi ismi .
Oqim manipulyatorlari berilgan. Yangi ismi .
Diskda joylashgan fayllar bilan kirish/chiqish amallarini
bajaruvchi funksiyalar ellonlari berilgan. Yangi ismi .
Quyidagi e'lon fayllarining faqat bitta ismi bir.
Boshqa kutubhonalar tomonidan qo'llaniladigan yordamchi funksiyalar
va klaslarning e'lonlari kiritilgan.
, , , , , 0>10>20>10>10>
Dostları ilə paylaş: |