Kirish / chiqish: scanf va printf

~15 daq · C tili · Asoslar

Dastur foydalanuvchi bilan qanday gaplashadi?

Hozircha biz faqat ekranga ma'lumot chiqardik. Lekin haqiqiy dastur ikki tomonlama ishlaydi:

Foydalanuvchi → [klaviatura] → dastur → [ekran] → foydalanuvchi

Bu ikki yo'nalish:

  • Chiqish (output): printf — dasturdan ekranga
  • Kirish (input): scanf — klaviaturadan dasturga

Ikkalasi ham stdio.h da — Standard Input/Output.


Kirish va chiqish qanday ishlaydi?

C da ma'lumot oqim (stream) orqali o'tadi. Uch ta standart oqim mavjud:

Oqim Yo'nalish Manba
stdin kirish klaviatura
stdout chiqish ekran
stderr xato chiqish ekran

scanf → stdin dan o'qiydi printf → stdout ga yozadi


printf — chuqurroq

Sintaksis

printf("format satr", argument1, argument2, ...);

Format specifierlar

Specifier Tur Misol
%d int (o'nlik) 25
%u unsigned int 4000000
%f float / double 3.140000
%e Ilmiy yozuv 3.140000e+00
%g Qisqaroq f yoki e 3.14
%c char A
%s Satr (string) Salom
%p Pointer (manzil) 0x7fff...
%x O'n oltilik 1a
%ld long int 1000000000
%lf double (scanf da) 3.14
%% % belgisi %

Kenglik va aniqlik

#include <stdio.h>

int main() {
    int    son   = 42;
    float  kasr  = 3.14159f;
    char   satr[] = "Salom";

    // Kenglik (width) — minimum joy
    printf("[%d]\n",    son);      // [42]
    printf("[%5d]\n",   son);      // [   42]  — o'ngga tekis
    printf("[%-5d]\n",  son);      // [42   ]  — chapga tekis
    printf("[%05d]\n",  son);      // [00042]  — nol bilan to'ldir

    // Aniqlik (precision) — kasrdan keyingi raqamlar
    printf("[%f]\n",    kasr);     // [3.141590]
    printf("[%.2f]\n",  kasr);     // [3.14]
    printf("[%.4f]\n",  kasr);     // [3.1416]
    printf("[%8.2f]\n", kasr);     // [    3.14]

    // Satr kenglik
    printf("[%s]\n",    satr);     // [Salom]
    printf("[%10s]\n",  satr);     // [     Salom]
    printf("[%-10s]\n", satr);     // [Salom     ]

    return 0;
}

Natija:

[42]
[   42]
[42   ]
[00042]
[3.141590]
[3.14]
[3.1416]
[    3.14]
[Salom]
[     Salom]
[Salom     ]

Bir nechta argument

#include <stdio.h>

int main() {
    char   harf  = 'A';
    int    yosh  = 19;
    float  gpa   = 3.75f;

    printf("Harf: %c, Yosh: %d, GPA: %.2f\n", harf, yosh, gpa);

    return 0;
}

Natija:

Harf: A, Yosh: 19, GPA: 3.75

⚠️ Muhim: Argumentlar tartibi va specifierlar tartibi mos kelishi shart. Mos kelmasa — noto'g'ri natija yoki dastur ishdan chiqadi.


scanf — foydalanuvchidan ma'lumot olish

Sintaksis

scanf("format", &o'zgaruvchi);

& — nima uchun kerak?

& — manzil olish operatori. scanf qiymatni to'g'ridan-to'g'ri o'zgaruvchiga yozishi kerak. Buning uchun o'zgaruvchining xotira manzili kerak.

int yosh;
scanf("%d", &yosh);   // to'g'ri — manzil bilan
scanf("%d", yosh);    // xato — manzilsiz (undefined behavior)

scanf — asosiy ishlatish

int o'qish

#include <stdio.h>

int main() {
    int yosh;

    printf("Yoshingizni kiriting: ");
    scanf("%d", &yosh);
    printf("Siz %d yoshdasiz.\n", yosh);

    return 0;
}

Ishlash:

Yoshingizni kiriting: 19
Siz 19 yoshdasiz.

float va double o'qish

#include <stdio.h>

int main() {
    float  narx;
    double masofa;

    printf("Narxni kiriting: ");
    scanf("%f", &narx);        // float — %f

    printf("Masofani kiriting: ");
    scanf("%lf", &masofa);     // double — %lf (l harfi bor!)

    printf("Narx: %.2f so'm\n", narx);
    printf("Masofa: %.3f km\n", masofa);

    return 0;
}

⚠️ Diqqat: scanf da double uchun %lf — l harfi bilan. printf da esa %f ikkalasi uchun ham ishlaydi. Bu ko'p chalkashtiradigan joy!

char o'qish

#include <stdio.h>

int main() {
    char baho;

    printf("Bahongizni kiriting (A/B/C): ");
    scanf(" %c", &baho);    // bo'sh joy oldida — muhim!

    printf("Bahoingiz: %c\n", baho);

    return 0;
}

💡 scanf(" %c") — %c oldidagi bo'sh joy muhim. U oldingi Enter yoki bo'sh joylarni "yutib" yuboradi. Bo'lmasa — oldingi kiritmadan qolgan \n ni o'qib qo'yadi.

Bir vaqtda bir nechta kiritish

#include <stdio.h>

int main() {
    int   yosh;
    float boy;
    char  jins;

    printf("Yosh, bo'y va jins kiriting (masalan: 19 175.5 M): ");
    scanf("%d %f %c", &yosh, &boy, &jins);

    printf("\n===== Ma'lumotlar =====\n");
    printf("Yosh: %d\n",   yosh);
    printf("Bo'y: %.1f\n", boy);
    printf("Jins: %c\n",   jins);

    return 0;
}

Ishlash:

Yosh, bo'y va jins kiriting (masalan: 19 175.5 M): 19 175.5 M

===== Ma'lumotlar =====
Yosh: 19
Bo'y: 175.5
Jins: M

scanf ning qaytargan qiymati

scanf nechta o'zgaruvchini muvaffaqiyatli o'qiganini qaytaradi. Bu xatolarni tekshirishda ishlatiladi:

#include <stdio.h>

int main() {
    int son;
    int natija;

    printf("Son kiriting: ");
    natija = scanf("%d", &son);

    if (natija == 1) {
        printf("Qabul qilindi: %d\n", son);
    } else {
        printf("Xato! Son emas.\n");
    }

    return 0;
}

To'g'ri kiritilsa:

Son kiriting: 42
Qabul qilindi: 42

Noto'g'ri kiritilsa:

Son kiriting: abc
Xato! Son emas.

Buffer muammosi

scanf ishlatganda bufer (input buffer) tushunchasi muhim. Bufer — klaviaturadan kiritilgan ma'lumotlar vaqtincha saqlanadigan joy.

Foydalanuvchi: "25\n" bosdi
Buffer:        [ 2 ][ 5 ][\n]

scanf("%d"):   25 ni oldi, \n bufferda qoldi!

Muammo misoli

#include <stdio.h>

int main() {
    int  yosh;
    char baho;

    printf("Yosh: ");
    scanf("%d", &yosh);     // "25\n" — 25 olindi, \n qoldi

    printf("Baho: ");
    scanf("%c", &baho);     // \n ni oldi! — baho kiritilmadi

    printf("Yosh: %d, Baho: %c\n", yosh, baho);

    return 0;
}

Natija (noto'g'ri):

Yosh: 25
Baho:               <- kiritishga imkon bermadi!
Yosh: 25, Baho:

Yechim — bo'sh joy qo'shish

scanf(" %c", &baho);    // bo'sh joy \n ni yutadi

Natija (to'g'ri):

Yosh: 25
Baho: A
Yosh: 25, Baho: A

Amaliy dastur — Kalkulyator

#include <stdio.h>

int main() {
    double a, b;
    char   amal;

    printf("=== Oddiy Kalkulyator ===\n");
    printf("Birinchi son: ");
    scanf("%lf", &a);

    printf("Amal (+, -, *, /): ");
    scanf(" %c", &amal);

    printf("Ikkinchi son: ");
    scanf("%lf", &b);

    printf("\nHisob: %.2f %c %.2f = ", a, amal, b);

    if      (amal == '+') printf("%.2f\n", a + b);
    else if (amal == '-') printf("%.2f\n", a - b);
    else if (amal == '*') printf("%.2f\n", a * b);
    else if (amal == '/') {
        if (b == 0) printf("Xato! Nolga bo'lib bo'lmaydi.\n");
        else        printf("%.2f\n", a / b);
    }
    else printf("Noto'g'ri amal!\n");

    return 0;
}

Ishlash:

=== Oddiy Kalkulyator ===
Birinchi son: 15.5
Amal (+, -, *, /): *
Ikkinchi son: 4

Hisob: 15.50 * 4.00 = 62.00

Keng tarqalgan xatolar

Xato Sabab Yechim
scanf("%d", yosh) & unutilgan scanf("%d", &yosh)
scanf("%d", &narx) — float Format mos emas scanf("%f", &narx)
scanf("%f", &pi) — double l harfi yo'q scanf("%lf", &pi)
scanf("%c") bo'sh joy yutadi Buffer tozalanmagan scanf(" %c", &c)

Vazifalar

✏️ Vazifa 1 — Salomlashish

Foydalanuvchidan ismining birinchi harfini (char) va yoshini o'qing. Ekranga:

Salom, A! Siz 19 yoshdasiz.

formatida chiqaring.

✏️ Vazifa 2 — Aylana hisobi

Foydalanuvchidan radiusni (double) o'qing. Aylana yuzasi va uzunligini hisoblang:

Yuzasi  = pi * r * r
Uzunlik = 2 * pi * r

double pi = 3.14159265358979 ishlating. Natijani %.4f bilan chiqaring.

✏️ Vazifa 3 — Harorat konvertori

Foydalanuvchidan Celsius (float) o'qing. Fahrenheit va Kelvin ga aylantiring:

F = (C * 9/5) + 32
K = C + 273.15

Uchta qiymatni chiroyli formatda chiqaring.

✏️ Vazifa 4 — To'rtburchak

Foydalanuvchidan to'rtburchakning eni va bo'yini (float) o'qing. Yuzasi va perimetrini hisoblang. Natijani %.2f bilan chiqaring.

✏️ Vazifa 5 — Vaqt konvertori

Foydalanuvchidan soniyalar sonini (int) o'qing. Soat, daqiqa va soniyaga aylantiring:

3661 soniya → 1 soat, 1 daqiqa, 1 soniya

(/ va % operatorlarini ishlating)

✏️ Vazifa 6 — O'rtacha baho

Foydalanuvchidan 5 ta baho (float) ni ketma-ket o'qing (5 ta scanf). O'rtachasini hisoblang. Natijani %.2f bilan chiqaring.

✏️ Vazifa 7 — Pul almashtirish

Foydalanuvchidan dollar miqdorini (double) o'qing. So'm va evro ga aylantiring:

double dollar_kurs = 12800.0;
double evro_kurs   = 13500.0;

Natijani vergullar bilan chiroyli chiqaring.

✏️ Vazifa 8 — Uchburchak yuzasi

Foydalanuvchidan uchburchak uch tomonini (float a, b, c) o'qing. Perimetri va Geron formulasi bilan yuzasini hisoblang:

s = (a + b + c) / 2
Yuza = sqrt(s * (s-a) * (s-b) * (s-c))

math.h dan sqrt() ishlating. Kompilyatsiyada -lm flag qo'shing:

gcc vazifa.c -o vazifa -lm

✏️ Vazifa 9 — Printf formatlash

Quyidagi jadval aynan shu ko'rinishda chiqsin (kenglik va tekislash bilan):

Mahsulot           Narx    Soni
--------------------------------
Olma               3500      50
Non                2000     100
Shakar             8000      25

%-15s %7.0f %6d formatini ishlating. Ma'lumotlarni o'zgaruvchilarga joylab chiqaring.

✏️ Vazifa 10 — Kichik bank tizimi

Quyidagi dastur yozing:

Hisob raqamingiz: 1001
Ismingiz (birinchi harf): A
Balans (so'm): 500000

=== Bank Cheki ===
Hisob:   1001
Ism:     A
Balans:  500000.00 so'm
Holat:   Faol
==================

Barcha ma'lumotlar scanf bilan o'qilsin. Balans double, hisob raqam int, ism char, holat _Bool (1 = Faol).


Xulosa

printf scanf
Maqsad Ekranga chiqarish Klaviaturadan o'qish
Oqim stdout stdin
& kerakmi? Yo'q Ha
double uchun %f %lf
char uchun %c " %c" (bo'sh joy bilan)


Qo'shimcha — Advanced (majburiy emas)

Bu bo'lim hozircha o'tkazib yuborishingiz mumkin. Keyinchalik qaytib kelganingizda foydali bo'ladi.

puts va putchar — sodda chiqarish

#include <stdio.h>

int main() {
    puts("Salom, Dunyo!");   // printf + \n — avtomatik yangi qator
    putchar('A');            // bitta belgi chiqaradi
    putchar('\n');
    return 0;
}

puts — faqat satr chiqaradi, oxiriga \n o'zi qo'shadi. putchar — bitta char chiqaradi.

getchar — bitta belgi o'qish

#include <stdio.h>

int main() {
    char c;
    printf("Belgi kiriting: ");
    c = getchar();
    printf("Kiritdingiz: %c\n", c);
    return 0;
}

scanf(" %c") o'rniga getchar() ishlatish mumkin — ba'zan qulayroq.

fprintf — stderr ga xato chiqarish

#include <stdio.h>

int main() {
    int son;
    printf("Son kiriting: ");
    if (scanf("%d", &son) != 1) {
        fprintf(stderr, "Xato: son emas!\n");
        return 1;
    }
    printf("Son: %d\n", son);
    return 0;
}

fprintf(stderr, ...) — xato xabarlarini stdout dan alohida oqimga chiqaradi. Professional dasturlarda xatolar doim stderr ga yoziladi.

fflush(stdout) — bufer tozalash

printf("Yuklanmoqda...");
fflush(stdout);    // ekranga darhol chiqar
// ... uzoq hisob ...
printf(" tayyor!\n");

Ba'zan printf natijasi ekranga darhol chiqmaydi — buferda to'planadi. fflush uni majburan chiqaradi. Ayniqsa Windows da va \n bo'lmagan holatlarda kerak.

Keyingi dars

Kiritish va chiqarishni o'rgandik. Endi bu qiymatlar ustida hisob-kitob qilamiz.

6-dars: Arifmetik va mantiqiy operatorlar