C Proqramlaşdırma Dili

Əlavələr

Əlavələr

Bu mətndə C dilinin əsas anlayışları daxil edilir. Bu mətndə daxil olunan proqramlarla tanış olduqca, tədricən proqramlaşdırma təcrübəsi formalaşır.
Daha sonra, kodları açıq şəkildə internetdə yerləşdirilən C proqramları üzərində işləmək lazımdır. Bunun üçün biz sayta 500 sətirlik fcp proqramını açıq kodla yerləşdirməyi planlaşdırırıq. Hal-hazırda müəlliflər bu proqramın ayrı-ayrı sətirlərinin şərhləri üzərində işlər görür.
Artıq özünü orta təcrübəli hesab edən proqramçılar Unix sistemini öyrənməyə başlamalıdırlar.
İlk olaraq, Unix-in əmrlərini (ls, cd, pwd, mkuser, chown, ps, nm, ld...), daha sonra isə, sistem funksiyaları (open, close – fayllara müraciət, read, write - fayla oxuyub-yazmaq, socket – Unix-də şəbəkə proqramlaşdırma, pipe – Unix-də proqramlararası informasiya mübadiləsi, fork, execve – Unix-də bir proqramdan digər proqramı yükləmək və s.) öyrənmək lazımdır.
Unix ile kifayət qədər proqramlaşdırma təcrübəsi yığdıqdan sonra, siz artıq gələcək inkişafınız barəsində seçim etməlisiniz.

Belə ki, sizin 2 seçiminiz var:

1. İstifadəçi proqramlaşdırma.
Bu halda siz böyük sürətlə (Unix təcrübəsi sizə bunu mümkün edəcək) C++, PHP, JAVA proqramlaşdırma dillərini, SQL Məlumatlar bazası dilini, Oracle, MySQL Məlumatlar bazası proqramlarını, HTML, CSS script dillərini və s. öyrənib, ciddi proyektlərlə məşğul ola bilərsiniz.

2. Sistem proqramlaşdırma.
Çox çətin bir seçim. İşlər o qədər də sürətlə getməyəcək, hətta çox güclü C və Unix təcrübəniz olsa da.
Sistem proqramlaşdırma ilə istifadəçi proqramlaşdırma arasında fərq çox böyükdür, hər ikisinin sonunun proqramlaşdırma ilə qurtarmasına baxmayaraq.

Bu istiqamət üzrə getmək istəsəniz, siz aşağıdakıları öyrənməlisiniz. İlk əvvəl öyrənməsi lazım olan ingilis dilidir (əgər bilmirsinizsə).

1. Assembler dili, mütləq vacibdir.
2. Make proqramı ilə tanış olmaq.
3. Shell proqramlaşdırmanı öyrənmək.

Bütün bunlar hazırlıq mərhələsi hesab olunur, məqsəd isə Linux nüvəsini öyrənməkdir.
Beləliklə, siz artıq kifayət qədər C, Assembler, Unix, Make, Shell təcrübəsinə sahibsiniz və Linux nüvəsini öyrənmək barədə qəti qərar vermisiniz.
Burada işləri necə görməli, Linux nüvəsini necə öyrənmək barədə hansısa bir ipucu və ya kitab axtarmağına dəyməz. Bütün problemləri özünüz həll etməlisiniz (xakerlərin hamısı belə edir). Birinci görməli iş Linux nüvəsini kompilyasiya edib əməliyyatlar sistemini yeni nüvə ilə yükləməkdir.
Müəlliflərdən birinə yeni başlayarkən bu işin öhdəsindən uğurla gəlməyə 4 ay vaxt sərf olunub (təqribən 1000 dəfə kompilyasiyadan sonra sistemi yeni nüvə ilə yükləmək mümkün olub).
Bu işin öhdəsindən uğurla gəldikdən və yeni nüvənin kodları ilə bir balaca oynadıqdan sonra, siz nüvənin təşkil olunduğu ayrı-ayrı hissələri öyrənməlisiniz. Bu hissələrə yaddaşın idarə olunması, fayllar sistemi, şəbəkə, IPC hissələrini və Linuxu ilk öyrəndikdə, bir çox proqramçıların böyük həvəs göstərdiyi (lakin heç də asan olmayan) driver-ləri misal göstərmək olar.
Bunlar barəsində elektron kitablar kifayət qədərdir (ingilis dilində). Linux nüvəsinin kodları açıqdır, Linus Torvalds-ın da dediyi kimi: "Linux-u öyrənməyin ən yaxşı yolu Linux-un açıq kodları ilə məşğul olmaqdır".
 

