15 Aralık 2014 Pazartesi

C-DILI

Giriş

Bu mətndə C dilində proqram tərtibindən bəhs olunur . Mətndən tələbələr, məktəblilər, informatika fənnini tədris edən müəllimlər , sistem inzibatçıları və ümumilikdə C (si) proqaramlaşdırma dilini örgənmək istəyən kər kəs istifadə edə bilər. Bu mətndən istifadə edə bilmək üçün ilkin olaraq heç bir proqramlaşdırma dilini bilmək tələb onunmur.

Kompüterlər, proqramlar, proqramlaşdırma dilləri, əməliyyat sistemləri.

Proqram anlayışını daxil etməzdən və C dilinin müasir İnformasiya və Kommunikasiya Texnalogiyalarında yeri barədə söz açmazdan öncə gəlin əvvəl bugünkü həyatımızada kompüterlərin və proqramların oynadığı rola sadə bir nəzər salaq. Kompüterlər demək olar ki, hər yerdə, məişətdə, təhsildə, tibbdə, sənayedə v.s. yerlərdə çox geniş istifadə olunur. Məsələn NASA – da kosmik gəmilər, süni peyklər, zavodlarda mürəkkəb istehsal prosesləri kompüterlər vasitəsilə idərə olunur. Milyardlarla insan məlumatları içərisində axtarış parametrlərinə uyğun gələnini kompüter verilənlər bazasından çox az bir zaman ərzində(saniyənin kiçik bir hissəsi) tapır. Adi istifadəçilər kompüterlə müxtəlif oyunlar oynayır, hər-hansı mətn və ya cədvəl üzərində işləyir v.s.
Arxitektura cəhətdən dünyada mövcud olan əksər kompüterlər arasında elə də böyük fərq yoxdur. Yəni evdə istifadə etdiyimiz komputerlə NASA – da istifadə olunan kompüterlər bir-birindən əsasən yaddaş və sürətinə görə fərqlənir. Bəs niyə biz öz kompüterimizlə hansısa kosmik gəmiləri idarə etmirik ? Kompüterlərə bu qədər müxtəlif işlər yerinə yetirməsinə imkan verən nədir? Niyə hansısa kompüterlə hər-hansı işi gürmək olar digəri ilə yox? Kompüterə ümumiyyətlə istənilən bir işi görə bilməsinə imkan verən nədir? Əlbəttdə ki proqram. Məhz proqram kompüterə hansı işlər görməli olduğunu tam detalları ilə bildirir. Proqramsız kompüter təmamilə yararsız bir dəmir parçasıdır. Proqramı isə əlbəttdə ki proqramçılar tərtib edir. Bu iş son dərəcə çətin və məsuliyyətlidir. Proqramın hazırlanma prosesi, onun daxili strukturu və yerinə yetirilmə prosesi kifayət qədər mürəkkəb məsələlərdir və bu məsələrlə məşğul olmaq təcrübə tələb edir. Biz hələlik proqramın hazırlanması ilə məşğul olacayıq. Biz proqramın mətn kodunu yazırıq C dilində , daha sonra xüsusi proqramlar vasitasilə bizim mətndən icra olunan proqram alınır.
İndi isə bir qədər C dili barəsində danışaq. C dili haqda Wikipediada kifayət qədər məlumat verilib. Qısa olaraq onu demək olar ki:
1. C dilinin sintaksisi C++, JAVA, PHP dillərinin sintaksisi ilə eynidir(buradan isə o çıxır ki, bütün bu dillərin sintaksisi eynidir :) ). Bu C dilini (və ya bu dillərdən hər hansı birini) bilməklə digərlərinə keçməni xeyli asanlaşdırır.
2. C dilində yazılan proqramlar çox sürətli və təhlükəsiz olduğundan ciddi proektlər əsasən bu dildə yaradılır. Buraya əməliyyatlar sistemləri (bütün UNİX-tipli sistemlərin hamısı C dilində yazılıb), Google axtarış sistemi və bir çox digər proqramları aid etmək olar. Bu siyahını istənilən qədər uzatmaq olar. Lakin C dilinin bugünkü gündə rolunu anlamaq üçün "bütün UNİX-tipli əməliyyatlar sistemi anlayışına" nəzər salmaq kifayətdir.
UNİX-tipli əməliyyatlar sistemlərinin dəqiq siyahısını vermək mümkün deyil. FreeBSD, OpenBSD SOLARİS, HP_UX, AİX... və xakerlərin sevimlisi GNU/LİNUX (çünki təmamilə xakerlər tərəfindən yaradılıb) sistemlərini bu siyahının parlaq nümunələri kimi misal göstərmək olar. UNİX-tipli anlayışına müəyyən qədər aydınlıq gətirdik, indi isə əməliyyatlar sisteminin nə demək olduğuna baxaq.
Əməliyyatlar sistemi sadəcə və sadəcə müəyyən qrup proqramlar yığınıdır. Ancaq proqramlar, ayrı heçnə. Buraya daxildir müxtəlif server proqramları webserver(appache...), file server(ftp server...), məlumatlar bazası proqramları( oracle, mysql ...), kompilyator, assembler, linker proqramları ( proqram tərtib etmək üçün) , mətn redaktorları, shell proqramları (digər proqramları yükləmək və icra etmək üçün), arxiv proqaramları (tar, gzip ... faylların həcmini kiçiltmək üçün) , 100 -lərlə, 1000 -lərlə digər proqramlar və əlbəttdə ki ən əsası nüvə (kernel) proqramı. Təsəvvür edin bu qədər proqramın hamısı C dilində yazılıb.
İndi isə ən maraqlısı – nüvə. Nüvə proqramı kompüter əməliyyatlar sisteminin ən əsas proqramıdır. Bu proqram sistemin fəaliyyatinə tam olaraq nəzarət edir. O əməliyyatlar sisteminin digər proqramlarının fəaliyyəti üçün lazim olan bütün funksiyaları özündə cəmləyir. Xüsusi olaraq buraya kompüterin qurğularının idarə olunması(driverlər), yaddaşının idarə olunması(memory management), proseslərin(yerinə yetirilən proqramların ) idarə olunması, faylların idarə olunması , şəbəkənin idarə olunması(networking), kompüterin digər resurslarının v.s. idarə olunması daxildir. Beləkliklə C dilini mükəmməl bilmək mənbə kodları açıq şəkildə verilən bu proqramları(bəziləri istisna olmaqla – oracle,...) başa düşməyə və müəlliflər tərəfindən verilmiş imkanlar daxilində (GPL, OSL, v.s. lisenziyaları) bu proqaramları dəyişib istifadə etməyə imkan verir.

C proqaramlaşdırma dili.

İlk proqram.

Bu mövzuda biz ilk proqramı yerinə yetirmək barədə danışacağıq. Yəni C dilində proqram yazmaq üçün bizə nə lazımdır, bunları haradan əldə edə və necə işlək vəziyyətə gətirə bilərik. Sonda hər şeyin qaydasında olduğunu yoxlamaq məqsədilə test proqram yerinə yetirəcəyik.
C dilində və istənilən digər dildə proqram yazmaq üçün bizə kompüter, əməliyyatlar sistemi, kompilyator və mətn redaktoru proaramları lazımdır. Kompüter məsələsi aydındır.
Əməliyyatlar sistemi. ---- Hal-hazırda geniş yayılmış 2 əməliyyatlar sistemi ailəsi mövcuddur. UNİX tipli sistemlər və Windows sistemləri ailəsi.
Windows əməliyyatlar sistemi.
Windows istifadəçilər üçün çox rahatdır, amma Windowsla bağlı bir çox proqramçıların mövqeyi müsbət deyil. Məsələ ondadır ki bir çox CPU(prosessor) arxitekturaları qoruyucu rejimdə(əsas işçi rejim) işlədikdə yaddaşı(RAM) seqmentlərə bölür və bir seqmentin proqram kodunun digər seqmentə müraciət etməsinin qarşısını alır(qoruyur). Belə halda kompüterdə yerinə yetirilən proqramlar 2 qrupa bölünür.
Yüksək prioritetli seqmentlərə yüklənmiş proqramlar.
Bu proqram kodlarına aiddir nüvə(kernel) kodu. Driverlər, yaddaşın, şəbəkənin, fayllar sisteminin, proseslərin idarə olunması və bir çox digər işləri yerinə yetirən proqram kodları bu qrupa daxildir. Bu proqramlar kompüterin bütün resurslarına (portlar v.s.) tam nəzarət edir və onlar yaddaşın istənilən segmentinə istənilən müraciəti edə bilərlər.
Aşağı prioritetli seqmentlərə yüklənmiş proqramlar.
Bu proqramlara kompüterə yüklənmiş yerdə qalan proqramlar -- istifadəçi proqramları aiddir.
Windows sistemi öz nüvəsinin proqram kodlarını gizli saxlayır.
Bu isə öz proqramlaşdırma biliyini daha da inkişaf etdirmək istəyən proqramçılara maneə yaradır.
UNIX tipli sistemlər.
GNU/LINUX, FREEBSD, SOLARIS, AIX, ...
Unix sistemləri proqramçılar tərəfindən yaradılıb və bütün proqram kodları açıqdır. Kompüter arxitekturasını örgənmək istəyən proqramçılar üçün unix əvəzedilməz əməliyyatlar sistemidir.
Unix sistemləri həm interfeys, həm də daxili struktur baxımından bir-birinə çox yaxındır. Bu sistemlərin içərisində ən maraqlısı GNU/LİNUX sistemidir.
Bu mətndə verilmiş bütün proqramlar GNU/LINUX sistemi üçün nəzərdə tutulub, lakin eyni qayda ilə digər unix sistemlərində də yerinə yetirilə bilər.
İstənilən halda bu mətndə verilmiş proqramları Windows sistemində də icra etmək olar, bunun üçün MS Visual C++, Borland C++ Builder və Delphi kompilyatorlarından istifadə edə bilərsiniz.
Proqram yazmaq üçün bizə lazım olan digər vasitə MƏTN redaktoru proqramıdır.
Biz gedit proqramından istifadə edəcəyik.
gedit proqramını yükləmək üçün
Applications->Accessories->Text Editor
seçimini edin.
Kompilyator proqramı
Kompilyator proqramı olaraq gcc -dən istifadə edəcəyik və bu kompilyator bütün unix sistemlərində ən çox istifadə olunan proqramdır və o hər bir sistemin paketinə daxil olduğundan instalyasiyaya ehtiyac yoxdur.

