> Bazı az kullanılan standart C fonksiyonları: >> "strtok" fonksiyonu: Özellikle sistem programlamada çok kullanılan bir fonksiyondur. Bir yazıyı çeşitli biçimlerde ayrıştırmaya yaramaktadır. Fonksiyonun prototipi aşağıdaki gibidir: #include char* strtok(char* str, const char* delimiters); Fonksiyonun birinci parametresi "const" olmadığı için buraya geçilen yazı değiştirilecektir. Yani parçalara ayrılacak yazının başlangıç adresi bu parametreye geçilmelidir. Buraya geçilecek yazının sonunda "\0" karakteri OLMALIDIR. Fonksiyonun ikinci parametresi ise ayraç olarak kullanılacak karakterlerin oluşturduğu yazının başlangıç adresidir. Fonksiyonun geri dönüş değeri, ilk parçalanan yazının başlangıç adresidir. Dolayısıyla bir yazıyı tam anlamıyla parçalarına ayırmak için bu fonksiyonu tekrar tekrar çağırmalıyız. Fakat ilk çağrıdan sonraki çağrılarda bu fonksiyonun birinci parametresine artık "NULL" değerini geçmemiz gerekmektedir. Dolayısıyla bu fonksiyonu bizler bir döngü içerisinde çağırmalıyız. * Örnek 1, #include #include int main(void) { /* # OUTPUT # Ahmet Kandemir .,,...,,,,Ahmet,,,...,,.Kandemir,..,, */ char string_to_parse[] = ".,,...,,,,Ahmet,,,,...,,.Kandemir.,..,,"; char delimeters[] = ".,"; for (char* parsed_string = strtok(string_to_parse, delimeters); parsed_string != NULL; parsed_string = strtok(NULL, delimeters)) puts(parsed_string); for (int i = 0; i < 40; ++i) printf("%c", string_to_parse[i]); return 0; } Bu fonksiyonun çalışmasını da şu şekilde açıklayabiliriz; Birinci parametresi ile belirtilen adresten başlayarak ilk ayraç karakteri olmayan karakterin yerini elde eder. Sonra ayıraç karakteri görmeyene dek ilerlemeye devam eder. İlk ayıraç karakteri gördüğünde oraya "\0" karakterini yerleştirir. Daha sonra yukarıda elde etmiş olduğu yer adresi ile fonksiyon geri döner. Yani; 1. Turda: .,,...,,,,Ahmet,,,,...,,.Kandemir.,..,, ^ ^^ a cb Burada ilk "a" konumunun adresi elde tutulur. Daha sonra "b" konumu bulunur ve bu konuma "\0" karakteri yerleştirilir. Artık yazı şu şekildedir: .,,...,,,,Ahmet\0,,,...,,.Kandemir.,..,, ^ ^ a c Fonksiyon "a" ile "c" konumları arasındaki yazıyı geri döndürür. Artık esas yazının son hali şu şekildedir: 2. Turda: .,,...,,,,Ahmet,,,...,,.Kandemir.,..,, ^ ^ d e Daha sonra bu fonksiyonu tekrar çağırırsak, "e" konumuna "\0" karakteri yerleştirip, "d" ve "e" konumları arasındaki yazıyı döndürecektir. Dolayısıyla esas yazının son hali aşağıdaki gibi olacaktır: .,,...,,,,Ahmet,,,...,,.Kandemir,..,, Görüldüğü üzere esas yazı bozulmuştur. Eğer bu bozulmanın olmasını istemiyorsak, ilgili diziyi kopyalamalıyız. Öte yandan bu program ile bir yazıyı parçalarken, ilgili yazının "static" alanda olması ve bir gösterici tarafından gösterilmediğine dikkat ediniz. Anımsayacağınız üzere C dilinde "string literal" lerin değiştirilmesi Tanımsız Davranış oluşturulacaktır. Bunun bir istisnası diziye ilk değer verilmesi durumudur. * Örnek 1, Aşağıdaki kodu "Microsoft Visual Studio" ile "Debugger" kullanarak çalıştırdığınızda programın çöktüğü görülecektir. #include #include int main(void) { /* # OUTPUT # */ char* string_to_parse = "Ali, Veli, Selami, Fatma"; /* Statik alandaki yazı bir gösterici tarafından gösterilmektedir. */ const char* delimeters = ".,"; char* parsed_string; for (parsed_string = strtok(string_to_parse, delimeters); parsed_string != NULL; parsed_string = strtok(NULL, delimeters)) puts(parsed_string); /* for (parsed_string = strtok("Ali, Veli, Selami, Fatma", delimeters); parsed_string != NULL; parsed_string = strtok(NULL, delimeters)) puts(parsed_string); */ for (int i = 0; i < 40; ++i) printf("%c", string_to_parse[i]); return 0; } * Örnek 2, Aşağıdaki kod Linux sisteminde çalıştırılmıştır. #include #include int main(void) { /* # OUTPUT # Segmentation fault */ char* string_to_parse = "Ali, Veli, Selami, Fatma"; /* Statik alandaki yazı bir gösterici tarafından gösterilmektedir. */ const char* delimeters = ".,"; char* parsed_string; for (parsed_string = strtok(string_to_parse, delimeters); parsed_string != NULL; parsed_string = strtok(NULL, delimeters)) puts(parsed_string); for (int i = 0; i < 40; ++i) printf("%c", string_to_parse[i]); return 0; } Şimdi de bu fonksiyonu bizler yazmaya çalışalım: * Örnek 1, #include #include char* mystrtok(char* s, const char* delims); int main(void) { /* # OUTPUT # Ali Veli Selami Fatma Ali Veli Selami Fatma ------------------------------------------------------------------------------------------- Ali Veli Selami Fatma Ali Veli Selami ,,,,, Fatma */ { char string_to_parse[] = "Ali, Veli, Selami, Fatma"; const char* delimeters = "., "; char* parsed_string; for (parsed_string = strtok(string_to_parse, delimeters); parsed_string != NULL; parsed_string = strtok(NULL, delimeters)) puts(parsed_string); for (int i = 0; i < 25; ++i) printf("%c", string_to_parse[i]); } puts("\n-------------------------------------------------------------------------------------------"); { char string_to_parse[] = "Ali, Veli, Selami, ,,,,, Fatma "; char* parsed_string; for (parsed_string = mystrtok(string_to_parse, ", "); parsed_string != NULL; parsed_string = mystrtok(NULL, ", ")) puts(parsed_string); for (int i = 0; i < 40; ++i) printf("%c", string_to_parse[i]); } return 0; } char* mystrtok(char* s, const char* delims) { static char* str; char* beg; /* Eğer fonksiyona geçilen adreste bir yazı varsa, bu yazı "str" ile gösterilecektir. */ if (s != NULL) str = s; /* * Daha sonra "str" adresinden başlayarak, ilk ayıraç karakteri olmayan karakter görülene kadar * ilgili gösterici ötelenecektir. Çünkü "strchr" fonksiyonu "NULL" değeri döndürmezse, ayıraç * karakterinin konumunu döndürür. Böylelikle bizler her ayıraç karakteri gördüğümüzde, göstericiyi * bir öteleriz. */ while (*str != '\0' && strchr(delims, *str) != NULL) ++str; /* Eğer yazının sonuna gelmişsek veya yazının içinde '\0' karakteri görmüşsek, geri döneriz. */ if (*str == '\0') return NULL; /* * Bu aşamada ne yazı sonundayız ne de bir ayıraç karakteri gördük. Artık ayıraç karakteri olmayan * bir karakterin adresini saklıyoruz. */ beg = str; /* * Daha sonra aramaya devam edelim ki ayıraç olmayan karakterler nerede son buluyor öğrenelim. "strchr" * fonksiyonu "NULL" değerini döndürdüğünde, ayıraç karakteri bulamamış demektir. Bu sefer de ayıraç olmayan * karakter gördükçe ilgili göstericiyi bi' öteliyoruz. */ while (*str != '\0' && strchr(delims, *str) == NULL) ++str; /* * Artık bu aşamada "str" göstericisi ayıraç karakteri göstermektedir. Eğer yazının sonu değilse, o karaktere * '\0' karakteri yerleştirip göstericiyi bir öteliyoruz. Böylelikle bizler ayıraç karakteri olmayan bir yazıyı * elde etmiş olduk. */ if (*str != '\0') *str++ = '\0'; /* * Bu aşamada yazının baş kısmını "beg" göstericisi, yazının sonundaki '\0' karakterinden sonraki konumu da "str" * göstericisi göstermektedir. */ /* printf("Obtained string: "); for (char* index = beg; index != str;) { printf("[%c] ", *index++); } */ return beg; } Şimdi de bu fonksiyonun "thread-safe" versiyonunu inceleyelim. Fonksiyonun ismi "strtok_s" biçimindedir. İleride de görüleceği üzere "static" ömürlü nesne kullanılması "thread-safe" değildir. Bu sebeple "Microsoft" standartlarınca böylesi bir fonksiyon oluşturulmuştur. Bu fonksiyon "static" ömürlü nesne yerine, üçüncü parametresinde geçilen göstericiyi kullanmaktadır. Bu fonksiyonun "UNIX" karşılığı da "strtok_r" isimli fonksiyondur. Fonksiyonların prototipi aşağıdaki gibidir: #include char* strtok_s(char* str,const char* delimiters,char** context ); char *strtok_r(char* s, const char* sep, char** state); Aşağıda örnek kullanımlar verilmiştir: * Örnek 1, Aşağıdaki örnekte "Microsoft" versiyonu kullanılmıştır. #include #include int main(void) { /* # OUTPUT # Ali Veli Selami Fatma Ali Veli Selami Fatma */ char string_to_parse[] = "Ali, Veli, Selami, Fatma"; const char* delimeters = "., "; char* parsed_string; char* saved_string; for (parsed_string = strtok_s(string_to_parse, delimeters, &saved_string); parsed_string != NULL; parsed_string = strtok_s(NULL, delimeters, &saved_string)) puts(parsed_string); for (int i = 0; i < 25; ++i) printf("%c", string_to_parse[i]); return 0; } * Örnek 2, Aşağıdaki örnekte ise "POSIX" versiyonu kullanılmıştır. #include #include int main(void) { /* # OUTPUT # Ali Veli Selami Fatma Ali Veli Selami Fatma */ char string_to_parse[] = "Ali, Veli, Selami, Fatma"; const char* delimeters = "., "; char* parsed_string; char* saved_string; for (parsed_string = strtok_r(string_to_parse, delimeters, &saved_string); parsed_string != NULL; parsed_string = strtok_r(NULL, delimeters, &saved_string)) puts(parsed_string); for (int i = 0; i < 25; ++i) printf("%c", string_to_parse[i]); return 0; } Şimdi de bir dosyadaki yazıları ayrıştırmayı görelim: * Örnek 1, /* test.csv */ ali,29,ankara veli,30,istanbul selami,17,sivas turgut,21,kastamonu /* main.c */ #include #include #include #define MAX_LINE 4096 int is_all_space(const char* string); int main(void) { /* # OUTPUT # ali 29 ankara ------------------ veli 30 istanbul ------------------ selami 17 sivas ------------------ turgut 21 kastamonu ------------------ */ FILE* f; if ((f = fopen("test.csv", "r")) == NULL) { fprintf(stderr, "cannot open file...\n"); exit(EXIT_FAILURE); } char line[MAX_LINE]; char* parsed_string; while (fgets(line, MAX_LINE, f) != NULL) /* "fgets" fonksiyonu, satır sonundaki '\n' karakterini de alacaktır. */ { /* Eğer okunan satır sadece boşluk karakterlerinden oluşmuşsa, o satırlar atlanacaktır. */ if(is_all_space(line)) continue; /* Satır sonundaki bu '\n' karakteri '\0' karakterine dönüştürülür. */ if ((parsed_string = strchr(line, '\n')) != NULL) *parsed_string = '\0'; /* Daha sonra her bir satır ayrıştırılır. */ for (parsed_string = strtok(line, ","); parsed_string != NULL; parsed_string = strtok(NULL, ",")) printf("%s\n", parsed_string); printf("------------------\n"); } fclose(f); return 0; } int is_all_space(const char* string) { while(*string != '\0' && isspace(*string)) ++string; return *string == '\0'; } Pekiyi ayrıştırma yaparken elimizdeki yazının bozulmasını istemiyorsak ne yapmalıyız? Tabii ki bu yazıyı başka bir yerde saklamalı. * Örnek 1, Aşağıdaki örnekte "strtok" fonksiyonunun esas yazıyı bozmayan versiyonunu yazmış olduk. Fakat bunu yapmak yerine esas diziyi başka yere kopyaladıktan sonra işlemlere devam da edebilirdik. #include #include char* mystrtok(const char* str, const char* delims, char* dest); int main(void) { /* # OUTPUT # Ali Veli Selami Fatma ---------------------------- Ali, Veli, Selami, ,,,,, Fatma */ char string_to_parse[] = "Ali, Veli, Selami, ,,,,, Fatma "; char buffer[1024]; char* parsed_string; for (parsed_string = mystrtok(string_to_parse, ", ", buffer); parsed_string != NULL; parsed_string = mystrtok(NULL, ", ", buffer)) puts(parsed_string); puts("----------------------------\n"); puts(string_to_parse); return 0; } char* mystrtok(const char* s, const char* delims, char* dest) { static const char* str; const char* beg; if (s != NULL) str = s; /* * Yazının içerisinde ayıraç karakteri bulunduğu müddetçe ilgili gösterici bir ötelenmektedir. */ while (*str != '\0' && strchr(delims, *str) != NULL) ++str; /* * Eğer yazı sonuna gelinmişse fonksiyondan dönülecektir. */ if (*str == '\0') return NULL; /* * Akış buraya gelmişse ayıraç olmayan bir karakteri bulunmuş demektir. Artık o karakterin konumu * saklandı. */ beg = str; /* * Artık ayıraç olmayan karakter bulunduğu müddetçe ilgili gösterici bir ötelenmektedir. */ while (*str != '\0' && strchr(delims, *str) == NULL) ++str; /* * Akış buraya gelmişse ayıraç olan bir karakteri bulunmuştur. Artık "beg" konumundan başlayan ve "str" * konumunda son bulan bu yazıyı "dest" adresinden itibaren kopyalayabiliriz. */ strncpy(dest, beg, str - beg); /* * Son olarak "dest" adresine kopyalanan yazının sonuna da '\0' karakteri koyalım. */ dest[str - beg] = '\0'; /* * Şimdi "str" konumu ayıraç karakterinin yerini göstermektedir. Birazdan fonksiyondan çıkılacağı için, * tekrardan göstericiyi ötelemeye lüzum yoktur. Fonksiyon yeniden çağrıldığında, bu karakterin konumundan * devam edecektir. */ if (*str != '\0') ++str; return dest; } * Örnek 2, Aşağıdaki örnekte ise parçalara ayrılacak olan yazı başka bir yere kopyalanmıştır. #include #include int main(void) { /* # OUTPUT # Ali Veli Selami Fatma ---------------------------- Ali, Veli, Selami, ,,,,, Fatma */ const char string_to_parse[] = "Ali, Veli, Selami, ,,,,, Fatma "; char copied_string[40]; char* parsed_string; strcpy(copied_string, string_to_parse); for (parsed_string = strtok(copied_string, ", "); parsed_string != NULL; parsed_string = strtok(NULL, ", ")) puts(parsed_string); puts("----------------------------\n"); puts(string_to_parse); return 0; } * Örnek 3, Aşağıdaki örnekte ise dinamik bellek tahsisatı yapılmıştır. #include #include #include char* mystrtok(const char* str, const char* delims); int main(void) { /* # OUTPUT # Ali Veli Selami Fatma ---------------------------- Ali, Veli, Selami, ,,,,, Fatma */ const char string_to_parse[] = "Ali, Veli, Selami, ,,,,, Fatma "; char* parsed_string; for (parsed_string = mystrtok(string_to_parse, ", "); parsed_string != NULL; parsed_string = mystrtok(NULL, ", ")) { puts(parsed_string); free(parsed_string); } puts("----------------------------\n"); puts(string_to_parse); return 0; } char* mystrtok(const char* s, const char* delims) { static const char* str; const char* beg; char* dest; if (s != NULL) str = s; /* * Yazının içerisinde ayıraç karakteri bulunduğu müddetçe ilgili gösterici bir ötelenmektedir. */ while (*str != '\0' && strchr(delims, *str) != NULL) ++str; /* * Eğer yazı sonuna gelinmişse fonksiyondan dönülecektir. */ if (*str == '\0') return NULL; /* * Akış buraya gelmişse ayıraç olmayan bir karakteri bulunmuş demektir. Artık o karakterin konumu * saklandı. */ beg = str; /* * Artık ayıraç olmayan karakter bulunduğu müddetçe ilgili gösterici bir ötelenmektedir. */ while (*str != '\0' && strchr(delims, *str) == NULL) ++str; /* * Bu aşamada ayıraç olmayan karakterlerin kopyalanacağı alan dinamik bir biçimde tahsis edilmiştir. Hata * kodunun daha iyi anlaşılabilir olması için "errno" değişkeninden faydalanabiliriz. */ if ((dest = (char*)malloc(str - beg + 1)) == NULL) return NULL; /* * Akış buraya gelmişse ayıraç olan bir karakteri bulunmuştur. Artık "beg" konumundan başlayan ve "str" * konumunda son bulan bu yazıyı "dest" adresinden itibaren kopyalayabiliriz. */ strncpy(dest, beg, str - beg); /* * Son olarak "dest" adresine kopyalanan yazının sonuna da '\0' karakteri koyalım. */ dest[str - beg] = '\0'; /* * Şimdi "str" konumu ayıraç karakterinin yerini göstermektedir. Birazdan fonksiyondan çıkılacağı için, * tekrardan göstericiyi ötelemeye lüzum yoktur. Fonksiyon yeniden çağrıldığında, bu karakterin konumundan * devam edecektir. */ if (*str != '\0') ++str; return dest; } >> "remove" fonksiyonu: Standart bir C fonksiyonudur. Dosya silmek için kullanılır. Fakat her kullanıcı her bir dosyayı da silemez. Bir takım güvenlik mekanizması arka planda işletilmektedir ki bu mekanizmaya ileride değinilecektir. Fonksiyonun prototipi aşağıdaki gibidir: #include int remove(const char *path); Fonksiyon argüman olarak silinmek istenen dosyanın yol ifadesini alır. Başarı durumunda "0", hata durumunda ise "0" dışı bir değeri döndürür. Muhtelif nedenlerden dolayı bu fonksiyon başarısız olabilir. Dolayısıyla geri dönüş değeri mutlaka kontrol edilmelidir. * Örnek 1, #include #include int main(void) { /* # OUTPUT # file removed... */ /* Prosesin "cwd" içerisindeki "test.csv" ismine sahip dosya silinmeye çalışılacaktır. */ if (remove("test.csv")) { fprintf(stderr, "cannot remove the file...\n"); exit(EXIT_FAILURE); } puts("file removed...\n"); return 0; } Pekiyi halihazırda kullanılan bir dosyayı silmek istersek ne olur? Bu durum işletim sistemine göre değişiklik göstermektedir. UNIX türevi sistemlerde, dosya yine silinir fakat gerçek silme işlemi ilgili dosya kapatıldıktan sonra gerçekleştirilir. Windows işletim sisteminde ise o dosya oluşturulurken kullanılan bir takım bayraklara göre davranış değişiklik göstermektedir. * Örnek 1, Aşağıdaki program Windows bir işletim sisteminde çalıştırılmıştır. #include #include int main(void) { /* # OUTPUT # File opened!... cannot remove the file... */ FILE* f; if ((f = fopen("test.txt", "r")) == NULL) { fprintf(stderr, "cannot open file...\n"); exit(EXIT_FAILURE); } puts("File opened!...\n"); if (remove("test.txt")) { fprintf(stderr, "cannot remove the file...\n"); exit(EXIT_FAILURE); } puts("file removed...\n"); fclose(f); return 0; } * Örnek 2, Aşağıdaki program UNIX türevi bir işletim sisteminde çalıştırılmıştır. #include #include int main(void) { /* # OUTPUT # File opened!... file removed... */ FILE* f; if ((f = fopen("test.txt", "r")) == NULL) { fprintf(stderr, "cannot open file...\n"); exit(EXIT_FAILURE); } puts("File opened!...\n"); if (remove("test.txt")) { fprintf(stderr, "cannot remove the file...\n"); exit(EXIT_FAILURE); } puts("file removed...\n"); fclose(f); return 0; } Öte yandan belirtmek gerekir ki bu fonksiyon kullanılarak silinen dosyalar Geri Dönüşüm Kutusu'nda saklanmaz. Geri Dönüşüm Kutusu, yüksek seviyeli bir "shell" organizasyonudur. İşletim sisteminin çekirdeğinin bir ilgisi yoktur. Hakeza Gizli Dosyaları da bu fonksiyonu kullanarak silebiliriz. Son olarak bir dosya silindiğinde diskteki baytlar silinmez, ekseriyetle. Sadece diskin o bölümünün kullanıma açık ilan edilir. Dolayısıyla o bölüme başka programlar bir şey yazmamışsa ve belli şartlara da haizsek, silinen dosyayı geri getirmemiz mümkündür. >> "rename" fonksiyonu: Bir dosyanın ismini değiştirmek için kullanılır. Fonksiyonun prototipi şu şekildedir: #include int rename(const char *old, const char *new); Fonksiyon birinci parametresi ile ismi değiştirilecek dosyanın ismini almaktadır. İkinci parametre ile bu dosyanın yeni ismini almaktadır. Başarı durumunda "0", hata durumunda "0" dışı bir değer döndürmektedir. Eğer yeni isim halihazırda başka dosya ismi olarak kullanılıyorsa, sonucun ne olacağı "Implementation Defined" biçimindedir. * Örnek 1, Bu programı ilk çalıştırdığımızda ismin değiştiğini, ikinci ve sonraki çalıştırmalarda işlemin başarısız olduğu görülecektir. #include #include int main(void) { /* # OUTPUT # Ok... */ if (rename("test.txt", "mest.txt")) { fprintf(stderr, "cannot rename the file...\n"); exit(EXIT_FAILURE); } puts("Ok...\n"); return 0; } * Örnek 2, Son olarak başka dizin içerisinden de isim verebiliriz. Bu durumuda ilgili dosya bir nevi taşınacaktır. #include #include int main(void) { /* # OUTPUT # */ if (rename("test.txt", "C:\\Users\\ahmet\\Desktop\\aqua.txt")) { fprintf(stderr, "cannot rename the file...\n"); exit(EXIT_FAILURE); } puts("Ok...\n"); return 0; } >> "system" fonksiyonu: Yine standart bir C fonksiyonudur. Argüman olarak aldığı ifadelerle işletim sisteminin terminal programını çalıştırır. Fonksiyonun prototipi aşağıdaki gibidir: #include int system(const char *command); Fonksiyon parametre olarak çalıştırılacak terminal komutlarını alır. Geri dönüş değeri ise derleyici yazanların isteğine bırakılmıştır. Ancak Windows ve UNIX türevi sistemlerde fonksiyon başarı durumunda "0", hata durumunda "0" dışı bir değer döndürmektedir. Eğer fonksiyona "NULL" değerini geçersek, ilgili sistemde bir terminal programının olup olmadığını sorgulamış oluruz. Bu durumda "0" dışı herhangi bir değere dönerse ilgili sistemde terminal programı vardır, "0" değerine dönerse ilgili sistemde terminal programı yoktur demektir. Fonksiyon detaylı olması hasebiyle ileride tekrardan ele alınacaktır. Burada dikkat etmemiz gereken şey ise bu fonksiyona geçeceğimiz argümanlar belli bir sistemdeki terminal programları için anlamlı olmalıdır. * Örnek 1, Aşağıdaki çıktıyı Windows işletim sistemindeki terminal programında "dir main.c" yaparak da elde edebiliriz. #include #include int main(void) { /* # OUTPUT # Volume in drive D is Archieve Volume Serial Number is 8CDD-C14B Directory of D:\CSD\SysProg-1\src\CFunctions 06/12/2023 06:08 PM 152 main.c 1 File(s) 152 bytes 0 Dir(s) 718,262,374,400 bytes free */ system("dir main.c"); return 0; } * Örnek 2, Aşağıdaki çıktıyı UNIX türevi bir işletim sisteminin "shell" programında "ls -l c_functions.c" yaparak da elde edebiliriz. #include #include int main(void) { /* # OUTPUT # -rw-r--r-- 1 ahmopasa ahmopasa 449 Jun 12 18:10 c_functions.c */ system("ls -l c_functions.c"); return 0; } * Örnek 3, #include #include int main(void) { /* # OUTPUT # Volume in drive D is Archieve Volume Serial Number is 8CDD-C14B Directory of D:\CSD\SysProg-1\src\CFunctions 06/12/2023 06:08 PM 152 main.c 1 File(s) 152 bytes 0 Dir(s) 718,262,374,400 bytes free */ if (system(NULL)) /* "0" ile dönmesi durumunda bir terminal programının olmadığı anlaşılacaktır. */ system("dir main.c"); else printf("terminal program does not exist!...\n"); return 0; } * Örnek 4, Aşağıdaki programda "system" fonksiyonuna geçilen komut aslında Windows işletim sistemindeki terminal programında anlamlıdır. #include #include int main(void) { /* # OUTPUT # Volume in drive D is Archieve Volume Serial Number is 8CDD-C14B Directory of D:\CSD\SysProg-1\src\CFunctions 06/12/2023 06:08 PM 152 main.c 1 File(s) 152 bytes 0 Dir(s) 718,262,374,400 bytes free */ if (system(NULL)) system("dir main.c"); else printf("terminal program does not exist!...\n"); printf("Press ENTER to continue!...\n"); getchar(); system("cls"); /* Linux işletim sistemi için "cls" yerine "clear" yazılmalıdır. */ return 0; } > Hatırlatıcı Notlar: >> Bir fonksiyon bir işi başlatsa fakat onun bitmesini beklemezse, bu duruma asenkron işlemler denir. Eğer başlattığı işin bitmesini bekleseydi, senkron işlemler denilecekti. Senkron işlemlerde beklenen işin bittiği garanti altındadır. >> "thread-safe" olması için statik ömürlü nesne kullanmaması gerekmektedir. >> Algoritma dünyasında "merge" işlemi demek kendi içerisinde sıralı dizileri birleştirerek yine sıralı hale getirmektir. >> "strdup" fonksiyonunun temsili implementasyonu: * Örnek 1, char* my_strdup(const char* str) { char* strbuf; if((strbuf = (char*)malloc(strlen(str) + 1)) == NULL) return NULL; return strcpy(strbuf, str); } >> "printf" ve türevi fonksiyonlarla ile yazıların arasında değişken uzunlukta boşluk karakteri eklemek için: * Örnek 1, Uzun Yol: #include int main() { /* # OUTPUT # width: 5 Used Format: %-5d%5d 0 0 1 1 2 4 3 9 4 16 5 25 6 36 7 49 8 64 9 81 */ int width; char format[64]; printf("width: "); scanf("%d", &width); snprintf(format, 64, "%%-%dd%%5d\n", width); printf("Used Format: %s\n", format); for (int i = 0; i < 10; ++i) { printf(format, i, i*i); } return 0; } * Örnek 2, Aşağıdaki '*' karakteri için de ekstradan değişkeni argüman olarak geçmemiz gerekmektedir. #include int main() { /* # OUTPUT # width: 5 0 0 1 1 2 4 3 9 4 16 5 25 6 36 7 49 8 64 9 81 */ int width; char format[64]; printf("width: "); scanf("%d", &width); for (int i = 0; i < 10; ++i) { printf("%-*d%5d\n", width, i, i*i); } return 0; }