fcp proqramı

Hörmətli oxucular, gənc proqramçılar, sizə tapşırıq:
fcp proqramının mətn kodunu təhlil edin, orada istifadə olunan struct tiplər, cərgələr, siyahılar və s. mürəkkəb strukturlu dəyişən tiplərini analiz edin, proqramda istifadə olunan funksiyaları, onlara parametrlərin ötürülməsi və cavabların qaytarılmasını təhlil edin, proqram kodunda istədiyiniz kimi dəyişiklik edib, onun imkanlarını (beləcə də, öz proqramlaşdırma təcrübənizi) artırın.
Proqramlaşdırmanı öyrənmənin yeganə yolu proqram yazmaq və proqram kodları üzərində çalışmaqdır.

Hamıya uğurlar. Hörmətlə: Əhməd Sadıxov.


Bu paraqrafda C dilində yazılmış, təxminən 300 sətirlik fcp proqramına baxılır.
Biz kompüterlə gündəlik iş zamanı bir neçə dəfə hər hansı bir faylı və qovluğu yaddaşda bir yerdən digər yerə köçürürük. Copy-Paste və ya Ctrl+C - Ctrl+V -dən istifadə edirik. Bu zaman köçürülən fayl və qovluqların adı və köçürüldüyü yer sistem tərəfindən köçürməni yerinə yetirən proqrama (cp - Unix, copy - Windows) ötürülür.
fcp analoji işi görən proqramdır və tamamilə C dilində yazılıb.

Proqramı kompilyasiya edək.


user@gnu_linux:~/prg# 
user@gnu_linux:~/prg# gcc main.c -o fcp
user@gnu_linux:~/prg#

Proqramı yerinə yetirmək üçün ./fcp fayl_ve_qovluq qovluq kimi əmr daxil etməliyik.
Gəlin, fcp ilə linux24 qovluğunu shw qovluğuna köçürək. Əvvəlcə shw qovluğunda olan fayllara baxaq və əmin olaq ki, linux24 qovluğu hələlik orada deyil və fcp vasitəsilə köçürüləcək.


user@gnu_linux:~/prg# ls shw
first first.c~ first.s~ main.c~ main.s Makefile~ README~ runmec runme.c~ runme.o shw
first.c first.s main.c main.o Makefile README runme runme.c runme.e runme.s
user@gnu_linux:~/prg# 
user@gnu_linux:~/prg# 

İndi isə, linux24 qovluğunda olan fayllara baxaq. linux24-ü shw-yə köçürdükdən sonra, biz onda olan fayllara yenidən baxıb, fcp-nin linux24-də olan faylların hamısını köçürməsini yoxlayacayıq.


user@gnu_linux:~/prg# ls linux24
arch CREDITS Documentation fs init kernel MAINTAINERS mm README Rules.make
COPYING crypto drivers include ipc lib Makefile net REPORTING-BUGS scripts
user@gnu_linux:~/prg# 
user@gnu_linux:~/prg#

Qeyd edək ki, linux24 qovluğu öz növbəsində bir neçə fayl və qovluqdan və onlar da öz növbəsində bir neçə fayl və qovluqdan ibarətdir. Bu qovluqda Linux nüvəsi 2.4 versiyasının proqram kodları yerləşir.
Gəlin görək, fcp öz işinin öhdəsindən necə gəlir.


user@gnu_linux:~/prg# 
user@gnu_linux:~/prg# ./fcp linux24 shw
user@gnu_linux:~/prg# 

Köçürməni yerinə yetirdik, yoxlamalarımızı aparaq.


user@gnu_linux:~/prg# ls shw
first first.c~ first.s~ main.c main.o Makefile README runme runme.c runme.e runme.s
first.c first.s linux24 main.c~ main.s Makefile~ README~ runmec runme.c~ runme.o shw
user@gnu_linux:~/prg#

fcp linux24 qovluğunu fhed qovluğuna köçürüb. linux24-də olan faylların siyahısına baxaq.


user@gnu_linux:~/prg# 
user@gnu_linux:~/prg# ls shw/linux24
arch CREDITS Documentation fs init kernel MAINTAINERS mm README Rules.make
COPYING crypto drivers include ipc lib Makefile net REPORTING-BUGS scripts
user@gnu_linux:~/prg# 
user@gnu_linux:~/prg#