İlk test proqram ---- Hello world proqramı.

Qeyd edək ki ilk test proqramını yerinə yetirib lazımi nəticəni almaq həqiqətən əzmkarlıq tələb edir və bir qayda olaraq həmişə bir neçə uğursuz cəhtdən sonra alınır. İlk olaraq işçi qovluq(kataloq, papka, folder, directory) anlayışına aydınlıq gətirək.Terminal proqramını yükləyin.
Applications->Accessories->Terminal
Terminal pəncərəsindən aşağıdakı əmri daxil edin.
pwd
Ekranda sizin işci qovluq cap olunacaq.
user@gnu_linux:~$ 
user@gnu_linux:~$ 
user@gnu_linux:~$ pwd
/home/user
user@gnu_linux:~$ 
user@gnu_linux:~$
ls əmrini daxil edin
user@gnu_linux:~$ 
user@gnu_linux:~$ ls
3_20      ch02.pdf      f1.txt       music        Public          ubuntu_ins
3_20.cpp  Desktop       german       music_file   fhedd           Videos
arch      documents     mozilla.pdf  music_file~  ramdisk.img.gz  vmlinuz26
a.txt     dff          mozilla.ps   pictures     telix           wget
boot      Examples      m.txt        prg          Templates
user@gnu_linux:~$ 
user@gnu_linux:~$
bu əmr hal hazırda bizim işci qovluqda olan faylları və qovluqları göstərir.
mkdir proqs əmrini daxil edirik.
Nəticədə bizim işci qovluqda yeni proqs qovluğu yaranacaq.
cd proqs əmrini daxil edirik.
Nəticədə bizim işci qovluq proqs olacaq. Bu qovluğu yeni yaratdıq və orada olan faylları yoxlamaq üçün yenidən ls əmrini daxil edirik.
user@gnu_linux:~$ 
user@gnu_linux:~$ mkdir progs
user@gnu_linux:~$ 
user@gnu_linux:~$ cd progs
user@gnu_linux:~/progs$ 
user@gnu_linux:~/progs$ ls
user@gnu_linux:~/progs$ 
progs qovluğunu yeni yaratdıq və hələlik onda heç bir fayl yoxdur.
gedit proqramını yükləyək.
Applications->Accessories->Terminal
Aşağıdakı mətni gedit proqramına köçürüb hello.c adı ilə yeni yaratdığımız proqs qovluğunda yadda saxlayırıq.
#include<stdio.h>
 
int main(){
 
printf("Hello World\n");
 
}
ls əmrini daxil edək. Nəticə aşağıdakına bənzər olmalıdır.
user@gnu_linux:~/progs$ 
user@gnu_linux:~/progs$ ls
hello.c
user@gnu_linux:~/progs$ 
user@gnu_linux:~/progs$ 
hal-hazırda proqs qovluğunda bizim yaratmaq istədiyimiz proqramın mətn fayli(çox vaxt buna mətn kodu deyirlər) var( hello.c ). Bu koddan yerinə yetirilə bilən proqram almaq üçün (mətn kodun kompilyasiya etmək üçün)
gcc hello.c -o hello
əmrini daxil edək. Əgər siz proqramın mətn kodunu düzgün köçürmüsünüzsə onda proqramın kompilyasiyası uğurla başa çatmalıdır. Bunu yoxlamaq üçün yenə ls əmrini daxil edirik. bu dəfə proqs qovluğunda hello adlı yeni faylın yarandığını görürük. Bu bizim proqramdır.
user@gnu_linux:~/progs$ 
user@gnu_linux:~/progs$ gcc hello.c -o hello
user@gnu_linux:~/progs$ 
user@gnu_linux:~/progs$ ls
hello  hello.c
user@gnu_linux:~/progs$ 
user@gnu_linux:~/progs$ 
Yeni yaratdığımız hello proqramını yerinə yetirmək üçün
./hello
əmrini daxil edirik. Əgər ekranda
Hello World 
sətri çap olundusa onda sizi təbrik edirik, siz artıq C dilində ilk proqramı yerinə yetirdiniz.
user@gnu_linux:prg# 
user@gnu_linux:prg# gcc  hello.c -o hello
user@gnu_linux:prg# ./hello
Hello World
user@gnu_linux:prg# 
user@gnu_linux:prg# 
Indi isə gəlin proqramın mətn kodu ilə daha ətraflı tanış olaq. Bunun üçün əvvəl bu proqramın bir qədər dəyişik variantlarını yerinə yetirək. 
prog hello_1.c
#include <stdio.h>
 
int main(){ 
 
printf("Hello World_1\n"); 
 
}
 
proqramın mətnini hello1.c adlı faylda yadda saxlayırıq və kompilyasiya edirik.
 gcc hello1.c -o hello1  
və yerinə yetiririk
./hello1
 
user@gnu_linux:~prg# 
user@gnu_linux:~prg# gcc  hello1.c -o hello1
user@gnu_linux:~prg# 
user@gnu_linux:~prg# 
user@gnu_linux:~prg# ./hello1
Hello World_1
user@gnu_linux:~prg#
Bu dəfə ekranda Hello World_1 sətrinin çap olunduğunu görərik. Yəqin ki oxucuya aydın olur ki, bu proqram yerinə yetirildikdə printf("....................."); sətrində "  " arasında olan ifadə ekranda çap olunur \n – dən savayı. hello1.cfaylında həmin sətri printf("Salam dünya . Bu mənim C dilində 3-cü proqramımdır\n"); sətri ilə əvəz edək. Proqramı kompilyasiya ediib yerinə yetirsək ekranda Salam dünya . Bu mənim C dilində 3-cü proqramımdır sətri çap olunacaq.
Tapşırıq:
Ekranda müxtəlif yazılar çap edən proqramlar yazmalı.
Beləliklə proqram haqda təcrübə topladıq , indi isə gəlin hello.c proqramını daha dərin analiz edək. Proqramın ilk sətri
   #include <stdio.h>  
sətridir. Bu sətrin dəqiq izahı 10-cu paraqrafda verilir. Hələlik isə onunla kifayətlənək ki, bu sətir proqramda printf funksiyasından istifadə etməyə imkan verir. Növbəti sətir
     int main(){   
sətridir. Burada main adlı funksiya təyin olunur. Funksiyalar barəsində daha ətraflı 5-ci paraqrafda söhbət açacağıq. Hələlik isə onu qeyd edək ki, main funksiyası bütün C proqaramlarında olmalıdır və C dilində yazılmış hər bir proqram yerinə yetirilməyə məhz bu yerdən başlayır. Növbəti sətir
printf("Hello World\n"); 
sətridir. Bu sətir bizə tanışdır. Ekranda hər – hansı sətri , rəqəmi, v.s. məlumatı çap etmək üçün istifadə olunur. printf çox güclü çap funksiyasıdır və konkret yerlərdə bu imkanlarla tanış olacağıq. İndi isə təcrübə kimiprintf("%d%s%d=%d\n",3,"+",5,3+5); sətrini proqrama əlavə edib onu yerinə yetirək. Proqramın son sətri isə } sətridir.
Bu işarə main funksiyasının bitdiyini bildirir. Printf funksiyasında tez-tez rast gəldiyimiz \n isə yeni sətir simvolu adlanır. Yəni printf çap edəcəyi sətirdə \n – nə rast gəldikdə yerdə qalan hissəni növbəti sətirdən çap edir. Aşağıdakı sətri proqrama əlavə edib bunu yoxlayın.

Dəyişənlər

Əvvəlki paraqrafda biz C dilində necə proqram yerinə yetirməyi örgəndik. Bu paraqrafda biz C dilində yazılmış proqramın ən vacib elementlərindən biri – dəyişənlərlə tanış olacağıq. Hər bir proqram yerinə yetirilərkən müxtəlif məlumatları yadda saxlamalı (yaddaşa yerləşdirməli) olur. Tutaq ki iki ədədin cəmini hesablayan proqram yazmaq istəyirik. Bu zaman biz yaddaşda 3 məlumat üçün yer ayırmalıyıq. İki toplanan və cəm. Proqramlaşdırmada hər hansı məlumatı qəbul etmək, yadda saxlamaq və bu məlumatın qiymətinə müraciət etmək üçün dəyişənlərdən istifadə olunur. Konkret olaraq dəyişən adı olan müəyyən bir yaddaş sahəsidir. Bu yaddaşın sahəsini və adı dəyişəni elan edərkən biz özümüz(proqramçılar) müəyyən edirik.
Yadda saxladığı məlumatın növünə və həcminə görə dəyişənlər tiplərə ayrılır. Misal üçün tam ədədlər tipi - int, kəsr ədədlər tipi - float, simvol tipi - char, sətir tipi - char [], char *v.s. Bu tiplərə standart tiplər deyilir. Bundan əlavə C dilində ünvan dəyişənləri tip, struktur tiplər və siyahılardan da çox geniş istifadə olunur ki, bunlarla da uyğun olaraq 4, 8 və 9-cu paraqraflarda məşğul olacayıq.
Əgər biz proqramda tam tipdən(int) olan və adı x olan dəyişən elan etmək istəyiriksə bu zaman
int x;  
sətrini proqrama yerləşdiririk.
Dəyişənlərə istədiyimiz kimi ad verə bilərik yalnız və yalnız həriflərdən(ingilis əlifbasının) , '_' simvolundan və rəqəmlərdən istifadə etməklə. Dəyişənin adı mütləq hərflə başlamalıdır, və operator, tip v.s. adlardan da dəyişən adı kimi istifadə etmək olmaz. Operatorlarla gələn mövzularda tanış olacayıq.
Beləliklə cəm proqrmında hər iki toplananı və onların cəmini yerləşdirmək üçün biz tam tipli 3 dəyişən təyin etməliyik. Gəlin bu dəyişənləri uyğun olaraq top1, top2 və cem kimi adlandıraq. Bu dəyişənləri təyin etmək üçün proqram kodu aşağıdakı kimi olacaq.
 int  top1;
 int  top2;
 int cem;
