DEV Community

Cover image for CS50 - Week 2
Dilbar
Dilbar

Posted on

CS50 - Week 2

Kompilyatsiya qilish

Shifrlash - bu oddiy matnni begona ko'zlardan yashirish jarayoni. Deshifrlash esa, shifrlangan matnni inson o'qiy oladigan shaklga qaytarishdir.
Shifrlangan matn quyidagicha ko'rinishi mumkin:

shifrlangan matn

Kompilyator - dastlabki kodni kompyuter tushunadigan mashina kodiga aylantiradigan maxsus kompyuter dasturi.
Bizga hello.c faylida quyidagi berilgan bo'lsin:

#include <stdio.h>

int main(void)
{
    printf("hello, world\n");
}
Enter fullscreen mode Exit fullscreen mode

Kompilyator yuqoridagi kodni olib, quyidagi mashina kodiga aylantiradi:

mashina kodi

VS Code - to'liq nomi Visual Studio Code, bu Microsoft tomonidan ishlab chiqilgan bepul va ochiq manbali kod muharriri hisoblanadi. CS50 kursi talabalari uchun cs50.dev saytida VS Code kod muharriri sozlangan bo'lib, unda kompilyator sifatida clang ni ishlatadi.
clang – bu C, C++, va boshqa dasturlash tillari uchun mo‘ljallangan yuqori samarali va tezkor kompilyator hisoblanadi.

VS Code

Rasmda chap tomonda fayllarimizni topishimiz mumkin. Shuningdek, o'rtada matn muharriri joylashgan. O'ng tomon pastda buyruqlar qatori interfeysi (CLI) yoki terminal oynasi deb ataladigan soha mavjud bo'lib, bu yerdan kompyuterga buyruqlarni yuborishimiz mumkin.

make hello buyrug'ini VS Code kod muharrining terminal oynasida kiritadigan bo'lsak, u clang ni chaqiradi va hello.c faylimizni kompilyatsiya qiladi. Dasturimizni ./hello buyrug'i orqali ishga tushura olamiz.

Kompilyatsiya qilish bir nechta qadamlarni o'z ichiga oladi:

  • oldindan qayta ishlash (preprocessing) - bu koddagi sarlavha fayllari (masalan, #include <stdio.h>) faylimizga nusxalanib, joylashtiriladigan bosqichdir:
int printf(string format, ...);

int main(void)
{
    printf("hello, world\n");
}
Enter fullscreen mode Exit fullscreen mode
  • kompilyatsiya qilish (compiling) - bu dasturni assembler kodiga aylantirishdir:

compiling

  • yig'ish (assembling) - kompilyatorning assembler kodini mashina kodiga aylantirish:

assembling

  • bog'lash (linking) - bu bosqichda kodimizga kiritilgan kutubxonalar kodlari ham mashina kodiga aylantiriladi va birlashtiriladi:

linking


"Debug" qilish

Har kim ham dasturlash jarayonida xatolar qiladi. Quyidagi ataylab xato bilan yozilgan buggy.c faylini ko'rib chiqsak:

#include <stdio.h>

int main(void)
{
    for (int i = 0; i <= 3; i++)
    {
        printf("#\n");
    }
}
Enter fullscreen mode Exit fullscreen mode

Ushbu kodni ishga tushirganimizda, ekranga uchta belgi o'rniga to'rtta belgi ekranga chiqadi. printf funksiyasi yordamida dasturimizning qayerida xato qilganimizni qanday topishni ko'rib chiqamiz:

#include <stdio.h>

int main(void)
{
    for (int i = 0; i <= 3; i++)
    {
        printf("i - bu %i\n", i);
    }
}
Enter fullscreen mode Exit fullscreen mode

Yuqoridagi kodimizni ishga tushirsak, terminalda quyidagi matnlar paydo bo'ladi:

Debugging

Buni ko'rib, kodni quyidagicha to'g'rilash kerakligini tushunamiz:

#include <stdio.h>

int main(void)
{
    for (int i = 0; i < 3; i++)
    {
        printf("#\n");
    }
}
Enter fullscreen mode Exit fullscreen mode

Ya'ni, <= (kichik yoki teng) belgisini < (kichik) belgisiga o'zgartirdik.
Dasturdagi xatolarni to'g'rilashning ikkinchi vositasi "debugger" deb atalib, u dasturchilar tomonidan koddagi xatolarni kuzatishda yordam berish uchun yaratilgan dasturiy vositadir.
VS Code da oldindan sozlangan debugger mavjud. Ushbu debuggerdan foydalanish uchun quyidagi bosqichlarni bajaramiz:

  • "Breakpoint" qo'yish - kod satrining chap tomoniga bosganimizda qizil nuqta (to'xtash belgisi) paydo bo'ladi va u kompilyatorga ushbu kod qismida to'xtab, nima sodir bo'layotganini ko'rib chiqishimiz mumkinligini bildiradi.

