5-bo‘lim
Kiritish va chiqarish
printf format belgilari, kenglik va aniqlik, scanf bilan ma'lumot o'qish va uning xavfli tomonlari, fgets bilan xavfsiz kiritish.
Ushbu bo‘lim mundarijasi
Dastur foydalanuvchi bilan matn orqali gaplashadi. C da buning uchun
stdio.h kutubxonasi ishlatiladi.
printf format belgilari #
| Belgi | Tur | Misol |
|---|---|---|
%d | butun son | printf("%d", 25) |
%u | ishorasiz butun | printf("%u", 25u) |
%lld | long long | printf("%lld", 9000000000LL) |
%f | haqiqiy son | printf("%f", 3.14) |
%.2f | 2 xona bilan | 3.14 |
%e | ilmiy shakl | 3.140000e+00 |
%c | bitta belgi | printf("%c", 'A') |
%s | satr | printf("%s", "salom") |
%p | manzil | printf("%p", &yosh) |
%x | o'n oltilik | printf("%x", 255) → ff |
%o | sakkizlik | printf("%o", 8) → 10 |
%zu | sizeof natijasi | printf("%zu", sizeof(int)) |
%% | foiz belgisi | printf("%%") → % |
#include <stdio.h>
int main(void) {
int yosh = 25;
double baho = 4.6789;
char harf = 'H';
char ism[] = "Husanboy";
printf("Butun son : %d\n", yosh);
printf("Haqiqiy : %f\n", baho);
printf("Ikki xona : %.2f\n", baho);
printf("Belgi : %c\n", harf);
printf("Satr : %s\n", ism);
printf("Foiz : %d%%\n", 85);
printf("O'n oltilik: %x\n", 255);
return 0;
}
Butun son : 25
Haqiqiy : 4.678900
Ikki xona : 4.68
Belgi : H
Satr : Husanboy
Foiz : 85%
O'n oltilik: ff
%f standart holatda 6 xona chiqaradiprintf("%f", 4.6789) → 4.678900. Odatda bu keraksiz. Deyarli har doim
%.2f yoki %.1f yozing.
Kenglik bilan jadval chiqarish #
#include <stdio.h>
int main(void) {
printf("%-12s %6s %8s\n", "Talaba", "Yosh", "Baho");
printf("---------------------------------\n");
printf("%-12s %6d %8.2f\n", "Husanboy", 25, 4.60);
printf("%-12s %6d %8.2f\n", "Malika", 21, 4.90);
printf("%-12s %6d %8.2f\n", "Nodira", 24, 4.30);
return 0;
}
Talaba Yosh Baho
---------------------------------
Husanboy 25 4.60
Malika 21 4.90
Nodira 24 4.30
| Yozuv | Ma'nosi |
|---|---|
%8d | o'ngga tekislab, 8 belgi joy |
%-8d | chapga tekislab, 8 belgi joy |
%08d | oldiga nol qo'yib: 00000025 |
%+d | musbat songa ham ishora: +25 |
%8.2f | 8 belgi joy, 2 xona kasr |
Kenglikni yulduzcha orqali dinamik berish ham mumkin:
int kenglik = 10;
printf("%*d\n", kenglik, 42);
Maxsus belgilar #
| Yozuv | Nima qiladi |
|---|---|
\n | Yangi qator |
\t | Tabulyatsiya |
\ | Teskari chiziq |
\" | Qo'shtirnoq |
\' | Bitta tirnoq |
\0 | Satr oxiri belgisi |
#include <stdio.h>
int main(void) {
printf("Ustun1\tUstun2\tUstun3\n");
printf("A\tB\tC\n");
printf("Yo'l: C:\\Users\\Husanboy\n");
printf("U \"salom\" dedi.\n");
return 0;
}
Ustun1 Ustun2 Ustun3
A B C
Yo'l: C:\Users\Husanboy
U "salom" dedi.
scanf - klaviaturadan o'qish #
#include <stdio.h>
int main(void) {
int yosh;
printf("Yoshingizni kiriting: ");
scanf("%d", &yosh);
printf("Siz %d yoshdasiz.\n", yosh);
printf("Kelasi yili %d yoshga to'lasiz.\n", yosh + 1);
return 0;
}
Yoshingizni kiriting: 25
Siz 25 yoshdasiz.
Kelasi yili 26 yoshga to'lasiz.
& belgisini unutmangscanf("%d", yosh); /* XATO: & yo'q */
scanf("%d", &yosh); /* to'g'ri */
scanf o'zgaruvchining manzilini talab qiladi - u qiymatni o'sha
manzilga yozadi. & ampersand «manzilini ol» degani.
& ni unutish - eng ko'p uchraydigan C xatosi. Dastur odatda darhol
qulaydi (segmentation fault).
Istisno: satr o'qiganda & kerak emas, chunki massiv nomi allaqachon
manzil. 12-bo'limda buning sababini tushunasiz.
scanf ning muammolari #
#include <stdio.h>
int main(void) {
int yosh;
int natija = scanf("%d", &yosh);
if (natija != 1) {
printf("Xato: son kiritilmadi.\n");
return 1;
}
printf("Yosh: %d\n", yosh);
return 0;
}
scanf natijasini tekshiringscanf muvaffaqiyatli o'qilgan qiymatlar sonini qaytaradi.
Foydalanuvchi son o'rniga abc yozsa, scanf 0 qaytaradi va o'zgaruvchi
o'zgarmaydi - unda eski axlat qoladi.
Doim natijani tekshiring.
scanf("%s", ...) - xavflichar ism[10];
scanf("%s", ism); /* XAVFLI */
Foydalanuvchi 50 ta belgi yozsa, scanf ularni 10 baytlik massivga
tiqishga urinadi va qo'shni xotirani buzadi. Bu bufer to'lib ketishi
(buffer overflow) deb ataladi va u eng mashhur xavfsizlik zaifligi.
Kengligini cheklang:
char ism[10];
scanf("%9s", ism); /* eng ko'pi 9 belgi + '\0' */
Yoki undan ham yaxshisi - fgets ishlating.
fgets - xavfsiz kiritish #
#include <stdio.h>
#include <string.h>
int main(void) {
char ism[50];
printf("Ismingizni kiriting: ");
if (fgets(ism, sizeof(ism), stdin) != NULL) {
ism[strcspn(ism, "\n")] = '\0'; /* qator oxiri belgisini olib tashlaymiz */
printf("Salom, %s!\n", ism);
}
return 0;
}
Ismingizni kiriting: Husanboy Qodirov
Salom, Husanboy Qodirov!
fgets afzal?scanf("%s") | fgets | |
|---|---|---|
| Hajm chegarasi | Yo'q - xavfli | Bor - xavfsiz |
| Probelli matn | O'qimaydi | O'qiydi |
| Qator oxiri | Qoldiradi | Massivga qo'shadi |
fgets massivga '\n' ni ham yozadi. strcspn(ism, "\n") uning
o'rnini topadi va biz u yerga '\0' qo'yib satrni kesamiz.
scanf va fgets ni aralashtirish #
#include <stdio.h>
int main(void) {
int yosh;
char ism[50];
printf("Yosh: ");
scanf("%d", &yosh);
/* scanf bufer ichida '\n' ni qoldiradi - uni tozalaymiz */
int belgi;
while ((belgi = getchar()) != '\n' && belgi != EOF) { }
printf("Ism: ");
fgets(ism, sizeof(ism), stdin);
printf("%d yoshli %s", yosh, ism);
return 0;
}
scanf("%d", &yosh) faqat sonni o'qiydi. Siz Enter bosganingizdagi
'\n' buferda qoladi.
Keyingi fgets o'sha '\n' ni ko'radi va darhol «bo'sh qator o'qidim»
deb qaytadi - foydalanuvchi hech narsa yoza olmaydi.
Yechim - yuqoridagi while sikli bilan buferni tozalash.
Eng oson yo'l esa: hamma narsani fgets bilan o'qib, so'ng sscanf
yoki atoi bilan songa aylantirish.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char qator[100];
int yosh;
printf("Yosh: ");
if (fgets(qator, sizeof(qator), stdin) != NULL) {
yosh = atoi(qator);
printf("Kelasi yili: %d\n", yosh + 1);
}
return 0;
}
Chiqishni bufersiz qilish #
#include <stdio.h>
int main(void) {
printf("Yuklanmoqda");
fflush(stdout); /* darhol ekranga chiqaradi */
/* uzoq davom etadigan ish... */
printf(" - tayyor!\n");
return 0;
}
Yuklanmoqda - tayyor!
fflush kerak?printf matnni darhol ekranga chiqarmaydi - u buferga to'playdi va
\n uchraganda yoki bufer to'lganda yuboradi.
Shuning uchun \n siz yozilgan matn ba'zan kech ko'rinadi. fflush(stdout)
uni majburan chiqaradi.
To'liq misol - hisob-kitob #
#include <stdio.h>
int main(void) {
const double QQS = 0.12;
double narx = 250000.0;
int miqdor = 3;
double oraliq = narx * miqdor;
double soliq = oraliq * QQS;
double jami = oraliq + soliq;
printf("+----------------------+------------+\n");
printf("| %-20s | %10s |\n", "Tavsif", "Summa");
printf("+----------------------+------------+\n");
printf("| %-20s | %10.2f |\n", "Narx (donasi)", narx);
printf("| %-20s | %10d |\n", "Miqdor", miqdor);
printf("| %-20s | %10.2f |\n", "Oraliq summa", oraliq);
printf("| %-20s | %10.2f |\n", "QQS (12%)", soliq);
printf("+----------------------+------------+\n");
printf("| %-20s | %10.2f |\n", "JAMI", jami);
printf("+----------------------+------------+\n");
return 0;
}
+----------------------+------------+
| Tavsif | Summa |
+----------------------+------------+
| Narx (donasi) | 250000.00 |
| Miqdor | 3 |
| Oraliq summa | 750000.00 |
| QQS (12%) | 90000.00 |
+----------------------+------------+
| JAMI | 840000.00 |
+----------------------+------------+
- Har bir format belgisini (
%d,%f,%c,%s,%x) sinab ko'ring. %.0f,%.1f,%.5fnatijalarini solishtiring.- Uch ustunli jadval chiqaring - kenglik bilan tekislang.
- Foydalanuvchidan ikkita son so'rab, ularning yig'indisini chiqaring.
scanfda&ni ataylab unutib, nima bo'lishini ko'ring.scanfnatijasini tekshiruvchi kod yozing va harf kiritib sinang.fgetsbilan to'liq ism (probel bilan) o'qing.scanfdan keyinfgetsishlatib, muammoni o'z ko'zingiz bilan ko'ring.- So'ng bufer tozalash bilan uni tuzating.
- Yuqoridagi hisob-kitob jadvalini foydalanuvchi kiritgan raqamlar bilan chiqaring.
Xulosa #
printfformat belgilari:%dbutun,%fhaqiqiy,%cbelgi,%ssatr,%zuhajm.%.2f- kasr xonasi soni,%-10s- chapga tekislangan kenglik.%%- foiz belgisini chiqarish uchun.scanfmanzilni talab qiladi -&ni unutmang.scanfnatijasini tekshiring - u o'qilgan qiymatlar sonini qaytaradi.scanf("%s", ...)xavfli - kenglikni cheklang yokifgetsishlating.fgetsxavfsiz va probelli matnni o'qiydi, lekin'\n'ni qoldiradi.scanfdan keyinfgetsishlatsangiz, buferni tozalang.fflush(stdout)matnni darhol ekranga chiqaradi.
Keyingi bo'limda operatorlarni - arifmetik, mantiqiy va bit amallarini ko'ramiz.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
Xatolik topdingizmi?
Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.