Qeyd edək ki eyni tipdən olan dəyişənləri vergüllə ayırmaqla bir sətirdə də elan edə bilərik. Aşağıdakı kimi
 int top1,top2,cem; 
Burada ; simvoluna diqqət yetirməyinizi istəyirəm. Bu işarə kompilyatora hər hansısa bir əməliyyatın (indiki halda dəyişənlərin elanının) bitməsini göstərir.
Gəlin proqramımızı tərtib edək. Hələlik 3 dəyişən elan etmişik(dəyişən elan etmək və ya təyin etmək eyni məna bildirir). Proqramımız belə olacaq.
   
#include <stdio.h>
   
int main(){
  
int top1, top2, cem;
   
}
Proqramı cem.c faylında yadda saxlayaq və kompilyasiya edək və yerinə yetirək.
user@gnu_linux:~/prg 
user@gnu_linux:~/prg gcc cem.c -o cem
user@gnu_linux:~/prg 
user@gnu_linux:~/prg ./cem
user@gnu_linux:~/prg 
user@gnu_linux:~/prg 
Göründüyü kimi proqram heç bir iş görmür, sadəcə tam tipli 3 dəyişən elan edir və icrasını bitirir.
İndi gəlin bu elan etdiyimiz dəyişənlərdə hər hansı məlumat (ədədlər) yerləşdirək(daha doğrusu dəyişənə aid olan yaddaş sahəsinə). Proqramlaşdırmada hər hansı əməliyyatı yerinə yetirmək üçün istifadə olunan əmrə operator deyilir. Yaddaşa məlumat yazma əməliyyatı üçün mənimsətmə operatorundan istifadə olunur. Mənimsətmə operatoru = kimi işarə olunur. Qətiyyən riyaziyyatda olan bərabərlik simvolu ilə qarışdırmaq olmaz. Proqramda bu operatordan solda dəyişənin adı , sağda isə ona mənimsədiləcək qiymət dayanır(və əlbəttdə bütün operatorların sonunda olduğu kimi sonda ; işarəsi). məsələn
 
   x = 5 ;  
Bu operator x dəyişəninə 5 qiymətini mənimsədir. Bu zaman yaddaşda nəyin baş verdiyinə gəlin nəzər salaq. Əvvəlcə 5ədədi onluq say sistemindən ikilik say sisteminə çevrilir. Say sistemləri əsasən assembler proqramlaşdırma dilinin mövzusu olduğundan və bu işlərlə məşğul olmaq böyük proqramlaşdırma təcrübəsi tələb etdiyindən bu haqda çox dərinə getməyəcəyik.
5 ədədi ikilik say sistemində aşağıdakı kimi göstərilir.
00000000000000000000000000000101
x tam tipli olduğundan yaddaşda onun üçün 4 bayt yer ayrılır. Bir bayt 8 bit – dən ibarət yaddaş sahəsidir. Bir bit ən kiçik yaddaş sahəsidir və bu sahəyə ancaq 1 və ya 0 yazmaq olar. Komputerin yaddaşı baytlar ardıcıllığından və o da öz növbəsində bitlərdən ibarət olduğundan, bitlərdə isə ancaq 0 və ya 1 yerləşdirmək mümkün olduğundan belə çıxır ki kompüterin yaddaşına yerləşdirilən bütün məlumat orada 0 və 1 -lər ardıcıllığı şəklində saxlanılır. Yəni bütün bizim mp3 , wav, jpg , doc v.s. fayllarımız və ümumiyyətlə bütün fayllar yalnız və yalnız 0 və 1 - lər ardıcıllığıdır. Məişətdə istifadə etdiyimiz bir çox texnikanın (komputer , fotoaparat, ... ) adının rəqəmsal (digital, digit ingilis dilində rəqəm deməkdir)olması da buradan qaynaqlanır və burada söhbət ancaq 0 və 1 rəqəmlərindən gedir.
Tutaq ki baxdığımız anda proqramın yaddaşı aşağıdakı şəkildədir. 
Shekil1.
x=5;  
Indi isə yaddaşın vəziyyəti aşağıdakı kimi olar.
şəkil 2.
Aşağıdakı operatora baxaq.
   x=y;  
Bu halda y -in qiyməti yaddaşdan x-in ünvanına köçürülür.
Sekil3. Shekil4.
Aşağıdakı hala baxaq.
   x=x+1;
Bu halda əvvəlcə x-in qiyməti yaddaşdan götürülür, onun üzərinə 1 əlavə olunur və alınmış nəticə yenidən x-ə yazılır. Tutaq ki x – ə 3 qiyməti mənimsədilib.
  x=3;  
Shekil5. x=x+1; 3+1 --- 4 --- 00000000000000000000000000000100 Shekil6.

Proqramda Şərhlər

C dilində yazılmış hər – hansı proqramı şərhsiz təsəvvür etmək olmaz. Şərh (comment, statement ... ) proqramın bu və ya digər hissəsinin hansı iş gördüyünü bildirmək üçün proqramın mətn koduna əlavə olunur .Şərhlər ancaq proqramın işini başa düşmək istəyənlər üçündür. Proqramın real yerinə yetirilən koduna şəhrlərin heç bir aidiyyəti yoxdur. Belə ki, kompilyator proqramı kompilyasiya edərkən birinci gordüyü iş şərhləri proqram kodundan silməkdir. Proqramda şərh elan etmək üçün /* və */ - dən istifadə olunur.
Bu zaman kompilyator bu işarələr arasında yerləşdirilən mətni şərh kimi üəbul edəcək. Lakin səhvən proqram kodlarını şərh kimi verməyin. Bu zaman kompilyator onları nəzərə almayacaq. Onu da deyim ki, çox vaxt bu qaydadan proqramdakı səhvləri tapmada istifadə olunur (proqramın müəyyən hissəsini şərh kimi verib nəticəni yoxlamaqla).

Dəyişənlərin müqayisəsi və qiymətlərinin dəyişdirilməsi.

Dəyişənlərin qiymələrinin dəyişdirilmə və müqaisə imkanının olması proqramçıya çox geniş imkanlar verir. Dəyişənərlə aşağıdakı əməliyyatları aparmaq olar. 
*, -, +, /, =, ==, >, < * hasil, - çıxma, + cəm. Bizim üçün lazım olan ən vacib əməliyyat , dəyişənin qiymətinin dəyişdirilməsi əməlidir. Bunun üçün '=' operatorundan istifadə olunur. Bu operatora 'mənimsətmə' operatoru deyirlər. Bu opratoru bərabərlik opratoru kimi qəbul etmək olmaz. C++ dilində bərabərlik opratoru olaraq == istifadə olunur. Aşağıdakı nümunələrə baxaq.
   a = 4*6;                  /*   proqramda bu sətir yerinə yetirildikdən sonra */
                             /* əvvəlki qiymətindən asılı olmayaraq a-nın qiyməti yeni qiyməti 24 olacaq. */
     a = a + 5;              /*   a -nın yeni qiyməti əvvəlki qiyməti ilə 5 -in cəminə bərabər olur.  */
     a == 3;                 /*   a -ya heç bir yeni qiymət mənimsədilmir(a-nin qiymeti deyishmir) , sadəcə onun 3 -   */
                            /*ə bərabər olub olmaması yoxlanılır  */
Yəqin ki, siz < və > operatorlarının necə işlədiyini düşünürsünüz. Onlar uyğun olaraq böyükdür və kiçikdir operatorlarıdır. Məsəslən.
   a < 5        /*  a -nın 5 -dən kiçik olmasını yoxlayır        */
   a > 5        /*  a -nın 5 -dən böyük olmasını yoxlayır        */
   a == 5          /*  a -nın 5 -ə bərabər olmasını yoxlayır        */
proqramlaşdırmanı örgənməyin yeganə yolu proqram yazmaqdır.
Aşağıda verilən tapşırıqları yerinə yetirən proqramlar yazın.
Həlli olanlar. (həllərə yalnız öz cəhdləriniz nəticə vermədikdə müraciət etmək məsləhət görülür.)
1.3 ədədin cəmini hesablayan proqram tərtib edin.
2. Hər – hansı ədədi və onun kvadratını hesablayan proqram tərtib edin.
3. Aşağıdakı kod hissəsinin gördüyü işi yoxlamaq üçün proqram tərtib edin.
   int  x,y;
    x=5;
     y=9;
  printf("x=%d  y=%d",x,y);
 
 
 
 
 

Operatorlar

Əvvəlki paraqrafda biz mənimsətmə operatoru ilə tanış olduq, bu paraqrafda isə şərt(if, switch) və dövr (for, while, do while) operatorları ilə tanış olacayıq.

Şərt operatorları -- if , switch

Bildiyimiz kimi operator proqramda hansı əməliyyatın yerinə yetirilməli olduğunu bildirir. Bir çox hallarda bu və ya digər əməliyyatın yerinə yetirilməsi hansısa şərtdən asılı olur. Bu zaman if operatorundan istifadə olunur. 

if operatoru
if operatorunun sintakisisi aşağıdakı kimidir
   if (şərt)  {
     yerinə yetirilməli  əməliyatlar
                  }
  
     else    {
     digər əməliyatlar
                }
Qeyd edək ki, əgər cəmi bir əməliyyat yerinə yetirilirsə onda {} mötərizələrinə ehtiyac yoxdur. Izahı:
Əvvəlcə şərt yoxlanılır , əgər doğrudursa onda {} arasında olan əməliyatlar yerinə yetirilir əks halda else – dən sonrakı {} mötərizələri arasında olan əməliyatlar yerinə yetirilir.

Məsələn:
    int x;
    if (x<5)
                    printf("%d  5 -den kiçikdir",x);
    else
                    printf("%d  5 -den böyükdür",x);
nümunə proqram prog3_1.c :
  #include<stdio.h>
 
  int main(int argc, char *argv[]){
  
        int x;
 
        printf("zehmet olmasa x-in qiymetini daxil edin\n");
        scanf("%d",&x);
 
        if (x<5) 
                printf("%d 5 -den kichikdir\n",x);
        else   
                printf("%d 5 -den boyukdur\n",x);
 
      return 0;   
                 }