breakpoint

  • Debuggerni ishga tushirish - terminalda debug50 ./buggy buyrug'ini bersak debugger ishga tushadi va breakpoint qo'yilgan satrda kod bajarilishi to'xtaydi.

  • Kodni tahlil qilish - barcha mahalliy o'zgaruvchilar chap yuqori burchakda ko'rsatiladi. Ekranning yuqorisida joylashgan "step over" tugmasini bosib, kodimizni birma-bir tekshirib chiqamiz. Bunda i o'zgaruvchisining qiymati qanday oshayotganini ko'rishimiz mumkin bo'ladi.

Debugger bizga qayerda xato borligini ko'rsatmasa ham, kodning qanday ishlashini asta-sekin ko'rib chiqishimizga yordam beradi.


Massivlar

Kompyuterimiz ichida mavjud bo'lgan xotira miqdori cheklangan.

memory

Kompyuter xotirasida ma'lum turdagi ma'lumotlar qanday saqlanishini tasavvur qilaylik. Masalan, char turi faqat 1 bayt xotira talab qiladi va u quyidagicha ko'rinishi mumkin:

byte

Shuningdek, 4 bayt xotira talab qiladigan int turi esa quyidagicha ko'rinishi mumkin:

4 bytes

Massivlar - ma'lumotlarni xotirada ketma-ket saqlash usulidir. Shuning uchun bu ma'lumotlarni osonlik bilan olish mumkin.
int scores[3] - bu kompilyatorga int turidagi uchta butun sonlarni saqlash uchun ketma-ket uchta joy ajratish buyrug'idir. Keling, ushbu ballarning o'rta arifmetigini topuvchi dastur yaratamiz:

#include <stdio.h>

int main(void)
{
    // Ballar qiymatini kiritish
    int scores[3];
    scores[0] = 72;
    scores[1] = 73;
    scores[2] = 33;

    // O'rta arifmetigini hisoblash va ekranga chiqarish
    printf("Average: %f\n", (scores[0] + scores[1] + scores[2]) / 3.0);
}
Enter fullscreen mode Exit fullscreen mode

scores[0] - massivning 0-indexsida turgan qiymatini kompyuter xotirasidan ko'rib chiqadi. Keling, scores massivi xotirada qanday joylashganini ko'ramiz:

scores in memory

Keling, yuqoridagi kodimizni abstraktlaymiz:

#include <cs50.h>
#include <stdio.h>

// O'zgarmas butun son
const int N = 3;

// Funksiya prototipi
float average(int length, int array[]);

int main(void)
{
    // Ballar qiymatini kiritish
    int scores[N];
    for (int i = 0; i < N; i++)
    {
        scores[i] = get_int("Score: ");
    }

    // O'rta arifmetikni ekranga chiqarish
    printf("Average: %f\n", average(N, scores));
}

float average(int length, int array[])
{
    // O'rta arifmetikni hisoblash
    int sum = 0;
    for (int i = 0; i < length; i++)
    {
        sum += array[i];
    }
    return sum / (float) length;
}
Enter fullscreen mode Exit fullscreen mode

