CS50 - Week 1
Tags: cs50, c, programming, learning
Published: 2024-06-07 11:20:11

**بِسْمِ اللَّهِ الرَّحْمَنِ الرَّحِيم**
Mashinalar faqat binarni tushunadi. Biz kompyuter uchun biror-bir inson o'qiy oladigan ko'rsatmalar ro'yxatini yozganimizda, mashinalar faqat biz hozir _mashina kodi_ deb ataydigan narsani tushunadilar. Bu mashina kodi faqat 1 va 0 lardan iboratdir.
**Kompilyator** deb ataladigan maxsus dastur yordamida dastlabki kodni mashina kodiga aylantira olamiz.

Yaxshi kodni 3 asosga ko'ra baholashimiz mumkin:
- to'g'rilik (_kod istalgan natijani beryabdimi?_),
- dizayni (_kod dizayni yoki strukturasi yaxshi tuzilganmi?_),
- stil (_kod qanchalik chiroyli ko'rinishda yozilgan?_).

## Salom, dunyo!
C dasturlash tilida ekranga biror-bir matnni chiqarmoqchi bo'lsak, `printf` funksiyasidan foydalanamiz:

```c
#include <stdio.h>

int main(void)
{
    printf("salom, dunyo\n")
}
```

`printf` funksiyasi _`salom, dunyo`_ matnini ekranga chiqaradi. Undagi maxsus `\` belgisi kompilyatorga keyingi keladigan belgi maxsus ko'rsatma ekanligini anglatadi. Undan keyin kelayotgan `n` belgisi esa _"new line"_ (_yangi qator_) belgisini bildiradi.
Kodning birinchi qatoridagi ifoda `stdio.h` nomli kutubxona imkoniyatlaridan foydalanmoqchi ekanligimizni bildiruvchi juda maxsus buyruqdir. Bu kutubxona bizga `printf` funksiyasidan foydalanish imkonini beradi.
**Kutubxonalar** - bu bizning kodimizda foydalanishimiz mumkin bo'lgan tayyor funktsiyalar to'plamidir.

## O'zgaruvchilar
Keling, foydalanuvchidan uning ismi nima ekanligini so'rab, unga salom beruvchi kodni C tilida yozamiz:
```c
#include <cs50.h>
#include <stdio.h>

int main(void)
{
    string answer = get_string("Ismingiz nima? ");
    printf("Assalomu alaykum, %s\n", answer);
}
```
CS50 kursi uchun maxsus ishlab chiqilgan `cs50.h` kutubxonasi imkoniyatlaridan ushbu kurs davomida foydalaniladi. Ulardan biri `get_string` funksiyasidir. `get_string` funksiyasi foydalanuvchi kiritgan matnni olish uchun ishlatiladi.
`answer` - bu biz o'zgaruvchi deb ataydigan maxsus foydalanuvchi kiritadigan matnni eslab qolish uchun ajratilgan joy. `answer` _string_ turiga kiradi. Shuningdek, undan tashqari _int_, _bool_, _char_ va boshqalar kabi ko'plab ma'lumotlar turlari mavjud.
`%s` - bu `printf` funksiyasiga qandaydir `string` turidagi o'zgaruvchini qabul qilib olishga tayyorgarlik ko'rishini bildiruvchi _format kodi_ deb ataladigan to'ldiruvchidir.
Shuningdek, boshqa ma'lumot turlari uchun ham format kodlari mavjud, masalan:
`%i` - _int_ (butun sonlar) uchun.

## Shart operatorlari
Keling, foydalanuvchidan `int` turidagi `x` va `y` o'zgaruvchilarini kiritishini so'rab, kiritilgan sonlarni bir-biri bilan solishtiramiz:
```c
#include <cs50.h>
#include <stdio.h>

int main(void)
{
    int x = get_int("x ni kiriting: ");
    int y = get_int("y ni kiriting: ");

    if (x < y)
    {
        printf("x soni y sonidan kichik\n");
    }
}
```
Bu yerda biz `int` (_butun son_) turidagi ikkita o'zgaruvchini, `x` va `y` o'zgaruvchilarini yaratyabmiz. Ularning qiymatlari `cs50.h` kutubxonasining `get_int` funksiyasi yordamida to'ldiriladi. Shart operatori yordamida `x` va `y` qiymatlarini bir-biriga solishtirib, natijaga qarab ekranga xabar chiqaryabmiz.

**Blok-sxema** - kompyuter dasturi qanday ishlashini tekshirishimiz mumkin bo'lgan usuldir. Bu usul yordamida biz kodimizning samaradorligini tekshirishimiz mumkin.
Yuqoridagi kodimizning blok-sxemasini ko'ramiz:
![Conditional 1](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/rmdmtj69443dbvqoos8i.png)

Dasturni quyidagi tarzda kodlash orqali yaxshilashimiz mumkin:
```c
#include <cs50.h>
#include <stdio.h>

int main(void)
{
    int x = get_int("x ni kiriting: ");
    int y = get_int("y ni kiriting: ");

    if (x < y)
    {
        printf("x soni y sonidan kichik\n");
    }
    else if (x > y)
    {
        printf("x soni y sonidan katta\n");
    }
    else
    {
        printf("x soni y soniga teng\n");
    }
}
```
Endi barcha mumkin bo'lgan holatlar hisobga olinadi. Uning blok-sxemasini ko'ramiz:
![Conditional 2](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/okdsr438q6shdkm5w74r.png)


## Takrorlash operatorlari
Keling, 3 marta ekranga _"meow"_ xabarini chiqaramiz:
```c
#include <stdio.h>

int main(void)
{
    printf("meow\n");
    printf("meow\n");
    printf("meow\n");
}
```
Yozgan kodimiz to'g'ri ishlaydi, lekin undagi takrorlanishlarni oldini olib, dasturimizni quyidagicha yaxshilashimiz mumkin:
```c
#include <stdio.h>

int main(void)
{
    int i = 0;
    while (i < 3)
    {
        printf("meow\n");
        i++;
    }
}
```
Bunda `int` turidagi `i` o'zgaruvchisi yaratilib, unga 3 qiymati berilgan. Keyin `i < 3` bo'lgan vaqt davom etadigan `while` sikli yaratilgan. Har safar `i++` ifodasi yordamida `i` sonimiz bittaga oshib boradi va qachonki `i = 3` bo'lganida sikl to'xtaydi.
`for` sikli yordamida dasturimiz dizaynini yanada yaxshilashimiz mumkin:
```c
#include <stdio.h>

int main(void)
{
    for (int i = 0; i < 3; i++)
    {
        printf("meow\n");
    }
}
```
`for` sikli uchta argumentni o'z ichiga oladi.
Birinchi argument: `int i = 0` hisoblagichimizni noldan boshlaydi.
Ikkinchi argument: `i < 3` - tekshirilayotgan shart.
Nihoyat, `i++` argumenti har safar `i` sonimiz bittaga oshishini bildiradi.
Biz o'zimizning funksiyamizni yaratishimiz ham mumkin:
```c
void meow(void)
{
    printf("meow\n");
}
```
`void` - funktsiya hech qanday qiymat qaytarmasligini bildiradi. Qavslar ichidagi `(void)` - funktsiya hech qanday parametr qabul qilmasligini bildiradi.
Ushbu yaratgan `meow` funksiyamizni asosiy funksiya ichida ishlatamiz:
```c
#include <stdio.h>

void meow(void);

int main(void)
{
    for (int i = 0; i < 3; i++)
    {
        meow();
    }
}

void meow(void)
{
    printf("meow\n");
}
```
`meow` funksiyasini asosiy funksiya ichida chaqira olishimiz uchun funksiya prototipi kodning yuqori qismida `void meow(void)` sifatida berilgan.

## Arifmetik operatorlar va akstraksiya
Keling, C tilida kalkulyator yasaymiz:
```c
#include <cs50.h>
#include <stdio.h>

int main(void)
{
    // x qiymati kiritilsin
    int x = get_int("x: ");

    // y qiymati kiritilsin
    int y = get_int("y: ");

    // Qo'shish amalini bajarish
    printf("%i\n", x + y);
}
```
`get_int` funktsiyasi yordamida foydalanuvchidan butun son bo'lgan `x` va `y` o'zgaruvchilariga qiymat berishi so'ralyabdi. Keyin `printf` funksiyasi butun son uchun format kodi - `%i` belgisi yordamida `x + y` qiymatini chop etadi.

**Arifmetik operatorlar** kompilyator tomonidan qo'llab-quvvatlanadigan matematik operatsiyalardir. C tilida arifmetik operatorlarga quyidagilar kiradi:
- `+` - qo'shish uchun;
- `-` - ayirish uchun;
- `*` - ko'paytirish uchun;
- `/` - bo'linish uchun;
- `%` - bir sonni ikkinchi songa bo'lgandagi qoldiqni hisoblash uchun.

**Abstraksiya** - bu muammoni kichik-kichik bo'laklarga bo'lib hal qilish orqali kodimizni soddalashtirish san'ati.
Biz yuqoridagi kodimizni quyidagicha abstraktlashimiz mumkin:
```c
#include <cs50.h>
#include <stdio.h>

int add(int a, int b);

int main(void)
{
    // x qiymati kiritilsin
    int x = get_int("x: ");

    // y qiymati kiritilsin
    int y = get_int("y: ");

    // Qo'shish amalini bajarish
    printf("%i\n", add(x, y));
}

int add(int a, int b)
{
    return a + b;
}
```
Bunda parametr sifatida `a` va `b` butun sonlarini qabul qilib oladigan va ularning yig'indisini qaytaradigan alohida `add` funksiyasi e'lon qilingan va asosiy funksiya ichida argument sifatida `x` va `y` butun sonlarini olib `add(x, y)` funksiyamiz chaqirilyabdi.

## Kommentlar (izohlar)
**Kommentlar** - kompyuter dasturining asosiy qismlari bo'lib, yozgan kodimiz nima vazifa bajarayotganini ifodalovchi, boshqa dasturchilarga, shuningdek o'zimizga tushunarli hamda qisqa qilib qoldirgan izohlarimizdir. Kommentni yozish uchun shunchaki ikkita `//` beligisidan foydalanamiz:
```c
#include <cs50.h>
#include <stdio.h>

int main(void)
{
    // Musbat butun son kiritilsin
    int n;
    do
    {
        n = get_int("Musbat butun son kiriting: ");
    }
    while (n < 1);
}
```

## Ma'lumot turlari
**Ma'lumotlar turlari** o'zgaruvchida saqlanishi mumkin bo'lgan ma'lumotlar turini belgilaydi. Misol uchun, o'zgaruvchilar raqamlar, belgilar yoki mantiqiy qiymatlarni saqlashi mumkin. O'zgaruvchining turi kompyuterga ushbu ma'lumotlarni qanday boshqarishni aytadi.
C tilidagi umumiy maʼlumotlar turlari:
 - `bool`: _rost_ (`true`) yoki _yolg'on_ (`false`) kabi mantiqiy qiymatlarni saqlashi mumkin.
 - `char`: faqat bitta belgini saqlashi mumkin.
 - `float`: o'nlik qiymatlari bo'lgan haqiqiy son.
 - `int`: kasrsiz butun son.
 - `long`: `int` dan kattaroq butun sonni saqlashi mumkin, chunki u ko'proq bit ishlatadi.
 - `string`: belgilar ketma-ketligini saqlashi mumkin (masalan, so'z).

Har bir turning o'ziga xos chegaralari bor. Misol uchun, xotiradagi cheklovlar tufayli `int` ning eng yuqori qiymati 4294967295 bo'lishi mumkin. Agar biz `int` ni uning eng yuqori qiymatidan o'tkazib sanashga harakat qilsak, bu o'zgaruvchida noto'g'ri qiymat saqlanishiga (_integer overflow_) olib keladi.
Xotirani noto'g'ri ishlatish kodimizdagi xatolar yoki muammolarga olib kelishi mumkin. Muammolarni oldini olish uchun biz to'g'ri ma'lumot turidan foydalanayotganimizga ishonch hosil qilishimiz kerak.

> Ushbu maqolada [CS50x 2024](https://cs50.harvard.edu/x/2024) manbasidan foydalanilgan.