proqramı kompilyasiya edək və hər dəfə müxtəlif qiymətlər daxil etməklə bir neçə dəfə yerinə yetirək.
user@gnu_linux:~/progs/3$ gcc prog3_1.c   -o   prog3_1
user@gnu_linux:~/progs/3$ ./prog3_1
zehmet olmasa x-in qiymetini daxil edin
7
7 5 -den boyukdur
user@gnu_linux:~/progs/3$ ./prog3_1
zehmet olmasa x-in qiymetini daxil edin
3
3 5 -den kichikdir
user@gnu_linux:~/progs/3$ ./prog3_1
zehmet olmasa x-in qiymetini daxil edin
45
45 5 -den boyukdur
user@gnu_linux:~/progs/3$ 
 

Dövr operatorları

 for, while, do while 
Dövr operatorları müəyyən əməliyyatların bir neçə dəfə təkrar yerinə yetirilməsinə imkan verir. Bu operatorlardan proqramlaşdırmada çox geniş istifadə olunur. 

for operatoru

for operatorunun sintakisisi aşagıdakı kimidir:
  for (sayğacın ilkin qiyməti; dövrün başa çatma şərti; sayğacın dəyişmə qaydası){
                 əməliyyatlar; 
} nümunə proqram:
 
    /*   prog3_2.c         */
 
      int main(int argc, char *argv[]){
 
       int k;
  
     for (k=0;   k<10;   k=k+1)
        printf("salam dunya\n");
   
     return 0;
      }
programı kompilyasiya edib yerinə yetirək.
user@gnu_linux:~/progs$ 
user@gnu_linux:~/progs$ gcc -o prog3_2   prog3_2.c
user@gnu_linux:~/progs$ 
user@gnu_linux:~/progs$ ./prog3_2
salam dunya
salam dunya
salam dunya
salam dunya
salam dunya
salam dunya
salam dunya
salam dunya
salam dunya
salam dunya
user@gnu_linux:~/progs$ 
user@gnu_linux:~/progs$ 
indi isə proqramda for (k=0; k<10; k=k+1) sərtini for (k=5; k<10; k=k+1) ,for (k=0; k<3; k=k+1), for (k=0; k<10; k=k+7),
for (k=0; k<10; k=2) şərtləri ilə əvəz edib proqramı icra edək. Hər dəfə müxtəlif nəticələr alacağıq. Sonuncu halda isə ekranda Salam dunya ifadəsi sonsuz çap olunacaq(proqramın icrasını dayandırmaq üçün CTRL + Z düyməsini daxil edin).
Birinci halı təhlil edək.
 for (k=0;   k<10;   k=k+1)
Sayğac olaraq k dəyişənindən istifadə olunur və ona başlanğıc qiymət olaraq 0 mənimsədilir. k=0; dövrün sona çatması şərti kimi k<10; göstərilib. Bu o deməkdir ki nə qədər ki k < 10 şərti ödənir dövr davam edəcək. Sayğacın qiymətinin dəyişmə qaydası kimi k=k+1 (! sonda ; simvolunun yoxluğuna diqqət yetirin) göstərilib, yəni dövr hər dəfə təkrar olunduqda sayğacın qiyməti 1 vahid artır.
Proses aşağıdakı şəkildə baş verir:
Əvvəlcə k dəyişəni 0 qiyməti alır. Sonra dərhal başa çatma şərti yoxlanılır. k<10 Şərt ödənir, belə ki, 0 < 10 ifadəsi doğru qiymət alır və avtomatik olaraq {} arasında olan əməliyatlar icra olunur. Bizim halda cəmi bir əməliyyatdan, printf("salam dunya\n"); 
istifadə etdiyimizə görə onu {} mötərəzələri arasına almadıq. Daha sonra növbə sayğacın qiymətinin dəyişməsinə gəlir. 
Baxdığımız hal üçün ( k -nın qiyməti 0 olan hal ) k-nın yeni qiyməti 1 olur. Dərhal şərt yoxlanılır. 1 < 10 . Hələki hər şey qaydasında, əməliyyatlar yerinə yetirilir, sayğacın qiyməti dəyişdirilir və hər dəfə 1 vahid artaraq 2,3, ... , 9 qiymətlərini alır. k - nın bütün bu qiymətlərində k<10 şərti ödənir və əməliyyatlar( printf("salam dunya\n");) yerinə yetirilir. Növbəti qiymət isə 10 – dur. Bu halda isə artıq 10 < 10 şərti üdənmir və for operatoru sona çatır.

while opratoru

for operatorunda biz sayğac təyin etdik, dövrün başa çatması şərtini və sayğacın dəyişmə qaydasını verdik. Bu zaman biz dövrün neçə dəfə təkrar olunacağını dəqiq bilirik. Bəzən isə elə olur ki, dövrün başa çatması şərtinin nə vaxt ödənəcəyi əvvəlcədən bilinmir. Bu zaman while operatorundan istifadə olunur. while operatorunun sisntaksisi aşağıdakı kimidr.
 
      while(şərt){
        əməliyatlar;                
                               }
   
nümunə:
 
        char x;
         x='b';
      while (x!='a'){
            printf("salam dunya\n");
            printf("  yeni  simvol daxil edin\n");
            scanf("%c",&x); 
                             }
   
Bu koddan proq3_3.c -də istifadə edilib. Bu proqramı kompilyasiya edib yerinə yetirək. Göründüyü kimi dövr biz a simvolunu daxil edənə kimi davam edəcək.
while dövr operatorunun digər nadir hallarda istifadə olunan forması do while operatorudur. do while operatorunun sintaksisi belədir:
    
     do{
     əməliyyatlar;
       } while(şərt);
bu operatorun while opratorundan yeganə fərqi odur ki, bu halda şərtin nə zaman ödənməsindən asılı olmayaraq əməliyyatlar ən azı 1 dəfə yerinə yetiriləcək.

switch operatoru

Əgər müəyyən halda proqramın icra istiqaməti bir neçə şərtdən asılıdırsa bu zaman if opratoru ilə bu şərtlərin mürəkkəb konfiqurasiyasından istifadə etmək əvəzinə switch operatorundan istifadə edirlər.
switch operatorunun sintaksisi aşağıdakı kimidir:
   switch ( dəyişən ) {
case qiymət1:
  yerinə yetirilməli proqram hissəsi /*  əgər dəyişənin qiyməti == qiymət1 */
  break;
case qiymət2:
  yerinə yetirilməli proqram hissəsi /*  əgər dəyişənin qiyməti == qiymət2  */
  break;
...
default:
yerinə yetirilməli proqram hissəsi    /*  yuxarıdakı şərtlərin heç biri ödənmədikdə  */
  break;
}
switch opratoru dəyişənin qiymətini yuxarıdan aşağı case ifadəsinin qarşısında dayanan qiymətlə yoxlayır və bərabər olarsa onda iki nöqtə : - dən sonra gələn bütün operatorları yerinə yetirir. Növbəti case ifadəsinə qədər. break rast gəlinən yerdə switch opratoru işini dayandırır və proqramda switch -dən sonra gələn oprator yerinə yetirilir. 
switch operatoru ilə bağlı mühüm məqamlardan biri də case ifadələrində qiymət kimi ancaq tam tipli dəyişənlərdən istifadə etmək olar (int) .
default seçimindən istifadə etmək vacib deyil. Əgər qiymətlərdən heç biri dəyişənə bərabər olmasa onda default:seçimində göstərilən operatorlar yerinə yetiriləcək.
nümunə proqram: prog3_4.c
      #include <stdio.h>  
int main(int argc, char *argv[]){
    int color = 0;
    printf("Her hansi reng sechin(qirmizi=1,yashil=2,qara=3):\n");
    scanf("%d",&color);  
    switch(color){
    case 1: printf("siz qirmizi rengi seçdiniz\n");
        break;
    case 2:printf("siz yaşıl rengi seçdiniz\n");
        break;
    case 3:printf("siz qara rengi seçdiniz\n");
        break;
   default:printf("siz hech bir reng sechmediniz\n");
    }
        return 0;
}
Proqramı kompilyasiya edib yerinə yetirək.
user@gnu_linux:~/progs$ 
user@gnu_linux:~/progs$ gcc -o prog3_4 prog3_4.c
user@gnu_linux:~/progs$ 
user@gnu_linux:~/progs$ ./prog3_4
Her hansi reng sechin(qirmizi=1,yashil=2,qara=3):
2
siz yaşıl rengi seçdiniz
user@gnu_linux:~/progs$ 
user@gnu_linux:~/progs$ 
 
 
 

Ünvan dəyişənləri

