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.

🕑 14 daqiqa o‘qish 📄 810 so‘z 👁 3 marta ko‘rilgan
Ushbu bo‘lim mundarijasi
  1. printf format belgilari
  2. Kenglik bilan jadval chiqarish
  3. Maxsus belgilar
  4. scanf - klaviaturadan o'qish
  5. scanf ning muammolari
  6. fgets - xavfsiz kiritish
  7. scanf va fgets ni aralashtirish
  8. Chiqishni bufersiz qilish
  9. To'liq misol - hisob-kitob
  10. Xulosa

Dastur foydalanuvchi bilan matn orqali gaplashadi. C da buning uchun stdio.h kutubxonasi ishlatiladi.

printf format belgilari #

Format belgisining tuzilishi %-8.2f boshlanish chapga tekislash kenglik: 8 belgi aniqlik: 2 xona tur: haqiqiy son Faqat % va tur majburiy, qolgani ixtiyoriy
Kenglik va aniqlik jadval ko'rinishidagi chiqish uchun juda foydali
BelgiTurMisol
%dbutun sonprintf("%d", 25)
%uishorasiz butunprintf("%u", 25u)
%lldlong longprintf("%lld", 9000000000LL)
%fhaqiqiy sonprintf("%f", 3.14)
%.2f2 xona bilan3.14
%eilmiy shakl3.140000e+00
%cbitta belgiprintf("%c", 'A')
%ssatrprintf("%s", "salom")
%pmanzilprintf("%p", &yosh)
%xo'n oltilikprintf("%x", 255)ff
%osakkizlikprintf("%o", 8)10
%zusizeof natijasiprintf("%zu", sizeof(int))
%%foiz belgisiprintf("%%")%
C
#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;
}
Natija
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 chiqaradi

printf("%f", 4.6789)4.678900. Odatda bu keraksiz. Deyarli har doim %.2f yoki %.1f yozing.

Kenglik bilan jadval chiqarish #

C
#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;
}
Natija
Talaba         Yosh     Baho
---------------------------------
Husanboy         25     4.60
Malika           21     4.90
Nodira           24     4.30
Kenglik qoidalari
YozuvMa'nosi
%8do'ngga tekislab, 8 belgi joy
%-8dchapga tekislab, 8 belgi joy
%08doldiga nol qo'yib: 00000025
%+dmusbat songa ham ishora: +25
%8.2f8 belgi joy, 2 xona kasr

Kenglikni yulduzcha orqali dinamik berish ham mumkin:

C
int kenglik = 10;
printf("%*d\n", kenglik, 42);

Maxsus belgilar #

YozuvNima qiladi
\nYangi qator
\tTabulyatsiya
\Teskari chiziq
\"Qo'shtirnoq
\'Bitta tirnoq
\0Satr oxiri belgisi
C
#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;
}
Natija
Ustun1    Ustun2    Ustun3
A    B    C
Yo'l: C:\Users\Husanboy
U "salom" dedi.

scanf - klaviaturadan o'qish #

C
#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;
}
Natija
Yoshingizni kiriting: 25
Siz 25 yoshdasiz.
Kelasi yili 26 yoshga to'lasiz.
& belgisini unutmang
C
scanf("%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 #

C
#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 tekshiring

scanf 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", ...) - xavfli
C
char 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:

C
char ism[10];
scanf("%9s", ism);     /* eng ko'pi 9 belgi + '\0' */

Yoki undan ham yaxshisi - fgets ishlating.

fgets - xavfsiz kiritish #

C
#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;
}
Natija
Ismingizni kiriting: Husanboy Qodirov
Salom, Husanboy Qodirov!
Nima uchun fgets afzal?
scanf("%s")fgets
Hajm chegarasiYo'q - xavfliBor - xavfsiz
Probelli matnO'qimaydiO'qiydi
Qator oxiriQoldiradiMassivga 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 #

C
#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;
}
Klassik tuzoq

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.

C
#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 #

C
#include <stdio.h>

int main(void) {
    printf("Yuklanmoqda");
    fflush(stdout);        /* darhol ekranga chiqaradi */

    /* uzoq davom etadigan ish... */

    printf(" - tayyor!\n");
    return 0;
}
Natija
Yuklanmoqda - tayyor!
Nima uchun 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 #

C
#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;
}
Natija
+----------------------+------------+
| Tavsif               |      Summa |
+----------------------+------------+
| Narx (donasi)        |  250000.00 |
| Miqdor               |          3 |
| Oraliq summa         |  750000.00 |
| QQS (12%)            |   90000.00 |
+----------------------+------------+
| JAMI                 |  840000.00 |
+----------------------+------------+
Amaliy topshiriq
  1. Har bir format belgisini (%d, %f, %c, %s, %x) sinab ko'ring.
  2. %.0f, %.1f, %.5f natijalarini solishtiring.
  3. Uch ustunli jadval chiqaring - kenglik bilan tekislang.
  4. Foydalanuvchidan ikkita son so'rab, ularning yig'indisini chiqaring.
  5. scanf da & ni ataylab unutib, nima bo'lishini ko'ring.
  6. scanf natijasini tekshiruvchi kod yozing va harf kiritib sinang.
  7. fgets bilan to'liq ism (probel bilan) o'qing.
  8. scanf dan keyin fgets ishlatib, muammoni o'z ko'zingiz bilan ko'ring.
  9. So'ng bufer tozalash bilan uni tuzating.
  10. Yuqoridagi hisob-kitob jadvalini foydalanuvchi kiritgan raqamlar bilan chiqaring.

Xulosa #

  • printf format belgilari: %d butun, %f haqiqiy, %c belgi, %s satr, %zu hajm.
  • %.2f - kasr xonasi soni, %-10s - chapga tekislangan kenglik.
  • %% - foiz belgisini chiqarish uchun.
  • scanf manzilni talab qiladi - & ni unutmang.
  • scanf natijasini tekshiring - u o'qilgan qiymatlar sonini qaytaradi.
  • scanf("%s", ...) xavfli - kenglikni cheklang yoki fgets ishlating.
  • fgets xavfsiz va probelli matnni o'qiydi, lekin '\n' ni qoldiradi.
  • scanf dan keyin fgets ishlatsangiz, buferni tozalang.
  • fflush(stdout) matnni darhol ekranga chiqaradi.

Keyingi bo'limda operatorlarni - arifmetik, mantiqiy va bit amallarini ko'ramiz.

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.