03 β Boshqaruv oqimi¶
β¬ οΈ Oldingi: 02 β Dart asoslari: o'zgaruvchi va tiplar Β· π README Β· Keyingi: 04 β Funksiyalar β‘οΈ
Bu bobda: dastur shartga qarab qaror qabul qilishni (
if/else, ternary,switch) va ishni takrorlashni (for,while,do-while) o'rganamiz. Dart 3 ning zamonaviyswitchifodasi bilan ham tanishamiz. Bu bob β Flutter'ga o'tishdan oldingi eng amaliy ko'nikma: deyarli har bir ilova "agar ... bo'lsa ... qil" va "ro'yxatdagi har bir element uchun ..." mantig'iga tayanadi.
Nega boshqaruv oqimi kerak?¶
Hozirgacha yozgan dasturlaringiz bir tekis edi: birinchi qator, ikkinchi qator, uchinchi qator β yuqoridan pastga, hech qaerga burilmasdan. Bu β retsept emas, balki bitta to'g'ri yo'l.
Lekin haqiqiy dastur qaror qabul qiladi va ishni takrorlaydi. O'ylab ko'ring β oddiy oshxona retsepti ham shunday yozilgan:
- "Agar xamir ko'tarilgan bo'lsa, pechga sol; aks holda yana 10 daqiqa kut." β bu shart (conditional).
- "Tuxumni 3 marta ayla." yoki "Idishdagi har bir sabzini archib chiq." β bu sikl (loop, takrorlash).
Boshqaruv oqimi (control flow) β dasturning shu "burilishlari": qaysi qatorlar bajarilishi, qaysilari o'tkazib yuborilishi va qaysilari necha marta takrorlanishi. Aynan shu narsa dasturni jonli qiladi.
Tushuncha: "oqim" deganda dastur bajarilish paytida qatordan qatorga qanday "oqib o'tishini" tushunamiz.
ifva sikllar shu oqimni boshqaradi β shuning uchun "boshqaruv oqimi".
if / else if / else β qaror qabul qilish¶
if β inglizcha "agar" degani. Qavs ichidagi shart true (rost) bo'lsa, jingalak qavs { } ichidagi blok bajariladi:
Bu yerda yosh >= 18 β bir bool (mantiqiy) qiymat: u faqat true yoki false bo'ladi. (Bool tiplari va >=, == kabi taqqoslash operatorlarini 02-bobda ko'rgan edingiz β kerak bo'lsa, 02 β Dart asoslari ga qaytib oling.)
else β "aks holda". Shart false bo'lsa, else bloki ishlaydi:
int yosh = 15;
if (yosh >= 18) {
print('Kattalar');
} else {
print('Bolalar'); // shu chiqadi, chunki 15 >= 18 emas
}
Quyidagi blok-sxema shu mantiqni ko'rsatadi: bitta shart β ikki yo'l, keyin yana bitta yo'lga birlashadi.
else if β bir nechta shartni ketma-ket tekshirish uchun. Dart ularni yuqoridan pastga sinaydi va birinchi rost shartda to'xtaydi, qolganlariga qaramaydi:
int ball = 75;
if (ball >= 90) {
print('A\'lo');
} else if (ball >= 70) {
print('Yaxshi'); // shu chiqadi: 75 >= 90 emas, lekin 75 >= 70
} else if (ball >= 60) {
print('Qoniqarli');
} else {
print('Qoniqarsiz');
}
Tartib muhim! Dart birinchi mos shartda to'xtagani uchun, shartlarni odatda eng qattiqdan eng yumshoqqa (katta sondan kichikka) joylaymiz. Agar
ball >= 60ni birinchi yozsangiz, 95 ball ham "Qoniqarli" chiqib qoladi β chunki 95 ham 60 dan katta va Dart o'sha yerda to'xtaydi.
Shartlarni && (va), || (yoki), ! (emas) bilan birlashtirish mumkin:
int yosh = 25;
bool chiptasiBor = true;
if (yosh >= 18 && chiptasiBor) {
print('Konsertga kirishingiz mumkin');
}
Ternary operator: shart ? a : b¶
Ko'pincha biz "shartga qarab ikkitadan birini tanlab, o'zgaruvchiga saqlaymiz". Buni if/else bilan yozsa, 5 qator bo'ladi. Ternary operator uni bitta qatorga jamlaydi:
int yosh = 20;
// if/else bilan:
String holat;
if (yosh >= 18) {
holat = 'kattalar';
} else {
holat = 'bolalar';
}
// ternary bilan β aynan o'sha mantiq, bitta qatorda:
String holat2 = yosh >= 18 ? 'kattalar' : 'bolalar';
O'qilishi: "shart rostmi? Ha bo'lsa β ? dan keyingi qiymat, yo'q bo'lsa β : dan keyingi qiymat." ? ni "ha bo'lsa", : ni "aks holda" deb o'qing.
Qachon ternary, qachon
if? Ternary faqat bitta qiymat tanlash uchun yaxshi. Agar shoxlarda bir nechta amal bajarilsa yoki mantiq murakkablashsa β oddiyif/elseo'qilishliroq. Ternary'ni ichma-ich (a ? b : c ? d : e) yozishdan saqlaning β buni o'qib bo'lmaydi.
Kichik teaser: ?? ("null bo'lsa")¶
Dart'da yana bir foydali qisqartma bor β ?? operatori. U "chap tomon null bo'lsa, o'ng tomonni ol" degani:
String? ism; // hozircha null (02-bobdan: ? β null bo'lishi mumkin)
String korsatiladigan = ism ?? 'Mehmon'; // ism null -> 'Mehmon'
print(korsatiladigan); // Mehmon
Buni hozircha "standart qiymat berish" deb tushuning. Null xavfsizligini β ?, !, ??, ?. ni β to'liq, alohida bobda chuqur o'rganamiz; hozir shunchaki ko'rib qo'ying.
Ichma-ich if va uni yassilashtirish¶
if ichida yana if yozish mumkin (nesting), lekin chuqurlashgani sari kodni o'qish qiyinlashadi:
Ko'pincha shartlarni && bilan birlashtirib yassilashtirish (flatten) mumkin:
Maslahat: kod chap tomondan "zinapoyadek" ichkariga ketaversa, bu odatda yassilashtirish mumkinligining belgisi. Tekis kod β o'qishli kod.
switch β bitta qiymatni ko'p variant bilan solishtirish¶
Ba'zan bitta o'zgaruvchini ko'p mumkin bo'lgan qiymat bilan solishtiramiz. Buni uzun else if zanjiri bilan yozish mumkin, lekin switch toza va aniqroq.
Klassik switch (statement)¶
int kun = 3;
switch (kun) {
case 1:
print('Dushanba');
break;
case 2:
print('Seshanba');
break;
case 3:
print('Chorshanba'); // shu chiqadi
break;
default:
print('Boshqa kun'); // hech bir case mos kelmasa
}
Bu yerda bir nechta muhim nuqta bor:
caseβ har bir mumkin bo'lgan qiymat.kunqaysicasega teng bo'lsa, o'sha blok bajariladi.defaultβ hech bircasemos kelmaganda ishlaydigan "qolgan hammasi" shoxi (if/elsedagielsekabi).breakβ shucasetugadi,switchdan chiq, degani.
Dart "fall-through" qilmaydi! Ba'zi tillarda (C, Java)
breakyozishni unutsangiz, dastur keyingicasega "tushib ketadi". Dart bunday qilmaydi: u bo'sh bo'lmagancaseoxiridabreak(yokireturn/continue) bo'lishini talab qiladi, aks holda kompilyator xato beradi. Shunga qaramay,breakni yozib qo'yish niyatingizni aniq ko'rsatadi β odat qiling.
Bir nechta qiymatni bitta shoxga birlashtirish uchun case larni ketma-ket yozing (oraliqni bo'sh qoldiring):
switch (kun) {
case 6:
case 7:
print('Dam olish kuni'); // 6 yoki 7 -> shu yerga keladi
break;
default:
print('Ish kuni');
}
Zamonaviy switch ifodasi (expression) β Dart 3¶
Yuqoridagi switch bir narsa qiladi (statement). Lekin ko'pincha bizga qiymat qaytaradigan switch kerak β masalan, kun raqamiga qarab nom tanlab, uni o'zgaruvchiga saqlash. Dart 3 da buning uchun nafis switch ifodasi (switch expression) bor:
int kun = 3;
final nom = switch (kun) {
1 => 'Dushanba',
2 => 'Seshanba',
3 => 'Chorshanba',
_ => 'Boshqa kun',
};
print(nom); // Chorshanba
Klassik switch dan farqini sezing:
caseso'zi yo'q,breakyo'q,:o'rniga=>(o'q) ishlatiladi.- Har bir "arm" (
o'q) bitta qiymat qaytaradi, va butunswitchshu qiymatni beradi β uni to'g'ridan-to'g'rifinal nom = ...ga saqladik. _(pastki chiziq) β "wildcard", ya'ni "qolgan hamma qiymat". Udefaulto'rnini bosadi.- Oxirgi
}dan keyin;qo'yiladi, chunki bu β butun bir ifoda (qiymat beradigan amal),ifbloki emas.
Quyidagi sxema buni ko'rsatadi: kirish qiymatlari => orqali chiqish qiymatlariga moslanadi, _ esa qolganini ushlaydi va butun ifoda bitta qiymat qaytaradi.
Bu ayniqsa Flutter'da juda ko'p ishlatiladi β masalan, holatga qarab matn yoki rang tanlashda. Shuning uchun uni hozirdan o'rganib qo'yish foydali.
Qisqacha when (guard) haqida. switch ifodasida bir arm'ga qo'shimcha shart qo'yish mumkin β when bilan:
int ball = 85;
final baho = switch (ball) {
>= 90 => 'A\'lo',
>= 70 => 'Yaxshi', // 85 shu yerga tushadi
_ when ball >= 60 => 'Qoniqarli',
_ => 'Qoniqarsiz',
};
Eslatma:
switchning to'liq kuchi β pattern matching (qoliplarni moslash),>= 90kabi sonli qoliplar, records'ni qismlarga ajratish, exhaustive (barcha variant qamrab olingani kafolatlangan)switchβ bularning hammasini keyinroq, 08 β Dart 3 zamonaviy imkoniyatlari bobida chuqur o'rganamiz. Hozircha shuni biling:switchifodasi qiymat qaytaradi va_qolganini ushlaydi β shu yetarli.
Sikllar β ishni takrorlash¶
Sikl (loop) β bir blokni ko'p marta bajarish usuli. "Ekranga 1 dan 100 gacha sonlarni chiqar" deb 100 ta print yozmaysiz β bitta sikl yozasiz.
for sikli (C-uslubidagi)¶
Eng ko'p ishlatiladigan sikl. U uch qismdan iborat:
Qavs ichidagi uch qism (; bilan ajratilgan):
- init (
var i = 0) β sanagich (counter) e'lon qilinadi. Faqat bir marta, sikl boshida bajariladi. - shart (
i < 3) β har aylanish oldidan tekshiriladi.truebo'lsa β tana bajariladi;falsebo'lsa β sikl tugaydi. - yangilash (
i++) β har aylanish oxirida bajariladi.i++β "ini 1 ga oshir" degani.
Quyidagi sxema shu aylanani va har bir qadamdagi i qiymatini ko'rsatadi:
Nega
i < 3bo'lsa 3 marta (0, 1, 2) takrorlanadi? Chunki dasturchilar 0 dan sanashni boshlaydi.iqiymatlari: 0, 1, 2 β uchta.i3 ga yetganda3 < 3yolg'on bo'ladi va sikl to'xtaydi. Bu β yangi boshlovchilar uchun eng tez-tez uchraydigan chalkashlik, pastda "off-by-one" xatosini alohida ko'ramiz.
for-in β ro'yxat bo'ylab yurish¶
Agar sizda bir ro'yxat (List) bo'lsa va uning har bir elementini ko'rib chiqmoqchi bo'lsangiz, indeks bilan ovora bo'lmang β for-in to'g'ridan-to'g'ri elementlarni beradi:
List<String> mevalar = ['olma', 'banan', 'uzum'];
for (final meva in mevalar) {
print('Men $meva yaxshi ko\'raman');
}
// Men olma yaxshi ko'raman
// Men banan yaxshi ko'raman
// Men uzum yaxshi ko'raman
for-inβ "ro'yxatdagi har bir element uchun ..." mantig'i. Indeks kerak bo'lmasa, doim shuni tanlang: u soddaroq va xatoga kamroq joy qoldiradi. (Listni 05-bobda batafsil o'rganamiz.)
while β shart bajarilguncha takrorlash¶
while β shart true bo'lib turguncha takrorlaydi. Tanani bajarishdan oldin shartni tekshiradi:
int son = 1;
while (son <= 5) {
print(son);
son++; // MUHIM: shartni o'zgartiramiz, aks holda sikl tugamaydi!
}
// 1 2 3 4 5
for qancha marta takrorlashni oldindan bilganda qulay. while esa "qachongacha"ni bilmaganda β masalan, foydalanuvchi to'g'ri parol kiritguncha yoki o'yin tugaguncha.
do-while β kamida bir marta bajarish¶
do-while while ga o'xshaydi, lekin shartni oxirida tekshiradi. Demak, tana kamida bir marta bajariladi β hatto shart birinchidanoq yolg'on bo'lsa ham:
int son = 10;
do {
print('Bu bir marta baribir chiqadi: $son');
} while (son < 5); // shart yolg'on, lekin tana allaqachon bir marta bajarildi
Buni "avval qil, keyin so'ra" deb eslang. Kamdan-kam kerak bo'ladi (masalan, menyuni kamida bir marta ko'rsatib, keyin "yana?" deb so'rash), lekin bor ekanini biling.
break va continue¶
Sikl ichida oqimni nozik boshqarish:
breakβ siklni butunlay to'xtatadi va undan chiqadi.continueβ joriy aylanishni o'tkazib yuboradi va keyingisiga o'tadi.
// break β qidirilgan narsa topilganda to'xtash
for (var i = 1; i <= 10; i++) {
if (i == 5) {
break; // 5 ga yetganda butunlay chiqadi
}
print(i); // 1 2 3 4
}
// continue β ba'zi elementlarni o'tkazib yuborish
for (var i = 1; i <= 5; i++) {
if (i == 3) {
continue; // 3 ni o'tkazib, keyingisiga o'tadi
}
print(i); // 1 2 4 5 (3 yo'q)
}
Amaliy qoliplar¶
Quyidagilar β kundalik dasturlashda qayta-qayta uchraydigan kichik "retseptlar". Ularni tushunsangiz, ko'plab masalalarni yecha olasiz.
1. Sonlar yig'indisi. Bir o'zgaruvchini boshlab, har aylanishda ustiga qo'shib boramiz (bu β "akkumulyator" qolipi):
int yigindi = 0;
for (var i = 1; i <= 100; i++) {
yigindi += i; // yigindi = yigindi + i
}
print(yigindi); // 5050 (1 dan 100 gacha yig'indi)
2. FizzBuzz β klassik mashq. 1 dan 15 gacha sonlarni chiqaramiz: 3 ga bo'linsa "Fizz", 5 ga "Buzz", ikkalasiga ham "FizzBuzz". % (qoldiq) operatori β bo'linish qoldig'ini beradi (i % 3 == 0 degani "i qoldiqsiz 3 ga bo'linadi"):
for (var i = 1; i <= 15; i++) {
if (i % 3 == 0 && i % 5 == 0) {
print('FizzBuzz');
} else if (i % 3 == 0) {
print('Fizz');
} else if (i % 5 == 0) {
print('Buzz');
} else {
print(i);
}
}
3. Ro'yxatdagi eng kattasini topish. "Hozirgi eng katta"ni saqlab, har elementni u bilan solishtiramiz:
List<int> sonlar = [12, 47, 5, 89, 33];
int engKatta = sonlar[0]; // birinchisini boshlang'ich deb olamiz
for (final son in sonlar) {
if (son > engKatta) {
engKatta = son; // kattaroq topilsa, yangilaymiz
}
}
print(engKatta); // 89
4. Sikl ichida matn yig'ish. Har aylanishda string'ga qo'shib, natija qatorini quramiz:
String natija = '';
for (var i = 1; i <= 5; i++) {
natija += '$i '; // string interpolation (02-bobdan)
}
print(natija.trim()); // 1 2 3 4 5
Yangi boshlovchilarning tez-tez uchraydigan xatolari¶
1. = va == ni chalkashtirish. = β qiymat berish (assignment), == β tenglikni tekshirish (taqqoslash). Shartda doim == kerak:
int x = 5;
if (x == 5) { // TO'G'RI: tekshirish
print('besh');
}
// if (x = 5) // XATO: bu qiymat berish β Dart kompilyatori buni rad etadi
Yaxshiyamki, Dart sizni himoya qiladi: shartga
intqiymat berishga urinsangiz, kompilyator xato beradi (shartboolbo'lishi shart). Lekin odat sifatida har doim==yozayotganingizni tekshiring.
2. "Off-by-one" β bir qadam adashish. Bu eng mashhur xato. i <= n va i < n ni, 0 dan yoki 1 dan boshlashni adashtirib yuborish oson:
// 5 ta element chiqarmoqchimiz (0..4):
for (var i = 0; i < 5; i++) { } // TO'G'RI: 5 marta (0,1,2,3,4)
for (var i = 0; i <= 5; i++) { } // XATO: 6 marta (0,1,2,3,4,5)
Ro'yxat indekslari 0 dan boshlanadi va oxirgi indeks
uzunlik - 1.i < ro'yxat.lengthyozsangiz, doim xavfsiz bo'lasiz.
3. break ni unutish (niyat aniqligi). Dart "fall-through" qilmagani uchun klassik switch da break ni unutish kompilyatsiya xatosini beradi β bu yaxshi, sizni xatodan saqlaydi. Lekin break ni doim yozish niyatingizni aniq ko'rsatadi. Qiymat qaytarish kerak bo'lsa β break bilan ovora bo'lmasdan switch ifodasini ishlating.
4. Cheksiz sikl. Agar siklning sharti hech qachon false bo'lmasa, dastur to'xtamay qoladi (va ko'pincha "muzlab" qoladi):
// XAVFLI β cheksiz sikl!
var son = 1;
while (son <= 5) {
print(son);
// son++ ni unutdik -> son doim 1 -> shart doim true -> tugamaydi
}
Har
while/forda o'zingizdan so'rang: "shart qachon yolg'on bo'ladi?" Agar javob "hech qachon" bo'lsa β sikl cheksiz. Sanagichni oshirayotganingizni yoki shartga yetayotganingizni tekshiring.
Mashqlar¶
Quyidagi mashqlarni avval o'zingiz yeching, keyingina yechimga qarang. Har birini alohida faylda yozib, dart run bilan ishga tushiring.
- Bir
int yosho'zgaruvchisi bering.if/elsebilan: 18 dan katta yoki teng bo'lsa "kattalar", aks holda "bolalar" chiqaring. Keyin xuddi shu mantiqni ternary operator bilan bitta qatorda qayta yozing. - Bir
int ball(0β100) bering.else ifzanjiri bilan baho chiqaring:>=90β "A'lo",>=70β "Yaxshi",>=60β "Qoniqarli", aks holda "Qoniqarsiz". - 2-mashqdagi mantiqni Dart 3 ning
switchifodasi bilan qayta yozing (>= 90 => ...qoliplari va_bilan). Natijanifinal bahoga saqlab,printqiling. forsikli bilan 1 dan 50 gacha bo'lgan juft sonlarni chiqaring. (Maslahat:i % 2 == 0β juftlik tekshiruvi.)- Bir
List<int> sonlarbering.for-inbilan ularning yig'indisini va eng kichigini toping va chiqaring. whilesikli bilan 10 dan 1 gacha teskari sanab chiqing, oxirida "Uchirildi!" deb yozing.
1-mashq yechimi
2-mashq yechimi
void main() {
int ball = 75;
if (ball >= 90) {
print('A\'lo');
} else if (ball >= 70) {
print('Yaxshi'); // 75 shu yerga tushadi
} else if (ball >= 60) {
print('Qoniqarli');
} else {
print('Qoniqarsiz');
}
}
Shartlar kattadan kichikka tartibda β birinchi mos shartda to'xtaydi.
3-mashq yechimi
void main() {
int ball = 75;
final baho = switch (ball) {
>= 90 => 'A\'lo',
>= 70 => 'Yaxshi', // 75 shu armga tushadi
>= 60 => 'Qoniqarli',
_ => 'Qoniqarsiz',
};
print(baho); // Yaxshi
}
switchifodasi qiymat qaytaradi β uni to'g'ridan-to'g'rifinal bahoga saqladik._qolgan hamma qiymatni ushlaydi.
4-mashq yechimi
5-mashq yechimi
void main() {
List<int> sonlar = [12, 47, 5, 89, 33];
int yigindi = 0;
int engKichik = sonlar[0]; // birinchisini boshlang'ich deb olamiz
for (final son in sonlar) {
yigindi += son;
if (son < engKichik) {
engKichik = son;
}
}
print('Yig\'indi: $yigindi'); // Yig'indi: 186
print('Eng kichik: $engKichik'); // Eng kichik: 5
}
6-mashq yechimi
void main() {
int son = 10;
while (son >= 1) {
print(son);
son--; // MUHIM: kamaytiramiz, aks holda cheksiz sikl
}
print('Uchirildi!');
}
son--β "sonni 1 ga kamaytir". Bu bo'lmasa, shart hech qachon yolg'on bo'lmaydi.
β¬ οΈ Oldingi: 02 β Dart asoslari: o'zgaruvchi va tiplar Β· π README Β· Keyingi: 04 β Funksiyalar β‘οΈ