Ünvan dəyişənləri proqramlaşdırmada çox geniş istifadə olunur. C dilində isə ünvan dəyişənləri şahmatda 2 topun oynadığı rolu oynayır. Vəzir rolu isə əlbəttdə funksiyalara məxsusdur. Bu imkandan hansı kombinasiyada istifadə etmək isə proqramçının təcrübəsinə bağlıdır. Ünvan dəyişənlərindən bir qayda olaraq təcrübəli proqramçılar daha çox istifadə edir. Yaranan fikir belədir ki, təcrübə nə qədər artarsa, proqramçının ünvan dəyişənlərindən istifadəsi daha çox olur.
Biz qeyd etdik ki, yerinə yetirdiyi işdən asılı olmayaraq proqram sadəcə və sadəcə hansısa məlumatları müəyyən mənbədən qəbul edir, yadda saxlayır, ötürür, dəyişdirir. İndiyə kimi baxdığımız proqramlarda istifadə etdiyimiz adi dəyişənlər vastəsilə bu işin öhdəsindən asanlıqla gəlmək mümkündür(qəbul,saxlama, ...). Bəs onda ünvan dəyişənləri nəyə lazımdır?
Biz bildiyimiz adi dəyişənlər qeyd etdiyimiz işlərin öhdəsindən həqiqətən də əla gəlirlər. Məsələn əgər biz yaddaşda 4 bayt yer ayırıb, bu yerə 155 ədədini yerləşdirmək istəyiriksə onda int x; x=155; operatorlarından istifadə edərik. Lakin bu dəyişənlərin böyük çatışmayan bir cəhəti var. Bu cəhət onların statik olmalarıdır. Yəni əgər yaddaşda hansısa məqsəd üçün yer ayırmaq tələb olunursa bu yalnız proqramın icraya başladığı zaman ola bilər. Proqramda elan etdiyimiz bütün dəyişənlər üçün proqram icraya başladığı zaman yaddaşda yer ayrılır və bu yaddaş sahəsi proqramın icrasına verilir. Proqram bu sahəyə istənilən məlumatları yaza, dəyişə, ... bilər.
Bəs birdən proqram yerinə yetirilərkən bizim əlavə yaddaşa ehtiyacımız oldu? Ya da, tutaq ki, biz proqramda 100 000 dənə int tipli dəyişəndən istifadə etmişik. Bu təqribən 1Mb -ta yaxın yaddaş deməkdir (Qeyd edək ki, bu qədər yaddaş RAM-da ayrılır, Hard diskdə yox. Ona görə 1 Mb yaddaş çox qiymətlidir). Proqramın icrası davam edir lakin, bu dəyişənlərə daha müraciət etməyəcəyik. Bu dəyişənlər həmi sahəni boş-boşuna tutur. Biz bu sahədən o dəyişənləri silib həmin yaddaş sahəsini yenidən proqramın istifadəsinə verə bilərikmi? İndi təsəvvür edin ki, int tipli dəyişənlər yox, özümüz tərtib etdiyimiz 100 baytlıq struct tipli 1000 000 dəyişəndən istifadə etmişik və bizə artıq lazım deyil. 100 000 000 bayt yaddaş proqram başa çatana kimi yaddaşda yer tutacaq, bu yerə həmin struct tipli dəyişənlərdən başqa dəyişənlər yerləşdirə bilmərik. Bu cür israfçılıqıa 2 proqram işləsə kompüterin bütün yaddaşı tutular və 3-cü proqramı yükləmək üçün biz bu proqramlardan birini söndürməli olarıq.
Ünvan tipli dəyişənlər dinamik dəyişənlərdir. Yəni proqramın icrası boyu istənilən vaxt onları yaradıb, istifadə edə bilərik. İstədiyimiz vaxtda da azad edə bilərik. Beləliklə də, onların tutduğu sahəni yenidən proqrama qaytara bilərik.
Lakin ünvan dəyişənlərinin özəllikləri sadəcə bununla bitmir. Adında göründüyü kimi ünvan dəyişənləri özlərində qiymət olaraq yadaşın müəyyən sahəsinin ünvanını saxlayır, həmin sahəyə istinad edir. Bu isə proqramçıya yaddaşla güclü manipulyasiya imkanı verir. Bu cəhətə görə istifadəçi proqramlarının tərtibi üçün nəzərdə tutulmuş bir çox proqramlaşdırma dilləri, o cümlədən JAVA və PHP təhlükəsizlik məsələlərinə görə(ünvan dəyişənlərinin qiymətini dəyişməklə başqa istifadəçilərə məxsus məlumatlar yerləşdirilmiş yaddaş sahəsinə müraciət etmək olar) göstəricilərdən istifadə etməyə icazə vermir.
Bundan əlavə ünvan dəyişənləri öz tiplarindən olan ünvan dəyişənlərinə mənimsədilə bilər. Bu imkandan əlaqələnmiş siyahıların yaradılmasında geniş istifadə edirlər. Əlaqələnmiş siyahılarla 8-ci paraqrafda məşğul olacağıq. Qeyd edək ki, kompüterdə ötürülən və qəbul olunan məlumatların böyük hissəsi(bir proqramdan digərinə, driverdən istifadəçi proqramına, TCP səviyyəsindən İP səviyyəsinə v.s. ) məhs əlaqələnmiş siyahılarla mümkün olur.
Ünvan dəyişənlərindən istifadə edən sadə proqrama baxaq(prg_4_1.c).
        
 
        #include <stdio.h>
 
        int main(int argc, char *argv[]){
        
               int x;
               int *y;                      
               x=5;
               y=&x;                       
               printf("x-in qiymeti = %d, x-in unvani = %p\n",x,y);
               return 0;      
        }
yerinə yetirək:
user@gnu_linux:~/prg# 
user@gnu_linux:~/prg# gcc prog_4_1.c -o prog_4_1
user@gnu_linux:~/prg# 
user@gnu_linux:~/prg# ./prog_4_1
x-in qiymeti = 5, x-in unvani = 0xbfcdae50
user@gnu_linux:~/prg# 
user@gnu_linux:~/prg# 
Izah:
Ünvan dəyişəni elan etmək üçün adi qaydada etdiyimiz kimi dəyişən elan edirik, lakin dəyişənin əvvəlinə * simvolunu artırırıq.
int x; adi dəyişən elan edirik. int *y; int tipli y ünvan dəyişənin elan edirik.
               int x;   int *y;

y=&x; burada biz y-ə x dəyişəninin yaddaşdakı ünvanını mənimsədirik. x dəyişəninin yaddaşdakı ünvanını təyin etmək üçün biz & operatorundan istifadə edirik.
                 y=&x;

 
Ünvan dəyişənləri elan etdik və onlara qiymət mənimsədə bildik. Növbəti məsələ ünvan dəyişənlərinin ünvanladığı yaddaş sahəsindən istifadə etmək məsələsidir.
Ünvan dəyişənlərinin ünvanladığı yaddaş sahəsinə müaciət etmək üçün dəyişəni elan edərkən istifadə etdiyimiz * operatorundan istifadə edirik. nümunə proqrama baxaq(prg_4_2.c).
        
 
        #include <stdio.h>
 
        int main(int argc, char *argv[]){
 
        int x;
        int *y;                         /* tam tipli unvan deyisheni*/       
        x=5;
        printf("x-in qiymeti = %d\n",x);
        y=&x;                         /* & unvan operatorudur */
        *y=155;
        printf("y-in qiymeti = %d\n",*y);      /* y x-in yaddshina unvanlandigindan(y=&x)
                                               *y – I deyismek  birbasha x-i deyishdirir.
                                               Bunu yoxlamaq uchun printf -den istifade edirik */
        printf("x-in qiymeti = %d\n",*x);
        return 0;      
        }