for sikli orqali scores[i] yordamida massiv elementlariga qiymat kiritamiz. O'zgarmas butun son N e'lon qilingan. Shuningdek, average funksiyasi e'lon qilingan va u int array[] qabul qiladi, ya'ni kompilyator massivni ushbu funksiyaga o'tkazadi.
Demak, massivlar nafaqat konteyner bo'lishi, shu bilan birga ular funksiyalar orasida o'tkazilishi mumkin ekan.


String

String - bu char turidagi o'zgaruvchilar massividir, ya'ni belgilar massivi. Bunda u ma'lum belgi bilan boshlanib, satr tugaganini bildirish uchun maxsus NUL belgisi bilan tugaydi:

char array

Keling, char turidagi o'zgaruvchilarni ekranga chiqaruvchi dastur yozamiz:

#include <stdio.h>

int main(void)
{
    char c1 = 'H';
    char c2 = 'I';
    char c3 = '!';

    printf("%c%c%c\n", c1, c2, c3);
}
Enter fullscreen mode Exit fullscreen mode

Agar %c format kodini %i bilan almashtirsak, berilgan char turidagi o'zgaruvchilarning ASCII kodlari chop etiladi:

#include <stdio.h>

int main(void)
{
    char c1 = 'H';
    char c2 = 'I';
    char c3 = '!';

    printf("%i %i %i\n", c1, c2, c3);
}
Enter fullscreen mode Exit fullscreen mode

string qanday ishlashini yaxshiroq tushunish uchun kodimizni quyidagicha o'zgartiramiz:

#include <cs50.h>
#include <stdio.h>

int main(void)
{
    string s = "HI!";
    printf("%c%c%c\n", s[0], s[1], s[2]);
}
Enter fullscreen mode Exit fullscreen mode

Bunda string turidagi s o'zgaruvchimiz aslida massiv bo'lganligi sababli, 0-, 1- va 2-indeksdagi qiymatlarni chaqirishimiz mumkin.
Oldingidek, %c format kodini %i bilan almashtirishimiz mumkin:

#include <cs50.h>
#include <stdio.h>

int main(void)
{
    string s = "HI!";
    printf("%i %i %i %i\n", s[0], s[1], s[2], s[3]);
}
Enter fullscreen mode Exit fullscreen mode

Bunda string turidagi s o'zgaruvchisi belgilarining ASCII kodlari hamda NUL belgisi ekranga chiqadi.

String uzunligi

C tilida massivning uzunligini aniqlash muammosi mavjud. string ham aslida belgilar massividir. Keling string turidagi o'zgaruvchi uzunligini aniqlaymiz:

#include <cs50.h>
#include <stdio.h>

int string_length(string s);

int main(void)
{
    // Foydalanuvchining ismini so'rash
    string name = get_string("Name: ");
    int length = string_length(name);
    printf("%i\n", length);
}

int string_length(string s)
{
    // Belgilar sonini NUL belgisigacha hisoblash
    int n = 0;
    while (s[n] != '\0')
    {
        n++;
    }
    return n;
}
Enter fullscreen mode Exit fullscreen mode

Bunda string turidagi name o'zgaruvchisining uzunligi NUL belgisi topilgunga qadar hisoblanyabdi.
Bu dasturlashda juda keng tarqalgan muammo bo'lganligi sababli, boshqa dasturchilar string uzunligini hisoblashni osonlashtirish uchun string.h kutubxonasida tayyor strlen funksiyasini yaratganlar va biz uni shunchaki chaqirib ishlatishimiz mumkin:

#include <cs50.h>
#include <stdio.h>
#include <string.h>

int main(void)
{
    // Foydalanuvchining ismini so'rash
    string name = get_string("Name: ");
    int length = strlen(name);
    printf("%i\n", length);
}
Enter fullscreen mode Exit fullscreen mode

string.h kutubxonasi kodning yuqori qismida e'lon qilingan va foydalanuvchi kiritgan name o'zgaruvchisining uzunligini hisoblash uchun tayyor strlen funksiyasidan foydalanilyabdi.

Ushbu maqolada CS50x 2024 manbasidan foydalanilgan.

Top comments (0)