Göründüyü kimi, fcp bütün fayl və qovluqları köçürmüşdür.
Biz köçürməni yerinə yetirmək üçün ./fcp linux24 shw əmrini daxil etdik. fcp linux24-ü shw-yə köçürdü, lakin ekrana heç bir məlumat çap etmədi.

Proqramda elə dəyişiklik edin ki:
1. Köçürülmə başlayan zaman və sona yetdikdə, ekrana müvafiq məlumat versin.
2. Köçürülən fayl və qovluqların adlarını ekranda çap etsin.
3. Köçürülən faylların ümumi sayını və həcmini (Mb-la) ekranda çap etsin.

fcp programı (main.c və fcp.h fayllarından ibarətdir)

main.c faylı:


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>

#include <sys/stat.h>
#include "fcp.h"


int nusxe_fayl(char *, char *);
int is_reg_file(char *);
void set_src_list_elem(struct source_list_elem *, char *, char *);
void copy_all(struct source_list *);
void new_src_lst(struct source_list *);
int is_same_file(char *,char *);
void add_src_list_elem(struct source_list *,struct source_list_elem *); 
int is_folder(char *);
void prn_src_lst(struct source_list *);
void set_src_lst(struct source_list *, char *, char *);
char *get_name(char *);
void copy_file(char *,char *);
char *get_curr_fold();


int main(int argc, char *argv[]){

/* Proqram icra olunmağa bu yerdən başlayır. */

struct source_list *src_lst;
src_lst=(struct source_list *) malloc(sizeof(struct source_list));
new_src_lst(src_lst);
int i,k;
struct source_list_elem *src_lst_el;

char dest_buf[100];
memset(dest_buf,0,100);

if (argc<3){
printf("istifadə: gcp köçürülməli olan fayl ve ya qovluqların siyahısı son_qovluq\n");
exit(0); }
if (!is_folder(argv[argc-1])){
printf("istifadə: gcp köçürülməli olan fayl ve ya qovluqların siyahısı son_qovluq\n");
exit(0); }
    
strcpy(dest_buf,argv[argc-1]);
*(dest_buf+strlen(argv[argc-1]))='/';
strcat(dest_buf,argv[1]);

src_lst_el=(struct source_list_elem *)malloc(sizeof(struct source_list_elem));
set_src_list_elem(src_lst_el,argv[1],dest_buf);
add_src_list_elem(src_lst,src_lst_el);


copy_all(src_lst); 

return 0;
}


/*=========================================================================*/


int is_reg_file(char *fn){


struct stat *info = (struct stat *)malloc(sizeof(struct stat));
memset(info,0,sizeof(struct stat));

if (stat(fn,info)==-1){
    printf("cannot stat file %s\n",fn);
exit(0);}
if (((info->st_mode)&(S_IFMT))==(S_IFREG))
return 1;
    
return 0;
}


/*=================================================*/


int is_folder(char *fn){


struct stat *info = (struct stat *)malloc(sizeof(struct stat));
memset(info,0,sizeof(struct stat));

if (stat(fn,info)==-1){
    printf("cannot stat %s\n",fn);
exit(0);}
if (((info->st_mode)&(S_IFMT))==(S_IFDIR))
return 1;

return 0;
}


/*=================================================*/


void set_src_list_elem(struct source_list_elem *src_lst_el, char *src_f, char *dest_f){

int k;
memset(src_lst_el,0,sizeof(struct source_list_elem));

k=strlen(src_f);
src_lst_el->src_file = (char *)malloc(k+1);
memset(src_lst_el->src_file,0,k+1);
strcpy(src_lst_el->src_file,src_f);

k=strlen(dest_f);
src_lst_el->dest_file = (char *)malloc(k+1);
memset(src_lst_el->dest_file,0,k+1);
strcpy(src_lst_el->dest_file,dest_f);

src_lst_el->copied = 0;
src_lst_el->next_el=NULL;
}


/*=================================================*/


void new_src_lst(struct source_list *src_lst){

memset(src_lst,0,sizeof(struct source_list));
src_lst->first_el=src_lst->last_el=NULL;
src_lst->count=0;
}


/*======================================================*/


int is_same_file(char *curr_fold,char *dest_fold){

char *tmp=(char *)malloc(BUF_LEN);
memset(tmp,0,BUF_LEN);
if((*dest_fold)=='/')
    return strcmp(curr_fold,dest_fold);
strcpy(tmp,curr_fold);
*(tmp+sizeof(curr_fold))='/';
strcat(tmp,dest_fold);
if((*dest_fold)=='/')
return strcmp(curr_fold,dest_fold);
}