yerinə yetirək
user@gnu_linux:~/prg# 
user@gnu_linux:~/prg# gcc prog_4_2.c -o prog_4_2
user@gnu_linux:~/prg# 
user@gnu_linux:~/prg# ./prog_4_2
x-in qiymeti = 5
y-in qiymeti = 155
x-in qiymeti = 155
user@gnu_linux:~/prg# 
user@gnu_linux:~/prg# 
Beləliklə biz ünvan dəyişənlərinin unvanlandığı yaddaş sahəsindən istifadə edə bilirik. İdi isə ünvan dəyişənləri ilə bağlı sonuncu və ən maraqlı məqam. Dinamik yaradılma və yaddaşdan silmə.
prg_4_3.c
               
        #include <stdio.h>
        #include <stdlib.h>
 
        int main(int argc, char *argv[]){
 
        int x;
        int *y;                         /* tam tipli unvan deyisheni*/       
        x=5;
        y=(int *)malloc(sizeof(int));   /* dinamik yaradilma */
        *y=176;
        printf("y-in qiymeti = %d,*y);
        free(y);                        /* y -e ayrilan yaddash sahesini y-den azad edir 
                                               ve bu sahede olan butun melumat silinir*/
        return 0;      
        }
yerinə yetirək
user@gnu_linux:~/prg#
user@gnu_linux:~/prg#gcc prog_4_3.c -o prog_4_3
user@gnu_linux:~/prg#
user@gnu_linux:~/prg#
user@gnu_linux:~/prg#./prog_4_3
y-in qiymeti = 176
user@gnu_linux:~/prg#
user@gnu_linux:~/prg#
 
 
 
 
 
 

Funksiyalar

C dilinin proqramçılar arasında ən məşhur dil olmasında rol oynayan 2 ən güclü imkanından biri funksiyalardır. Digəri isə yaddaş dəyişənləridir. Funksiyalar proqramın her-hansı bir hissesine ad vermekle bu hisseye proqramın istənilən yerindən, digər funksiyalardan və eləcə də digər proqramlardan nüraciət etməyə imkan verir. Bu hissəyə funksiyanın mətni, bu hissəyə verilən ada isə funksiyanın adı deyilir. Nümunə proqrama baxmazdan əvvəl funksiyalarla bağlı bir neçə məqama nəzər salaq. 
Ola bilsin ki, funksiyanın mətni yerinə yetirildikdən sonra hansısa bir nəticə alınsın və ya bu mətn hissəsi hansısa əməliyyatlar yerinə yetirsin və heç bir nəticə qaytarmasın(void). Digər bir məqam odur odur ki, funksiya mətnində istifadə olunan bəzi dəyişələrin qiyməti funksiya çağırılarkən ona parametr kimi ötürülsün və ya funksiya çağırılarkən ona heç bir parametr ötürülməsin(void).
Indi isə gəlin konkret proqram nümunələrində funksiyalar, onların tərtibi, çağırılma qaydası ilə tanış olaq və bu məqamların hər birini ayrı-ayrı təhlil edək.
proq_5_1.c
        #include <stdio.h>
 
        int main(int argc, char *argv[]){
        
        printf("Setirlerin ekrana verilmesi\n");
 
        printf("Setir 1\n");
        printf("bu gun yagish yagir\n");
        printf("Bu gun kulek esir\n");
        
        return 0;
        }
programı yerinə yetirək.
user@gnu_linux:~/prg# 
user@gnu_linux:~/prg# gcc prog_5_1.c -o prog_5_1
user@gnu_linux:~/prg# 
user@gnu_linux:~/prg# ./prog_5_1
Setirlerin ekrana verilmesi
Setir 1
bu gun yagish yagir
Bu gun kulek esir
user@gnu_linux:~/prg# 
proqram bizə tam aydındır. Indi isə gəlin
printf("Setir 1\n");
printf("bu gun yagish yagir\n");
printf("Bu gun kulek esir\n");
proqram hissəsindən ibarət cap_et funksiyası yaradaq və proqramımızda bu funksiyadan istifadə edək.
prog_5_2.c
        #include<stdio.h>
 
        void cap_et(void);
 
        int main(int argc, char *argv[]){
        cap_et();
        return 0;
        }
 
        /*-----------------------cap_et funksiyasi --------------------------------*/
 
        void cap_et(void)
        {
        printf("Setirlerin ekrana verilmesi\n");
        printf("Setir 1\n");
        printf("bu gun yagish yagir\n");
        printf("Bu gun kulek esir\n");
        }
 
proqramı yerinə yetirək.
user@gnu_linux:~/prg#
user@gnu_linux:~/prg#gcc prog_5_2.c -o prog_5_2
user@gnu_linux:~/prg#
user@gnu_linux:~/prg#./prog_5_2
Setirlerin ekrana verilmesi
Setir 1
bu gun yagish yagir
Bu gun kulek esir
user@gnu_linux:~/prg#
İzahı
proqramda ilk #include<stdio.h> sətrindən sonra gələn void cap_et(void); sətridir. Bu sətir funksiyanın elanı sətridir. Hər bir funksiyanı proqramda istifadə etməzdən əvvəl onu elan etmək lazımdır. Bu sətir kompilyatora funksiyanın adı, qaytaracağı nəticənin tipi və ona ötürüləcək parametrlər haqqında məlumat verir. Bu sətirdə birinci yerdə gələn söz funksiyanın qaytaracağı nəticənin tipini bildirir.
Əgər funksiya heç bir nəticə qaytarmırsa onda bu yerdə void yazılır , baxdığımız haldakı kimi. Funksiyanın tipindən sonra funksiyanın adı qeyd olunur – cap_et. Addan sonra () mötərəzələri arasında funksiyanın parametrləri haqda məlumat qeyd olunur. Əgər funksiya heç bir parametr qəbul etmirsə burada void yazırıq. 
prog_5_3.c -ni yerinə yetirin və onu başa düşməyə çalışın. 
prog_5_3.c
        #include<stdio.h>
 
        void cap_et(void);
 
        int main(int argc, char *argv[]){
        
        int i;
        for(i=0; i<5; ++i)
        cap_et();
        
        return 0;
        }
 
        /*-----------------------cap_et funksiyasi --------------------------------*/
 
        void cap_et(void)
        {
        printf("Setirlerin ekrana verilmesi\n");
        printf("Setir 1\n");
        printf("bu gun yagish yagir\n");
        printf("Bu gun kulek esir\n");
        } 
Digər proqrama baxaq.
prog_5_4.c
        #include<stdio.h>
 
        int sahe(int,int);
 
        int main(int argc, char *argv[])
        {
        int x,y,z;
        printf("Duzbucaqlinin enini daxil edin\n"); 
        scanf("%d",&x);
        printf("Duzbucaqlinin uzunlugunu daxil edin\n");
        scanf("%d",&y);
 
        z=sahe(x,y);
               
        printf("Duzbucaqlinin sahesi =%d\n",z);       
 
        return 0;
 
        }
  
        int sahe(int t1, int t2)
        {
        int sh;
        sh=t1*t2;
        return sh;
        } 
proqramı yerinə yetirək
user@gnu_linux:~/prg# 
user@gnu_linux:~/prg# gcc prog_5_4.c -o prog_5_4
user@gnu_linux:~/prg# 
user@gnu_linux:~/prg# ./prog_5_4
Duzbucaqlinin enini daxil edin
6
Duzbucaqlinin uzunlugunu daxil edin
8
Duzbucaqlinin sahesi =48
user@gnu_linux:~/prg# 
user@gnu_linux:~/prg# 
Izahı
Burada biz yeni sahe funksiyası yaradırıq hansı ki int tipli 2 parametr qebul edir və nəticə olaraq int tipli ədəd (düzbucaqlının sahəsini ) qaytarır. int sahe(int,int);
Mötərizələr arasında funksiyaya ötürülən parametrlərin tipləri sadalanır, vergüllə ayrılaraq. Qeyd edək bu zaman her parametrin tipinin qarşısında ad da vere bilerik, kompilyator bunu nəzərə almır, o ancaq tipə əhəmiyyət verir. Yəni əgər yuxarıdakı proqramda sahə funksiyasını elan edərkən biz 
int sahe(int,int); sətri əvəzinə int sahe(int teref2,int teref2); də yaza bilərdik. Sadəcə özümüzə və bu proqrama daha sonra baxan proqramçılara mılumat məqsədilə. Əgər proqramda bir funksiyada istifadə olunursa bunun elə də əhəmiyyəti yoxdur, lakin proqramda 1000-lə funksiyadan istifadə olunduqda (məsələn nüvənin yaddaşın idarə olunması hissəsi və ya şəbəkə hissəsi) bunun əhəmiyyəti hiss olunur.
Biz proqramda sahe funksiyasını 
z=sahe(x,y); sətrində çağırırıq. x  y dəyişənlərinin qiymətləri scanf funksiyası vasitəsilə istifadəçidən alınır və sahə funksiyasına parametr kimi ötürülür. sahe funksiyasında bu 2 dəyişənin hasili hesablanır və qaytarılan nəticə z dəyişəninə mənimsədilir.
sahe funksiyasının mətnində biz int tipli sh dəyişəni elan edirik və parametrlərin hasilini hesablayaraq bu dəyişənə mənimsədirik. Daha sonra return əmri vasitəsilə funksiyanın proqramda çağırılma nöqtəsinə( z=sahe(x,y);) qaytarılacaq nəticə göstərilir. return əmri funksiyasiyanın icrasını başa çatdırır və proqramın icrası funksiyanın çağrılma yerindən davam edir. 
Biz burada 
x,y dəyişələri daxil etdik və onlara scanf vasitasilə istifadəçinin daxil etdiyi qiymətləri mənimsətdik, daha sonra sahə funksiyasını çağırdıq. x,y -in qiymətlərini bu funksiyaya parametr kimi ötürdük. z=sahe(x,y); bu yerdə proqramın icrası sahə funksiyasına ötürüldü və x,y -in qiymətlərindən istifadə olunaraq hsablama aparıldı, nəticə zdəyişəninə mənimsədildi və proqramın icrası davam etdi.
Sual? Tutaq ki istifadəçi
 5  7 ədədlərini daxil edib.
x=5; y=7;. sahə funkdiyası yerinə yetirildikdən sonra x  y -in qiyməti dəyişmədiki? Yəni funksiyanın mətnində ona ötürülən arqumentlərə edilən dəyişiklik funksiya icra olunduqdan sonra öz qüvvəsini saxlayırmı? Bunu yoxlamaq üçün printf funksiyasından istifadə edək.
prog_5_5.c
        #include<stdio.h>
 
        int sahe(int,int);
 
        int main(int argc, char *argv[])
        {
        int x,y,z;
        printf("Duzbucaqlinin enini daxil edin\n"); 
        scanf("%d",&x);
        printf("Duzbucaqlinin uzunlugunu daxil edin\n");
        scanf("%d",&y);
 
        z=sahe(x,y);
               
        printf("Duzbucaqlinin sahesi =%d\n",z);       
        printf("x=%d, y= %d\n",x,y);
        return 0;
 
        }
  
        int sahe(int t1, int t2)
        {
        int sh;
        sh=t1*t2;
        return sh;
        } 
proqramı yerinə yetirək
user@gnu_linux:~/prg# 
user@gnu_linux:~/prg# gcc prog_5_5.c -o prog_5_5
user@gnu_linux:~/prg# 
user@gnu_linux:~/prg# ./prog_5_5
Duzbucaqlinin enini daxil edin
6
Duzbucaqlinin uzunlugunu daxil edin
8
Duzbucaqlinin sahesi =48
x=6, y= 8
user@gnu_linux:~/prg# 
user@gnu_linux:~/prg#
Qeyd edək ki bu halda biz sahə funksiyasında ona ötürülən parametrlərin qiymətlərini dəyişmədik. İdi gəlin digər proqramda sahə funksiyasında bu qiymətləri dəyişək və nəticəni yenidən yoxlayaq.
proq_5_6.c
        #include<stdio.h>
 
        int sahe(int,int);
 
        int main(int argc, char *argv[])
        {
        int x,y,z;
        printf("Duzbucaqlinin enini daxil edin\n"); 
        scanf("%d",&x);
        printf("Duzbucaqlinin uzunlugunu daxil edin\n");
        scanf("%d",&y);
 
        z=sahe(x,y);
               
        printf("Duzbucaqlinin sahesi =%d\n",z);       
        printf("x=%d, y= %d\n",x,y);
        return 0;
 
        }
  
        int sahe(int t1, int t2)
        {
        int sh;
        sh=t1*t2;
        /* funksiyaya oturulen arqumentlerin(t1,t2) qiymtlerini
        burada deyishirik */
        t1=1; t2=2;
        return sh;
        } 
Gördüyümüz kimi sahə funksiyasında biz sahəni hesabladıqdan sonra ona ötürülən parametrlərin qiymətlərini dəyişdirdik.
Nəticəni yoxlayaq.
user@gnu_linux:~/prg# 
user@gnu_linux:~/prg# gcc prog_5_6.c -o prog_5_6
user@gnu_linux:~/prg# 
user@gnu_linux:~/prg# ./prog_5_6
Duzbucaqlinin enini daxil edin
4
Duzbucaqlinin uzunlugunu daxil edin
7
Duzbucaqlinin sahesi =28
x=4, y= 7
user@gnu_linux:~/prg# 
user@gnu_linux:~/prg# 
Gördüyümüz kimi funksiyanın daxilində ona ötürülən parametrlərin qiymətlərinin dəyişdirilməsi funksiya icra olduqdan sonra öz qüvvəsini itirdi, x  y- in qiymətləri olduğu kimi qaldı. Dəyişənlərin funksiyaya belə ötürülməsinə deyirlər qiymətə görə ötürmə.
Bunun səbəbi odur ki, funksiya çağırılarkən parametr kimi ona əslində 
x  y ötürülmür, bu dəyişənlərin surətləri yaradılır və funksiyaya ötürülür. Funksiyanın mətnində bu dəyişənlər üzərində aparılan bütün dəyişikliklər əslində onların surətləri üzərində aparılır.
Dəyişənlərin funksiyaya bu cür ötürülməsinin müsbət və mənfi tərəfləri var. Müsbət hal odur ki qiymətə görə ötürülmə zamanı bütün əməliyyatlar dəyişənlərin surətləri üzərində aparıldığından dəyişənlərin qiymətləri hər cür dəyişiklikdən qorunmuş olur. 
Mənfi hal odur ki, bu zaman dəyişənlərin surətləri yaradılır və buna proqramçı üçün ən qiymətli resurslar – əməli yaddaş və zaman sərf olunur.
Parametrlərin funksiyaya ötürülməsinin digər variantı da ünvana görə ötürülmədir. Bu zaman, dəyişənlərin surətləri yaradılmır və funksiyaya dəyişənlərin ünvanları ötürülür. Nəticədə funksiyada dəyişənlər üzərində aparılan bütün əməliyyatlar məhz onların əsli üzərində aparılmış olur. 
Parametrlərin ünvana görə ötürülməsi 
prog_5_7.c -ni yerinə yetirək
        #include<stdio.h>
 
        int sahe(int *,int *);
 
        int main(int argc, char *argv[])
        {
        int x,y,z;
        printf("Duzbucaqlinin enini daxil edin\n"); 
        scanf("%d",&x);
        printf("Duzbucaqlinin uzunlugunu daxil edin\n");
        scanf("%d",&y);
 
        z=sahe(&x,&y);
               
        printf("Duzbucaqlinin sahesi =%d\n",z);       
        printf("x=%d, y= %d\n",x,y);
        return 0;
 
        }
  
        int sahe(int  *t1, int *t2)
        {
        int sh;
        sh=(*t1)*(*t2);
        *t1=1; *t2=2;
        return sh;
        } 
 
proqramı yerinə yetirək
user@gnu_linux:~/prg# gcc prog_5_7.c -o prog_5_7
user@gnu_linux:~/prg# 
user@gnu_linux:~/prg# ./prog_5_7
Duzbucaqlinin enini daxil edin
3
Duzbucaqlinin uzunlugunu daxil edin
8
Duzbucaqlinin sahesi =24
x=1, y=2
user@gnu_linux:~/prg# 
Izahı (to do: ahmed bura izah yaz)
Gördüyümüz kimi funksiayda ona ötürülən parametrlər üzərində edilən dəyişiklik öz qüvvəsini saxladı. Izahı:
int sahe(int *,int *); sətri ilə sahə funksiyası elan edilir. Bu sətrdə göstərilir ki, sahə funksiyası nəticə olaraqint tipli qiymət qaytarır. Bizim üçün maraqlı () mötərizələri arasında onaldı hissədir. Qiymətə görə ötürmə zamanı biz yalnız tipi göstərirdik. Ünavana görə ötürmə zamanı isə sadəcə tipdən sonra * simvolu yazırıq. Sahə funksiyasına proqramda z=sahe(&x,&y); sətrində müraciət edirik. Burada & operatoru vastəsilə sahə funksiyasına parametr kimix  y dəyişənlərinin yaddaşdakı ünvanları ötürülür.

Cərgələr

Biz indiyə kimi adi dəyişənlər və ünvan dəyişələri ilə tanış olduq. Bu dəyişənlər istifadə üçün çox rahatdır və çox geniş tətbiq olunur. misal üçün 2 tam ədəd elan etmək istəyiriksə onda int ed1; ed2; yazırıq.
Lakin çox vaxt elə olur ki, proqramlda eyni tipli 
100 000 dəyişənə ehtiyac olur . Əgər bu halda biz hər bir dəyişən üçün bir ad təyin etsək onda proqramda müxtəlif adlı 100 000 dəyişən elan etməliyik. Bu isə praktik olaraq qeyri mümkündür. Belə hallarda cərgələrdən və əlaqələnmiş siyahılardan istifadə edirlər.
Cərgələr eyni tipdən olan istənilən sayda elementə eyni adla müraciət etməyə imkan verir. Cərgə (cərgə dəyişəni ) elan etmək üçün aşağıdakı sintaksisdən istifadə edirlər. 
tip cergenin_adi [ elementlerin_sayi ] ;
məsələn 
int x[5]; biz burada int tipli 6 elementli x cərgəsi elan etdik.
Bu cərgənin hər bir elementinə 
x[index] kimi müraciət edə bilərik. Burada index 0-dan 5-ə kimi (5 -də daxil olmaqla) qiymət alır. 
Belə bir proqrama baxaq. 
int tipli 5 elementdən ibarət cərgə yaradaq. Bu cərgənin elementinə müxtəlif qiymətlər mənimsədək. Daha sonra bu cərgənin elementlərinin ədədi ortasını (cəmin saya nisbəti) tapaq.
proqram aşağıdakı kimi olar:
prog_6_1.c
        #include <stdio.h>
 
        int main(){
 
        int x[5];
        int i,s;
 
        x[0]=1; x[1]=5; x[2]=7;
        x[3]=45; x[4]=22;
        s=0;
 
        for (i=0; i>5; ++i)
        s=s+x[i];
 
        printf("x cergesinin elementleri ashagidakilardir\n");
        for(i=0; i>5; ++i)
        
        printf("%d\n",x[i]);
        printf("x-in elementlerinin ededi ortasi %d\n", s/5);
        
        return 0;
        }
        
proqramı yerinə yetirək
user@gnu_linux:~/prg# gcc prog_6_1.c -o prog_6_1
user@gnu_linux:~/prg# 
user@gnu_linux:~/prg# ./prog_6_1
x cergesinin elementleri ashagidakilardir
1
5
7
45
22
x-in elementlerinin ededi ortasi 16
user@gnu_linux:~/prg# 
user@gnu_linux:~/prg#
Cərgələr ilə ünvan dəyişənlərinin əlaqəsi.

Tutaq ki, proqramda aşağıdakı kimi elan vermişik. 
int y, x[4],*z; Bu zaman yaddaşda nəyin baş verməsinə nəzər salaq.

Cərgənin adı əslində ünvan dəyişənidir. Fərq yalnız ondadır ki, unvan dəyişənini (z) yaddaşda istənilən yerə unvanlamaq olar, cərgənin adı (x) isə ancaq bir yerə (yaddaşda [4] -ün başlanğıc addresinə) ünvanlanır(shəkil 1). 
Əgər 
z-tə y-in ünvanını mənimsətmək istəyiriksə onda ünvan operatorundan (&) istifadə edirik.
z=&y; 

Əgər z-tə cərgənin (x) ünvanını mənimsətmək istəsək onda unvan operatorundan istifadə etmirik. z=x; Başqa sözlə C kompilyatoru cərgənin adı ilə ünvan dəyişəninə "eyni gözlə" baxır. 
Lakin biz 
x=z; yaza bilmərik, çünki x-in qiyməti dəyişməzdir. z-ti x-ə mənimsətdikdən sonra biz x-in istənilən elementinə z-lə müraciət edə bilərik. Tutaq ki, x cərgəsinin ilk elementini (x[0]) z-lə çap etmək istəyirik.
Kod belə olar:
          z=x; printf(*z);

          şəkil_6_1.
Biz indi z-in qiymətini artırıb , azaltmaqla onun ünvanladığı yeri x cərgəsi boyu sürüşdürə bilərik. Misal üçün z-in qiymətini 1 vahid artıraq z++; bu zaman z artıq x[1]-ə ünvanlayacaq. 
          z=x; printf(*z); z++;

          şəkil_6_2.
Proqram icra etməyin vaxtıdır.
prog_6_2.c
        #include <stdio.h>
        
        int main(){
        int x[5],*y;
        int i,s;
        x[0]=1; x[1]=5; x[2]=7;
        x[3]=45; x[4]=22;
        s=0;
        y=x;
        for (i=0; i<5; ++i){
        s=s+(*y);
        y++;               }
        printf("x cergesinin elementleri ashagidakilardir\n");
        y=x;
        for(i=0; i<5; ++i){
        printf("%d\n",*y);
        y++;}
        printf("x-in elementlerinin ededi ortasi %d\n", s/5);
        return 0;
        }
        
proqramı yerinə yetirək
user@gnu_linux:~/prg# gcc prog_6_2.c -o prog_6_2
user@gnu_linux:~/prg# 
user@gnu_linux:~/prg# ./prog_6_2
x cergesinin elementleri ashagidakilardir
1
5
7
45
22
x-in elementlerinin ededi ortasi 16
user@gnu_linux:~/prg# 
Izahı
#include <stdio.h> 
stdio.h faylını proqrama əlavə edirik. printf v.s. funksiyalardan istifadə edə bilmək üçün.
int main(){
int x[5],*y;
main proqramın əsas funksiyasını elan edirik.
int tipindən olan x cərgəsi və y ünvan dəyişəni elan edirik.
x[0]=1; x[1]=5; x[2]=7;
x[3]=45; x[4]=22;
s=0;
x cərgəsinin elementlərinə qiymətlər mənimsədirik.
s cəminə 0 qiyməti mənimsədirik.
y=x;
y-ə x-in başlanğıc unvanını mənimsədirik. şəkil_6_1.
for (i=0; i<5; ++i){
dövr elan edirik
s=s+(*y);
s -ə 0 qiyməti mənimsətmişik. y x -in 1 -ci elementinə istinad edir, deməli *y x-in ilk elementinin qiymətinə bərabərdir.
y++; }
y -i x -in növbəti elementi üzərinə sürüşdürürük. şəkil_6_2.
printf("x cergesinin elementleri ashagidakilardir\n");
ekrana setir çap edirik.
y=x;
for dövrünün sonunda y x-in sonuncu elementi üzərinə istinad edir. y -i yenidən x-in ilk elementi üzərinə sürüşdürürük.
for(i=0; i<5; ++i){
dövr elan edirik
printf("%d\n",*y);
y -in istinad etdityi elementi çapa veririk.
y++;}
y -i x -in növbəti elementi üzərinə sürüşdürürük. şəkil_6_2.
printf("x-in elementlerinin ededi ortasi %d\n", s/5);
return 0;
}
ədədi ortanı çap edib proqramı bitiririk.


Sətirlər

Sətirlər cərgələrin xüsusi halıdır. Cərgə elementlərinin tipinin char olduğu hal. char tipi simvol tipi adlanır. Başqa sözlə sətirlər simvollar cərgəsidir. İlk baxışda sətirlər elə də əhəmiyyət kəsb etmir və onlarla işləmək üçün bir neçə standart funksiya təyin olunur. 
Sətirlərin tətbiq sahəsi çox genişdir, həm nüvədə, həm də istifadəçi proqramlaşdırmasında sətirlərdən çox geniş istifadə olunur.
Misal üçün çat proqramında daxil etdiyimiz her-hansı sətir internet şəbəkəsinə qoşulmuş digər komputerdə yerinə yetirilən çat proqramına ötürülən zaman bir neçə dəfə bir yerdən(yaddaşda) digər yere köçürülür.
İstifadəçinin daxil etdiyi parolu yoxlamaq üçün biz proqramda sətirlərin müqaisəsi funksiyalarından istifadə edirik v.s. Sətirlərlə işləyən zaman diqqət verilməsi lazım gələn məsələlərdən biri də sətirin sonu məsələsidir. Sətirlərin sonunu bildirmək üçün '\0' simvolundan istifadə olunur. Sətir funksiyaları bu simvola rast gəldikdə sətrin yerdə qalan hissəsini inkar edirlər.
prog_7_1.c
        #include <stdio.h>
        #include <string.h>
        
        int main(int argc, char *argv[]){
        
        char  set[12];   /*12 elementden ibaret setir elan edirik*/
        
        strcpy(set,"Azerbaycan");    
        
        printf("%s\n",set);
        
        return 0;      
               
        }
        
proqramı yerinə yetirək
user@gnu_linux:~/prg# gcc prog_7_1.c -o prog_7_1
user@gnu_linux:~/prg# 
user@gnu_linux:~/prg# ./prog_7_1
Azerbaycan
user@gnu_linux:~/prg# 
Izahı
Burada biz 12 elementden ibaret set adlı setir elan edirik. Daha sonra strcpy funksiyası vasitəsilə set sətrinə"Azerbaycan" qiymətini mənimsədirik. strcpy funksiyasi string.h faylinda təyin olduğundan #include <string.h> vasitəsiləstring.h faylini proqrama əlavə edirik. strcpy funksiyasının sintaksisi aşağıdakı kimidir. 
char * strcpy(char *s1, char *s2); 
strcpy funksiyası s1 sətrinə s2 sətrini mənimsədir. Sətirlərlə işləyən digər funksiyalara baxaq. strlen funksiyası.
int strlen(char *s); 
s sətrində olan elementlərin sayını qaytarır. '\0' simvolunu hesaba almır.
char * strncpy(char *s1, char *s2, int n); 
s2 sətrinin ilk n elementini s1-ə köçürür(s1-in əvvəlindən başlayaraq).
int strcmp(char *s1, char *s2); 
bu funksiyadan sətirlərin müqaisəsi üçün istifadə edirlər. Əgər s1 sətri s2 sətri ilə eynidirsə onda funksiya 0 qiymətini qaytarır, əgər s1-in elementlərinin sayı s2-den azdırsa onda <0 əks halda >0 qiymətini qaytarır.
char * strcat (char *s1, char *s2); 
bu funksiya s1-in sonuna s2-ni əlavə edir.


Strukt tiplər

İndiyə qədər biz dəyişən elan edərkən int, double, char, long kimi standart tiplərdən istifadə edirdirk. Əlbətdə bu tpliər çox əlverişlidir, lakin çox vaxt məsələnin şərtinə uyğun olaraq proqramçının özü yaratdığı tiplərdən istifadə etmək lazım gəlir.
Tutaq ki hər-hansı zavodun 
100 000 işçisi var. Bizdən tələb olunur ki, bu zavodun işçilərinin məlumatlar bazası proqramını yazaq. Hər bir işçi haqqında onun adı, soyadı, yaşı, maaşı, vəzifesi barədə məlumatlar qeyd edilməlidir. Bunun üçün yeni struct tipi təyin edək.
Yeni tip təyin etmək üçün sintaksis aşağıdakı kimidir.
  
 struct yeni_tipin_adı {
        tip  dey1;
        tip  dey2;
        tip  dey3;
               .
               .
        tip  deyn;             };
Məsələmizə uyğun təyin etməli olduğumuz yeni tip belə olar. Gəlin bu yeni yaradacağımız tipə ishci adını verək.
   struct  ishci  {
        int            yash;
        char           ad[12]; 
        char           soyad[20];
        char           vezife[20];
        double  maash;  };
Beləliklə biz yeni ishci tipi təyin etdik. Bu elandan sonra biz proqramımızda bu tipdən adi tiplər kimi dəyişənlər və ünvan dəyişənləri elan edə bilərik, lakin gərək tipin adından (ishici) əvvəl kompilyatora bu tipi bizim özümüz yaratdığımızı bildirmək üçün struct ifadəsini yerləşdirək.
Məsələn: 
struct ishci dey1, ishci1, *muhendis, yeni_ishciler[100]; 
yuxaridakı elanda biz
 ishci tipindən olan dey1  ishci1 dəyişənləri, muhendis unvan dəyişəni və 100 elementliyeni_ishciler cərgəsi yatardıq. 
100 000 ishci barəsində məlumat saxlamaq üçün biz yeni yaratdığımız ishci tipindən olan 100 000 elementli cərgədən istifadə edə bilərik.
struct ishci ishciler[100000];
İndi isə maraqlı məqam. Tutaq ki,
 int tipindən olan x dəyişənimiz var.
int x; Əgər biz bu dəyişənə 4 qiyməti mənimsətmək istəyiriksə x=4; yazırıq. Bəs strukt tipindən olan dəyişənlərə və ya oların təşkil onlunduqları ayrı-ayrı elementlərə necə qiymət mənimsədək? strukt tipinin elementlərinə müraciət etmək üçün ( . ) və ya ( -> ) operatorlarından istifadə olunur. Aşağıdakı kimi:
  
   struct ishci  reis;
    reis.yash = 50;
    strcpy(reis.ad,"Anar");  
... v.s.
Artıq strukt tipindən istifadə etməklə proqram tərtibinin vaxtı çatıb.
prog_8_1.c
        #include <stdio.h>
        #include <stdlib.h>
        #include <string.h>
        
        /* yeni_tip adli struct tipi yaradiriq*/
        
        struct yeni_tip{
        char ad[20];
        int  x; };
        
        int main(int argc, char *argv[]){
        
        /* struct yeni_tip -den dey adli deyishen elan edirik*/
        
        struct yeni_tip dey;
        
        dey.x=50;
        memset(dey.ad,0,20); /* memset (stdlib.h) 
                             ad -in butun baytlarina 0 qiymeti yaziriq.
                              setirlerle ishleyerken bunu etmek vacibdir.*/
        strcpy(dey.ad,"Ali");
        
        printf("%s,%d\n",dey.ad,dey.x);
        return 0;      
        }
        
proqramı yerinə yetirək
user@gnu_linux:~/prg# 
user@gnu_linux:~/prg# gcc prog_8_1.c -o prog_8_1
user@gnu_linux:~/prg# 
user@gnu_linux:~/prg# ./prog_8_1
Ali,50
user@gnu_linux:~/prg# 
user@gnu_linux:~/prg#
Strukut tipindən olan ünvan dəyişənləri
strukt tipindən aşağıdakı kimi ünvan dəyişəni təyin edək:
strukt ishci *muhendis;
Əgər biz strukt tipdən adi yox unvan dəyişəni təyin ediriksə onda strukt tipinin elementlərinə müraciət zamanı ( .) əvəzinə (->) istifadə edirik. misal üçün:
muhendis->yash=45; kimi. 
DIQQƏT! ÜNVAN DƏYİŞƏNLƏRİ ÜÇÜN YADDAŞDA YER AYIRMADAN ONLARIN ELEMENTLƏRİNƏ MÜRACİƏT ETMƏK OLMAZ. 
Paraqraf 4-dən bilir ki, hər hansı bir tipdən olan unvan dəyişəninə yaddaşda yer ayırmaq üçün
tip *dey; 
dey = (tip *) malloc (sizeof(tip));
sintaksisindən istifadə edirik.
Bu sintaksisə əsasən yuxarıda təyin etdiyimiz muhendis ünvan dəyişəninin elementlərinə qiymət mənimsədə bilmək üçün əvvəlcə ona yaddaşda aşağıdakı kimi yer ayırmalıyıq.
muhendis = (struct ishci *)malloc(sizeof(struct ishci));
Bu operatordan sonra biz artıq muhendis dəyişəninin istənilən elementinə -> operatoru vasitəsilə müraciət edə bilərik.
  muhendis->yash=33;
  strcpy(muhendis->ad,"Rustem");  
Proqram nümunəsi:
prog_8_2.c
        #include <stdio.h>
        #include <stdlib.h>
        #include <string.h>
        
        /* yeni_tip adli struct tipi yaradiriq*/
        struct yeni_tip{
        char ad[20];
        int  x; };
        
        int main(int argc, char *argv[]){
        
        struct yeni_tip *dey;
        
        /* malloc yaddashda yer ayirir, bu yerde evvelceden bashqa melumatlar ola biler ve bu bize 
               gozlenilmeyen problemler yarada biler. Ona gore malloc -la yaddashda yer ayiranda 
             onun butun baytlarini memset -le 0-ra menumsetmek meslehetdir. */
        
        dey = malloc(sizeof(struct yeni_tip));
        memset(dey,0,sizeof(struct yeni_tip));
        
        dey->x=50;
        strcpy(dey->ad,"Veli");
        
        printf("%s,%d\n",dey->ad,dey->x);
        return 0;      
        }
        
user@gnu_linux:~/prg# 
user@gnu_linux:~/prg# gcc prog_8_2.c -o prog_8_2
user@gnu_linux:~/prg# 
user@gnu_linux:~/prg# ./prog_8_2
Veli,50
user@gnu_linux:~/prg# 
user@gnu_linux:~/prg# 


Hiç yorum yok:

Yorum Gönder