/*======================================================*/


void add_src_list_elem(struct source_list *src_lst, struct source_list_elem *sle){

if (src_lst->first_el==NULL)
{
    src_lst->first_el=src_lst->last_el=sle;
    sle=NULL; }
else
    {
    src_lst->last_el->next_el=sle;
    src_lst->last_el=sle;
    sle=NULL; }
}


/*======================================================*/


void prn_src_lst(struct source_list * src_lst){

struct source_list_elem *tmp=src_lst->first_el;

while(tmp!=NULL){
    printf("source file %s\n",tmp->src_file);
    printf("dest file %s\n",tmp->dest_file);
    tmp=tmp->next_el;
}
}


/*======================================================*/


void set_src_lst(struct source_list *src_lp, char *src_fold, char *dest_fold){
DIR *dir_ptr;
struct source_list_elem *src_lst_el;
char *src_buf,*dest_buf;

src_buf = (char *)malloc(100);
dest_buf = (char *)malloc(100);
memset(src_buf,0,100);
memset(dest_buf,0,100);
struct dirent *direntp;
if ((dir_ptr=opendir(src_fold))==NULL){
    printf("cannot open %s exiting\n",src_fold);
exit(0); }

while((direntp=readdir(dir_ptr))!=NULL){

memset(dest_buf,0,100);
strcpy(dest_buf,dest_fold);
*(dest_buf+strlen(dest_buf))='/';
strcat(dest_buf,direntp->d_name);

memset(src_buf,0,100);
strcpy(src_buf,src_fold);
*(src_buf+strlen(src_buf))='/';
strcat(src_buf,direntp->d_name);

src_lst_el=(struct source_list_elem *) malloc(sizeof(struct source_list_elem));

set_src_list_elem(src_lst_el,src_buf,dest_buf);
add_src_list_elem(src_lp,src_lst_el);} 

closedir(dir_ptr);
}


/*======================================================*/


char *get_name(char *fn){
int k=strlen(fn);
char *p=fn+k;
while((*(p)!='/')&&(k--))
p--;
if (*p=='/') 	return p+1;
else return p;
}


/*======================================================*/


void copy_file(char *src_file,char *dest_file){
    int i,k;
    int fd1,fd2;
    char buf[BUF_LEN];
    fd1=open(src_file,O_RDONLY);	
    if(fd1==-1){
    printf("copy_fayl: %s faylı açılmır\n",src_file);
exit(0); }

/* BUG yeni faylın modu orijinal deyil, 644 götürülür! */

if ((fd2=open(dest_file, O_WRONLY | O_CREAT | O_TRUNC, 0644))==-1)

    printf("nuxse_fayl: %s faylını yaratmaq mümkün olmadı\n",dest_file);

/* Hissə-hissə (1024 bayt) köçürürük */

while((i=read(fd1,buf,BUF_LEN)) >0)
    write(fd2,buf,i);
    close(fd1);
    close(fd2); }


/*======================================================*/


void copy_all(struct source_list *src_lst){
struct source_list *src_lp;	
struct source_list_elem *tmp=src_lst->first_el;
while (tmp!=NULL) {
if (is_reg_file(tmp->src_file)) {
    copy_file(tmp->src_file,tmp->dest_file); }
if (is_folder(tmp->src_file)&&((strcmp(get_name(tmp->src_file),"..")!=0)&&(strcmp(get_name(tmp->src_file),".")!=0))) {
if (mkdir(tmp->dest_file, 0755)==-1) {
    printf("copy_all: %s qovluğu yaradılmır\n",tmp->dest_file);
exit(0); }
src_lp=(struct source_list *) malloc(sizeof(struct source_list));
new_src_lst(src_lp);
set_src_lst(src_lp,tmp->src_file,tmp->dest_file);
copy_all(src_lp); 
free(src_lp); }
tmp=tmp->next_el; }
}

Nümunə


fcp.h faylı:


#ifndef GCP_H
#define GCP_H

#define BUF_LEN 1024
#define FNAME_LEN 1024

struct source_list_elem{
    char *src_file;
    char *dest_file;
    int copied; 
    struct source_list_elem *next_el;
};

struct source_list{
    struct source_list_elem *first_el;
    struct source_list_elem *last_el;
    int count;
};
#endif

Nümunə