> GNU stili komut satırı argümanları: >> Bir takım belirlemeleri de gerçekleştirmek için "-" karakteri ve bir harf karakterini kullanıyoruz. Bunlara da genel olarak "option" denmektedir. Örneğin, "ls" komutu ilgili dizindeki dosyaların isimlerini ekrana basmaktadır. Bu komutu "-l" seçeneği ile kullanırsak ilgili dosyaların detaylarını da ekrana yazdıracaktır (bkz. "ls -l"). >> Ekseriyet ile bu komutlar birer programlardır da. >> GNU stili komut satırı argümanlarını üç ana başlıkta incelememiz mümkündür. Bunlar, >>> Argümansız Seçenekler (Options without an Argument) : "ls -l" komutunu ele alırsak, buradaki "-l" seçeneği argümansız bir seçenektir. >>> Argumanlı Seçenekler (Options with an Argument) : İş bu seçeneğin yanına ek olarak ekstra bir argüman geçmemiz gereken seçeneklerdir. Örneğin, "gcc sample.c -o my_file_name" komutundaki "-o" argümanlı bir seçenek olup, "my_file_name" ise bunun argümanıdır. Argümanlı bir seçenek girdiğimiz zaman devamında yazacaklarımız onun argümanını teşkil etmektedir. >>> Seçeneksiz Argümanlar (Arguments without an Option) : Hiç bir seçeneğe ait olmayan argümanlardır. >>> Özetle, "gcc sample.c -o my_file_name -S" komutundaki, "sample.c" Seçeneksiz Argüman, "-o" Argümanlı Seçeneği ve "-S" ise Argümansız Seçeneği belirtmektedir. Buradaki "my_file_name" ise "-o" seçeneğine ait bir argüman olarak değerlendirilecektir. >> Bazı özel durumlar haricinde, seçenekler arasındaki sıranın bir önemi yoktur. Örneğin, aşağıdaki her iki komut da aynı çıktıyı üretecektir; "ls -l -i" "ls -i -l" >> Yine GNU stilinde seçenekler "Case-Sensitive" bir özelliğe sahiptirler. >> Birden fazla argümansız seçeneği, aralarında boşluk ve "-" karakteri olmadan, yazmamız mümkündür. Örneğin, aşağıdaki komutlar aynı çıktıyı üretecektir; "ls -l -i" "ls -i -l" "ls -il" "ls -li" >> Fakat argümanlı seçenekler ile argümansız seçenekleri birleştirerek yazmaktan kaçınmalıyız. Her ne kadar programlar bunu kabul ediyor olsalar da iyi bir teknik olduğu söylenemez. Örneğin, "./sample -a -b ali" "./sample -ab ali" >> Belirli bir dönemden sonra Uzun Seçenek terimi de bu stile dahil edildi. Birden fazla karakter içeren seçenekler Uzun Seçenek olarak geçmektedir. Bu tip seçenekleri kullanmak için "-" karakteri yerine "--" karakterini kullanmalıyız. Örneğin, "--ali" seçeneğinde "ali" seçeneğin kendi ismidir. Uzun Seçenekler ise kendi bünyesinde üçe ayrılmaktadır. Bunlar, >>> Argümansız Seçenekler (Options without an Argument) : "./sample --wrap" komutunu ele aldığımızda, buradaki "--wrap" seçeneği argümansız seçenektir. >>> Argumanlı Seçenekler (Options with an Argument) : "./sample --size 100" komutundaki "--size 100" ikilisi ise argümanlı seçeneği işaret etmektedir. >>> İsteğe Bağlı Argüman İçeren Uzun Seçenek (Options with an Optional Argument): "./sample --myWrap=100" komutundaki "--myWrap=100" ise iş bu seçeneği işaret etmektedir. İsteğe bağlı olduğu için, "./sample --myWrap" şeklinde de kullanabiliriz. Eğer bu şekil yerine "--myWrap 100" yazarsak Argümanlı Seçenek gibi algılanacaktır. >>>> Ayrıca bir uzun seçeneği "=" karakterini kullanarak da yazabiliriz. Örneğin, aşağıdaki komutlar aynı çıktıyı üretecektir; "head --lines 3 sample.c" "head --lines=3 sample.c" Fakat İsteğe Bağlı Argüman İçeren Uzun Seçeneklere argüman geçeceksek, "=" KULLANMAK ZORUNDAYIZ. >> Artık yer yer kısa seçenek ve uzun seçenek birbirinin alternatifi haline gelmiştir. Örneğin, "-m" seçeneği ile "--mode" seçeneği aynı şeyi yapmaktadır. >> İsteğe Bağlı Argüman İçeren Kısa Seçenek YOKTUR. Fakat kendi programlarımızda böyle bir uygulamaya gidebiliriz. >> Ama kısa seçeneği ama uzun seçeneği, varsa, argümanı izlemek zorundadır. >> Argümanlı kısa seçeneği, argümanı ile kombine bir şekilde yazabiliriz. Örneğin, aşağıdaki iki komut da aynı çıktıyı verecektir; "gcc sample.c -o my_file_name" "gcc sample.c -omy_file_name" Fakat bu kurala uymayanlarda da vardır. >> Aynı seçenekleri, ama argümanlı ama argümansız, tek bir komut içerisinde girmek herhangi bir hata mesajının ekrana yazılmasına neden olmaz. Çünkü GNU stilinde buna karşın bir kontrol mekanizması yazılmamıştır. > Komut satırı argümanlarının ayrıştırılması (bkz. "parsing"): >> Komut satırı argümanlarının ekrana bastırılması, * Örnek 1, programa geçilen komut satırı argümanlarının ekrana yazdırılması: #include "stdio.h" #include "unistd.h" int main(int argc, char **argv) { /* # INPUT # ./ex_01 -a -b --ceyhan denizli */ /* # OUTPUT # ./ex_01 -a -b --ceyhan denizli */ for (size_t i = 0; i < argc; i++) { puts(argv[i]); } } >> GNU stili bir ayrıştırma yapmak için iki adet "getopt" ve "getoptlong" POSIX fonksiyonu kullanılmaktadır. Burada "getoptlong" fonksiyonu, "getopt" fonksiyonunu KAPSAMAKTADIR. >>> "getopt" fonksiyonu, aşağıdaki parametrik yapıya sahiptir; #include int getopt(int argc, char * const argv[], const char *optstring); Fonksiyonun birinci ve ikinci parametreleri, "main" fonksiyonuna geçilen parametrelerdir. Üçüncü parametre olan "optstring" ise bizim belirlediğimiz seçeneklerin oluşturduğu bir karakter dizisidir. Bu diziye yazacağımız karakterlerin sıralamasının bir önemi yoktur fakat eşleştirme sırasında bu sıranın gözetilmesi tavsiye edilmektedir. Ek olarak "unistd.h" başlık dosyası bir çok önemli POSIX fonksiyonunun imzasını barındırmaktadır. Fakat unutmamak gerekir ki bu başlık dosyası standart C kütüphanesi değil, bir POSIX kütüphanesidir. İş bu fonksiyonun geri dönüş değeri, bulmuş olduğu ilk argümandır fakat "int" türündendir. Fakat Argümansız Seçenekler gördüğünde geriye o karakterin "int" halini, bütün argümanlar "parse" edildiğinde ise geriye "-1" değerini döndürmektedir. Bu durumda, her çağırmada bulunan bir seçenek döndürülüyorsa, bir "while" döngüsü içerisinde bu fonksiyonu kullanabiliriz. * Örnek 1, "getopt()" fonksiyonunun çağrılması: #include "stdio.h" #include "unistd.h" int main(int argc, char **argv) { /* # INPUT # ./ex_01 -a -b -c Ahmo -d -e Memo */ /* # OUTPUT # -a option is given. -b option is given. -c option is given. -d option is given. -e option is given. */ int result; /* * @param a, Argümansız Seçenek olan "-a" yı temsil etmektedir. * @param b, Argümansız Seçenek olan "-b" yi temsil etmektedir. * @param c, Argümanlı Seçenek olan "-c" yi temsil etmektedir. * @param d, Argümansız Seçenek olan "-d" yi temsil etmektedir. * @param e, Argümanlı Seçenek olan "-e" yi temsil etmektedir. */ const char* myArgumentList = "abc:de:"; while ((result = getopt(argc, argv, myArgumentList)) != -1) { switch (result) { case 'a': fprintf(stdout, "-a option is given.\n"); break; case 'b': fprintf(stdout, "-b option is given.\n"); break; case 'c': fprintf(stdout, "-c option is given.\n"); break; case 'd': fprintf(stdout, "-d option is given.\n"); break; case 'e': fprintf(stdout, "-e option is given.\n"); break; } } } İş bu fonksiyon, Seçeneksiz Argümanları, ilgili "buffer" ın sonuna ötelemektedir. İş bu "buffer", fonksiyonun gövdesinde hayata gelmektedir. "optind" isimli "int" türden değişken ise iş bu Seçeneksiz Argümanların, öteleme işleminden sonraki, başladığı yeri göstermektedir. Bu "optind" isimli değişken de yine "unistd.h" isimli başlık dosyasında bildirilmiştir. Fakat öteleme işlemi sonrasında iş bu Seçeneksiz Argümanların kendi içindeki sıralaması, bizim girdiğimiz sıralamaya göre olacağı GARANTİ DEĞİLDİR. * Örnek 1, #include "stdio.h" #include "unistd.h" int main(int argc, char **argv) { /* # INPUT # ./ex_01 -a -b -c Ahmo -d -e Memo TheOptionWithoutAnArgument */ /* # OUTPUT # -a option is given. -b option is given. -c option is given. -d option is given. -e option is given. List of Options without an Argument: TheOptionWithoutAnArgument */ /* * @param a, Argümansız Seçenek olan "-a" yı temsil etmektedir. * @param b, Argümansız Seçenek olan "-b" yi temsil etmektedir. * @param c, Argümanlı Seçenek olan "-c" yi temsil etmektedir. * @param d, Argümansız Seçenek olan "-d" yi temsil etmektedir. * @param e, Argümanlı Seçenek olan "-e" yi temsil etmektedir. */ const char* myArgumentList = "abc:de:"; int result; while ((result = getopt(argc, argv, myArgumentList)) != -1) { switch (result) { case 'a': fprintf(stdout, "-a option is given.\n"); break; case 'b': fprintf(stdout, "-b option is given.\n"); break; case 'c': fprintf(stdout, "-c option is given.\n"); break; case 'd': fprintf(stdout, "-d option is given.\n"); break; case 'e': fprintf(stdout, "-e option is given.\n"); break; } } /* * Buradaki "optind" isimli değişken, Seçeneksiz Argümanların "buffer" * içerisindeki indisini belirtmektedir. "argc" ise toplam eleman sayısıdır. */ fprintf(stdout,"List of Options without an Argument:\n"); for (int i = optind; i < argc; i++) { puts(argv[i]); } } Argümanlı Seçeneklerde ise devreye "optarg" isimli gösterici girmektedir. İş bu gösterici yine "unistd.h" isimli başlık dosyasında bildirilmiş olup, "getopt" fonksiyonu ile böyle bir seçeneğe denk geldiğinizde, ilgili göstericimiz, bu seçeneğin argümanını gösterir hale gelmektedir. Eğer "getopt" başka bir argümanlı seçenek yakalarsa, bu sefer "optarg" isimli göstericimiz onun argümanını gösterecektir. "optarg" isimli göstericinin gösterdiği yer "static" bir alan olduğundan, "strcpy" isimli fonksiyonu çağırmamıza gerek yoktur. * Örnek 1, Argümanlı Seçeneklerde ilgili seçeneğe ait argümanın tutulması: #include "stdio.h" #include "unistd.h" int main(int argc, char **argv) { /* # INPUT # ./ex_01 -a -b -c Ahmo -d -e Memo TheOptionWithoutAnArgument */ /* # OUTPUT # -a option is given. -b option is given. -c option is given. -d option is given. -e option is given. List of Options without an Argument: TheOptionWithoutAnArgument List of Arguments that belong to Options: Argument [Ahmo] belongs to the option -c Argument [Memo] belongs to the option -e */ /* * @param a, Argümansız Seçenek olan "-a" yı temsil etmektedir. * @param b, Argümansız Seçenek olan "-b" yi temsil etmektedir. * @param c, Argümanlı Seçenek olan "-c" yi temsil etmektedir. * @param d, Argümansız Seçenek olan "-d" yi temsil etmektedir. * @param e, Argümanlı Seçenek olan "-e" yi temsil etmektedir. */ const char* myArgumentList = "abc:de:"; const char* c_arg, *e_arg; int result; while ((result = getopt(argc, argv, myArgumentList)) != -1) { switch (result) { case 'a': fprintf(stdout, "-a option is given.\n"); break; case 'b': fprintf(stdout, "-b option is given.\n"); break; case 'c': fprintf(stdout, "-c option is given.\n"); c_arg = optarg; break; case 'd': fprintf(stdout, "-d option is given.\n"); break; case 'e': fprintf(stdout, "-e option is given.\n"); e_arg = optarg; break; } } fprintf(stdout,"List of Options without an Argument:\n"); for (int i = optind; i < argc; i++) { puts(argv[i]); } fprintf(stdout, "List of Arguments that belong to Options:\n"); fprintf(stdout, "Argument [%s] belongs to the option -c\n", c_arg); fprintf(stdout, "Argument [%s] belongs to the option -e\n", e_arg); } Bütün eşleme işlemleri tamamlandıktan sonra, yapacağımız şeyleri ilgili "while" döngüsü dışında yapmamız tavsiye olunur. Bunu gerçekleştirmek için de her bir seçeneğe karşılık gelen birer "flag" tanımlamamız yeterlidir. * Örnek 1, #include "stdio.h" #include "unistd.h" int main(int argc, char **argv) { /* # INPUT # ./ex_01 -a -b -c Ahmo -d -e Memo TheOptionWithoutAnArgument */ /* # OUTPUT # -a option is given. -b option is given. -c option is given with an argument [Ahmo] -d option is given. -e option is given with an argument [Memo]. List of Options without an Argument: TheOptionWithoutAnArgument */ /* * @param a, Argümansız Seçenek olan "-a" yı temsil etmektedir. * @param b, Argümansız Seçenek olan "-b" yi temsil etmektedir. * @param c, Argümanlı Seçenek olan "-c" yi temsil etmektedir. * @param d, Argümansız Seçenek olan "-d" yi temsil etmektedir. * @param e, Argümanlı Seçenek olan "-e" yi temsil etmektedir. */ const char* myArgumentList = "abc:de:"; // Harflerin sırasını unutmayalım. const char* c_arg, *e_arg; // Seçeneklerimizin sıralamasını unutmayalım. int a_flag, b_flag, c_flag, d_flag, e_flag; // Seçeneklerimizin sıralamasını unutmayalım. a_flag = b_flag = c_flag = d_flag = e_flag = 0; int result; while ((result = getopt(argc, argv, myArgumentList)) != -1) { switch (result) { // YİNE SEÇENEKLERİMİZİN SIRALAMASINI GÖZ ÖNÜNDE BULUNDURDUK. case 'a': a_flag = 1; break; case 'b': b_flag = 1; break; case 'c': c_flag = 1; c_arg = optarg; break; case 'd': d_flag = 1; break; case 'e': e_flag = 1; e_arg = optarg; break; } } // YİNE SEÇENEKLERİMİZİN SIRALAMASINI GÖZ ÖNÜNDE BULUNDURDUK. if (a_flag) { fprintf(stdout, "-a option is given.\n"); } if (b_flag) { fprintf(stdout, "-b option is given.\n"); } if (c_flag) { fprintf(stdout, "-c option is given with an argument [%s]\n", c_arg); } if (d_flag) { fprintf(stdout, "-d option is given.\n"); } if (e_flag) { fprintf(stdout, "-e option is given with an argument [%s].\n", e_arg); } fprintf(stdout,"List of Options without an Argument:\n"); for (int i = optind; i < argc; i++) { puts(argv[i]); } } Geçersiz bir seçenek ya da argümanı girilmeyen argümanlı seçenek girildiğinde "stderr" akımına hata mesajı yazarlar. Fakat bu hata mesajının işlenmesini bizler üzerimize almak istiyorsak "opterr" isimli değişkenin değerini sıfıra çekmemiz gerekiyor. Yine bu değişken de "unistd.h" isimli başlık dosyasında bildirilmiştir. Eğer bizler de unutursak herhangi bir mesaj yazılmayacaktır. "getopt" fonksiyonu ise iş bu durumda "?" karakterini döndürür. İş bu mesajı düzenlemek için de "optopt" isimli göstericiyi kullanacağız. Sorun çıkartan hangi seçenek ise o turda bu gösterici onu gösterecektir. * Örnek 1, hata mesajının bizler tarafından ele alınması: #include "stdio.h" #include "unistd.h" int main(int argc, char **argv) { /* # INPUT # ./ex_01 -a -b -f -c */ /* # OUTPUT # [-f] is an invalid option! [-c] must have an argument! -a option is given. -b option is given. */ /* * @param a, Argümansız Seçenek olan "-a" yı temsil etmektedir. * @param b, Argümansız Seçenek olan "-b" yi temsil etmektedir. * @param c, Argümanlı Seçenek olan "-c" yi temsil etmektedir. * @param d, Argümansız Seçenek olan "-d" yi temsil etmektedir. * @param e, Argümanlı Seçenek olan "-e" yi temsil etmektedir. */ const char* myArgumentList = "abc:de:"; // Harflerin sırasını unutmayalım. const char* c_arg, *e_arg; // Seçeneklerimizin sıralamasını göz önünde bulundurduk. int a_flag, b_flag, c_flag, d_flag, e_flag; // Seçeneklerimizin sıralamasını göz önünde bulundurduk. a_flag = b_flag = c_flag = d_flag = e_flag = 0; opterr = 0; // Geçersiz girişlerde hata mesajının stili bize bağlıdır. int result; while ((result = getopt(argc, argv, myArgumentList)) != -1) { switch (result) { // YİNE SEÇENEKLERİMİZİN SIRALAMASINI GÖZ ÖNÜNDE BULUNDURDUK. case 'a': a_flag = 1; break; case 'b': b_flag = 1; break; case 'c': c_flag = 1; c_arg = optarg; break; case 'd': d_flag = 1; break; case 'e': e_flag = 1; e_arg = optarg; break; case '?': if (optopt == 'c' || optopt == 'e') fprintf(stderr, "[-%c] must have an argument!\n", optopt); else fprintf(stderr, "[-%c] is an invalid option!\n", optopt); break; } } // YİNE SEÇENEKLERİMİZİN SIRALAMASINI GÖZ ÖNÜNDE BULUNDURDUK. if (a_flag) { fprintf(stdout, "-a option is given.\n"); } if (b_flag) { fprintf(stdout, "-b option is given.\n"); } if (c_flag) { fprintf(stdout, "-c option is given with an argument [%s]\n", c_arg); } if (d_flag) { fprintf(stdout, "-d option is given.\n"); } if (e_flag) { fprintf(stdout, "-e option is given with an argument [%s].\n", e_arg); } /* * "optind", Seçeneksiz Argümanların indis bilgisini tutmaktadır. "argc" ise ilgili * "buffer" alanının toplam eleman sayısını. Bu ikisinin birbirine eşit olmaması, * en az bir Seçeneksiz Argüman olduğunu göstermektedir. Eğer her ikisi de eşitse * programın akışı hem "if" hem "for" gövdesine girmeyecektir. */ if (optind != argc) fprintf(stdout,"List of Options without an Argument:\n"); for (int i = optind; i < argc; i++) { puts(argv[i]); } } Bir hata ile karşılaşıldığında programın "parsing" işleminin tamamlanmasının ardından sonlandırılması gerekiyor. Geçerli seçeneklerin işlenmesi TAVSİYE EDİLMEZ. * Örnek 1, AŞAĞIDAKİ KALIP DİĞER PROGRAMLARDA KULLANMAK İÇİN UYGUNDUR. #include "stdio.h" #include "unistd.h" #include "stdlib.h" int main(int argc, char **argv) { /* # INPUT # ./ex_01 -a -b -f -c */ /* # OUTPUT # [-f] is an invalid option! [-c] must have an argument! */ /* * @param a, Argümansız Seçenek olan "-a" yı temsil etmektedir. * @param b, Argümansız Seçenek olan "-b" yi temsil etmektedir. * @param c, Argümanlı Seçenek olan "-c" yi temsil etmektedir. * @param d, Argümansız Seçenek olan "-d" yi temsil etmektedir. * @param e, Argümanlı Seçenek olan "-e" yi temsil etmektedir. */ const char* myArgumentList = "abc:de:"; // Harflerin sırasını unutmayalım. const char* c_arg, *e_arg; // Seçeneklerimizin sıralamasını göz önünde bulundurduk. int a_flag, b_flag, c_flag, d_flag, e_flag, err_flag; // Seçeneklerimizin sıralamasını göz önünde bulundurduk. a_flag = b_flag = c_flag = d_flag = e_flag = err_flag = 0; opterr = 0; // Geçersiz girişlerde hata mesajının stili bize bağlıdır. int result; while ((result = getopt(argc, argv, myArgumentList)) != -1) { switch (result) { // YİNE SEÇENEKLERİMİZİN SIRALAMASINI GÖZ ÖNÜNDE BULUNDURDUK. case 'a': a_flag = 1; break; case 'b': b_flag = 1; break; case 'c': c_flag = 1; c_arg = optarg; break; case 'd': d_flag = 1; break; case 'e': e_flag = 1; e_arg = optarg; break; case '?': if (optopt == 'c' || optopt == 'e') fprintf(stderr, "[-%c] must have an argument!\n", optopt); else fprintf(stderr, "[-%c] is an invalid option!\n", optopt); err_flag = 1; } } /* * Seçenekleri ayırt ettikten sonra gördük ki bir hata durumu var. Artık bu aşamadan * sonra ilerlemek TAVSİYE EDİLMEZ. Yani her şey hatasız olmalıdır. */ if (err_flag) { exit(EXIT_FAILURE); } // YİNE SEÇENEKLERİMİZİN SIRALAMASINI GÖZ ÖNÜNDE BULUNDURDUK. if (a_flag) { fprintf(stdout, "-a option is given.\n"); } if (b_flag) { fprintf(stdout, "-b option is given.\n"); } if (c_flag) { fprintf(stdout, "-c option is given with an argument [%s]\n", c_arg); } if (d_flag) { fprintf(stdout, "-d option is given.\n"); } if (e_flag) { fprintf(stdout, "-e option is given with an argument [%s].\n", e_arg); } if (optind != argc) fprintf(stdout,"List of Options without an Argument:\n"); for (int i = optind; i < argc; i++) { puts(argv[i]); } } Pekiştirici bir örnek: Sırasıyla "-a", "-m", "-d" ve "-s" seçenekleri için toplama, çarpma, bölme ve çıkarma işlemlerini gerçekleştiren bir program yazalım. * Örnek 1, #include "stdio.h" #include "stdlib.h" #include "unistd.h" int main(int argc, char** argv) { /* # INPUT # i. ./ex_01 -a 10 20 ii. ./ex_01 -m 10 20 iii. ./ex_01 -d 10 20 iv. ./ex_01 -s 10 20 v. ./ex_01 -m 10 20 -M result */ /* # OUTPUT # i. 30.000000 ii. 200.000000 iii. 0.500000 iv. -10.000000 v. result: 200.000000 */ int a_flag, m_flag, d_flag, s_flag, M_flag, err_flag; a_flag = m_flag = d_flag = s_flag = M_flag = err_flag = 0; const char* M_arg; opterr = 0; int result; while ((result = getopt(argc, argv, "amdsM:")) != -1) { switch (result) { case 'a': a_flag = 1; break; case 'm': m_flag = 1; break; case 'd': d_flag = 1; break; case 's': s_flag = 1; break; case 'M': M_flag = 1; M_arg = optarg; break; case '?': err_flag = 1; if (optopt == 'M') fprintf(stderr, "[-M] has no argument!\n"); else fprintf(stderr, "[-%c] is an invalid option!\n", optopt); } } if (err_flag) { exit(EXIT_FAILURE); } if (a_flag + m_flag + d_flag + s_flag == 0) { fprintf(stderr, "At least one -[amds] option must be passed.!\n"); exit(EXIT_FAILURE); } if (a_flag + m_flag + d_flag + s_flag > 1) { fprintf(stderr, "Only one option must be passed!\n"); exit(EXIT_FAILURE); } if (argc - optind != 2) { fprintf(stderr, "Two number must be passed as argument!\n"); exit(EXIT_FAILURE); } double argOne, argTwo; argOne = atof(argv[optind]); argTwo = atof(argv[optind + 1]); double calc_result; if (a_flag) { calc_result = argOne + argTwo; } else if (m_flag) { calc_result = argOne * argTwo; } else if (d_flag) { calc_result = argOne / argTwo; } else { calc_result = argOne - argTwo; } if (M_flag) { fprintf(stdout, "%s: %f", M_arg, calc_result); } else { fprintf(stdout, "%f\n", calc_result); } } >> GNU stili bir ayrıştırma yapmak için iki adet "getopt" ve "getoptlong" POSIX fonksiyonu bulunduğunu ve "getoptlong" fonksiyonunun, "getopt" fonksiyonunu kapsadığını daha önce açıklamıştık. >>> "getopt_long" fonksiyonu, aşağıdaki parametrik yapıya sahiptir; #include int getopt_long( int argc, char * const argv[], const char *optstring, const struct option *longopts, int *longindex ); Fonksiyonun ilk üç parametresi "getopt" fonksiyonunun parametresiyle birebir aynıdır. Dördüncü parametre ise elemanları "struct option" türden olan bir dizinin başlangıç adresidir ve bu dizinin son elemanı olan yapı nesnesinin bütün elemanları NULL değerinde olmalıdır. Bu yapı ise aşağıdaki biçimdedir; #include struct option { const char *name; int has_arg; int *flag; int val; }; Yapının, -> "name", "const char*" türünden bir değişken olup, ilgili uzun seçeneğin adını tutmaktadır. -> "has_arg", "int" türden bir değişken olup, argüman bilgisini tutmaktadır. Burada "no_argument", "required_argument" ve "optional_argumen" isimli sembolik sabitler kullanabiliriz. Bu isimler sırasıyla ilgili seçeneğin argümansız, argümanlı ya da isteğe bağlı argümanlı olduğunu belirtmektedir. -> "flag", "int*" türden bir değişken olup, uzun seçeneğin bulunması durumunda, bizim belirlediğimiz rakamı iş bu adrese yazmak için kullanılmaktadır. NULL geçilmesi durumunda bu mekanizma devre dışı kalacaktır. -> "val", "int" türden bir değişken olup, uzun seçeneğin bulunması durumunda, iş bu "getopt_long" fonksiyonunun ne ile döndüreceğini belirtmek için kullanılır. Eğer üçüncü parametreye bir adres bilgisi geçersek, iş bu değer, üçüncü parametreye geçilen adrese yazılacaktır. Açıkçası bu dördüncü parametre pek kullanılmaz, dolayısıyla fonksiyonun bu parametresine NULL değerini geçebiliriz. Öte yandan, aynı anda ya "getopt" ya da "getopt_long" kullanamayız. Her ikisini de kullandığımız zaman bir karışma söz konusu olacaktır. İş bu "getopt_long" fonksiyonunun kullanılması, "getopt" fonksiyonuna nazaran daha karmaşık olduğu için, uzun seçenek kullanmadığımız zamanlarda direkt "getopt" fonksiyonunu kullanabiliriz. Çünkü aslında kısa seçenekler söz konusu olduğunda her iki fonksiyon da aynı sonucu üretecektir. Fonksiyonun beşinci parametresine ilerleyen vakitlerde değinilecektir. * Örnek 1, "getopt_long" fonksiyonunu, "getopt" fonksiyonu gibi kullanmak: #include "stdio.h" #include "stdlib.h" #include "unistd.h" #include "getopt.h" int main(int argc, char** argv) { /* # INPUT # */ /* # OUTPUT # */ // Aşağıdaki kullanım şekilleri aynı sonucu üretecektir; //getopt(argc, argv, "ab:"); getopt_long(argc, argv, "ab:"); } "getopt" fonksiyonunu çağırma şeklimiz, iş bu fonksiyon için de geçerlidir. "-1" değeri dönene kadar iş bu fonksiyon çağrılacaktır. Kısa seçenek buldu ise o kısa seçeneğin kendisini, uzun seçenek buldu ise "struct option" türünden değişkenin dördüncü parametresini döndürecektir. Burada "struct option" türden yapı nesnesinin üçüncü parametresine NULL geçilmiştir. * Örnek 1, #include "stdio.h" #include "stdlib.h" #include "unistd.h" #include "getopt.h" int main(int argc, char** argv) { /* # INPUT # ./ex_01 -a -b TheArgumentOfb --size --length 2000 --number=31 */ /* # OUTPUT # -a option was given. -b option was given with an argument of [TheArgumentOfb]. --size option was given. --length option was given with an argument of [2000]. --number option was given with an argument of [31]. */ /**type "struct option": * @param name, "const char*" türünden bir değişken olup, ilgili uzun seçeneğin adını tutmaktadır. * @param has_arg, "int" türden bir değişken olup, argüman bilgisini tutmaktadır. Burada no_argument", * "required_argument" ve "optional_argumen" isimli sembolik sabitler kullanabiliriz. Bu isimler sırasıyla * argümansız, argümanlı ya da isteğe bağlı argümanlı olduğunu belirtmektedir. * @param flag, "int*" türden bir değişken olup, uzun seçeneğin bulunması durumunda, bizim belirlediğimiz * rakamı iş bu adrese yazmak için kullanılmaktadır. NULL geçilmesi durumunda bu mekanizma devre dışı * kalacaktır. * @param val, "int" türden bir değişken olup, uzun seçeneğin bulunması durumunda, iş bu "getopt_long" * fonksiyonunun * ne ile döneceğini belirtmek için kullanılır. Eğer üçüncü parametreye bir adres bilgisi de geçersek, * iş bu değer, * üçüncü parametreye geçilen adrese yazılacaktır. ******************************************************************************************************** * Aşağıdaki "options" dizisinin son elemanı olan yapı nesnesinin bütün elemanları NULL değerinde * olmalıdır. */ struct option options[] = { {"size", no_argument, NULL, 1}, {"length", required_argument, NULL, 2}, {"number", optional_argument, NULL, 3}, {0, 0, 0, 0} }; char* b_arg, *length_arg, *number_arg = NULL; opterr = 0; int result; while ((result = getopt_long(argc, argv, "ab:", options, NULL)) != -1) { switch (result) { case 'a': fprintf(stdout, "-a option was given.\n"); break; case 'b': b_arg = optarg; fprintf(stdout, "-b option was given with an argument of [%s].\n", b_arg); break; case 1: fprintf(stdout, "--size option was given.\n"); break; case 2: length_arg = optarg; fprintf(stdout, "--length option was given with an argument of [%s].\n", length_arg); break; case 3: number_arg = optarg; fprintf(stdout, "--number option was given with an argument of [%s].\n", number_arg); break; } } } İş bu fonksiyonu kullanırken aşağıdaki hata durumlarında ilgili "getopt_long" fonksiyonu "?" karakteri döndürmektedir. Bu hata durumları, >>>> Olmayan bir kısa seçeneğin girilmesi durumunda "optopt", olmayan bu kısa seçeneği bize vermektedir. >>>> Olmayan bir uzun seçeneğin girilmesi durumunda "optopt" değeri sıfıra çekiliyor. Fakat girilen bu seçeneğin ne olduğunu bize verememektedir. >>>> Argümanlı bir kısa seçeneğin argümanının girilmemiş olması durumunda "optopt", olmayan bu kısa seçeneği bize vermektedir. >>>> Argümanlı bir uzun seçeneğin argümanının girilmemiş olması durumunda ise "struct option" yapı nesnesinin dördüncü veri elemanını bize döndürecektir. Aşağıda bu konuya ilişkin örnekler verilmiştir: * Örnek 1, #include "stdio.h" #include "stdlib.h" #include "unistd.h" #include "getopt.h" int main(int argc, char** argv) { /* # INPUT # ./ex_01 -a -b TheArgumentOfb --all --length 3000 --number=4000 5000 6000 */ /* # OUTPUT # -a option was given. -b option was given with an argument of [TheArgumentOfb]. --all option was given. --length option was given with an argument of [3000]. --number option was given with an argument of [4000]. Arguments without an options 5000 6000 */ /**type "struct option": * @param name, "const char*" türünden bir değişken olup, ilgili uzun seçeneğin adını tutmaktadır. * @param has_arg, "int" türden bir değişken olup, argüman bilgisini tutmaktadır. Burada no_argument", * "required_argument" ve "optional_argumen" isimli sembolik sabitler kullanabiliriz. Bu isimler sırasıyla * argümansız, argümanlı ya da isteğe bağlı argümanlı olduğunu belirtmektedir. * @param flag, "int*" türden bir değişken olup, uzun seçeneğin bulunması durumunda, bizim belirlediğimiz * rakamı iş bu adrese yazmak için kullanılmaktadır. NULL geçilmesi durumunda bu mekanizma devre dışı kalacaktır. * @param val, "int" türden bir değişken olup, uzun seçeneğin bulunması durumunda, iş bu "getopt_long" fonksiyonunun * ne ile döneceğini belirtmek için kullanılır. Eğer üçüncü parametreye bir adres bilgisi de geçersek, iş bu değer, * üçüncü parametreye geçilen adrese yazılacaktır. */ struct option options[] = { {"all", no_argument, NULL, 1}, {"length", required_argument, NULL, 2}, {"number", optional_argument, NULL, 3}, {0, 0, 0, 0} }; char* b_arg, *length_arg, *number_arg = NULL; opterr = 0; int result; while ((result = getopt_long(argc, argv, "ab:", options, NULL)) != -1) { switch (result) { case 'a': fprintf(stdout, "-a option was given.\n"); break; case 'b': b_arg = optarg; fprintf(stdout, "-b option was given with an argument of [%s].\n", b_arg); break; case 1: fprintf(stdout, "--all option was given.\n"); break; case 2: length_arg = optarg; fprintf(stdout, "--length option was given with an argument of [%s].\n", length_arg); break; case 3: number_arg = optarg; fprintf(stdout, "--number option was given with an argument of [%s].\n", number_arg); break; case '?': { if (optopt == 'b') { fprintf(stderr, "-b option was given WITHOUT an argument!.\n"); } else if(optopt == 2) { fprintf(stderr, "--length option was given WITHOUT an argument\n"); } else if(optopt != 0) { fprintf(stderr, "invalid option: -%c\n", optopt); } else { fprintf(stderr, "invalid long option!\n"); } } } } if (optind != argc) { fprintf(stdout, "Arguments without an options\n"); for (size_t i = optind; i < argc; i++) { puts(argv[i]); } puts("\n"); } } * Örnek 2, #include "stdio.h" #include "stdlib.h" #include "unistd.h" #include "getopt.h" int main(int argc, char** argv) { /* # INPUT # ./ex_01 -a -b TheArgumentOfb --all --length 3000 --number=4000 5000 6000 */ /* # OUTPUT # -a option was given. -b option was given with an argument of [TheArgumentOfb]. --all option was given. --length option was given with an argument of [3000]. --number option was given with an argument of [4000]. Arguments without an options 5000 6000 */ /**type "struct option": * @param name, "const char*" türünden bir değişken olup, ilgili uzun seçeneğin adını tutmaktadır. * @param has_arg, "int" türden bir değişken olup, argüman bilgisini tutmaktadır. Burada no_argument", * "required_argument" ve "optional_argumen" isimli sembolik sabitler kullanabiliriz. Bu isimler sırasıyla * argümansız, argümanlı ya da isteğe bağlı argümanlı olduğunu belirtmektedir. * @param flag, "int*" türden bir değişken olup, uzun seçeneğin bulunması durumunda, bizim belirlediğimiz * rakamı iş bu adrese yazmak için kullanılmaktadır. NULL geçilmesi durumunda bu mekanizma devre dışı kalacaktır. * @param val, "int" türden bir değişken olup, uzun seçeneğin bulunması durumunda, iş bu "getopt_long" fonksiyonunun * ne ile döneceğini belirtmek için kullanılır. Eğer üçüncü parametreye bir adres bilgisi de geçersek, iş bu değer, * üçüncü parametreye geçilen adrese yazılacaktır. */ struct option options[] = { {"all", no_argument, NULL, 1}, {"length", required_argument, NULL, 2}, {"number", optional_argument, NULL, 3}, {0, 0, 0, 0} }; int a_flag, b_flag, all_flag, length_flag, number_flag, err_flag; a_flag = b_flag = all_flag = length_flag = number_flag = err_flag = 0; char* b_arg, *length_arg, *number_arg = NULL; opterr = 0; int result; while ((result = getopt_long(argc, argv, "ab:", options, NULL)) != -1) { switch (result) { case 'a': a_flag = 1; break; case 'b': b_flag = 1; b_arg = optarg; break; case 1: all_flag = 1; break; case 2: length_flag = 1; length_arg = optarg; break; case 3: number_flag = 1; number_arg = optarg; break; case '?': { err_flag = 1; if (optopt == 'b') { fprintf(stderr, "[ERROR] -b option was given WITHOUT an argument!.\n"); } else if(optopt == 2) { fprintf(stderr, "[ERROR] --length option was given WITHOUT an argument\n"); } else if(optopt != 0) { fprintf(stderr, "[ERROR] invalid option: -%c\n", optopt); } else { fprintf(stderr, "[ERROR] invalid long option!\n"); } } } } if (err_flag) { exit(EXIT_FAILURE); } if (a_flag) { fprintf(stdout, "-a option was given.\n"); } if (b_flag) { fprintf(stdout, "-b option was given with an argument of [%s].\n", b_arg); } if (all_flag) { fprintf(stdout, "--all option was given.\n"); } if (length_flag) { fprintf(stdout, "--length option was given with an argument of [%s].\n", length_arg); } if (number_flag) { if (number_arg != NULL) { fprintf(stdout, "--number option was given with an argument of [%s].\n", number_arg); } else { fprintf(stdout, "--number option was given without an argument of.\n"); } } if (optind != argc) { fprintf(stdout, "Arguments without an options\n"); for (size_t i = optind; i < argc; i++) { puts(argv[i]); } puts("\n"); } } "getopt_long" fonksiyonunun dördüncü parametresi olan "struct option" türünden değişkenin "flag" isimli veri elemanına NULL değeri geçilmediğinde, yani "int" türden bir değişkenin ADRESİ geçildiğinde, ilgili uzun seçenek bulunduğunda, geçilen adrese bilgiyi işliyor ve fonksiyon sıfır değeri ile geri dönüyor. Böylelikle ilgili örnekteki "while" bloğuna hiç girmeden ilgili uzun seçeneğin var bilgisini temin ediyoruz. Fakat seçeneğimiz bir argüman alıyorsa, aldığı argümanı temin etme şansımız KALMIYOR. Bu yöntem argüman almayan seçeneklerde kullanabiliriz. * Örnek 1, #include "stdio.h" #include "stdlib.h" #include "unistd.h" #include "getopt.h" int main(int argc, char** argv) { /* # INPUT # ./ex_01 -a -b TheArgumentOfb --all --length 3000 --number=4000 5000 6000 */ /* # OUTPUT # -a option was given. -b option was given with an argument of [TheArgumentOfb]. --all option was given. --length option was given with an argument of [3000]. --number option was given with an argument of [4000]. Arguments without an options 5000 6000 */ int a_flag, b_flag, all_flag, length_flag, number_flag, err_flag; a_flag = b_flag = all_flag = length_flag = number_flag = err_flag = 0; /**type "struct option": * @param name, "const char*" türünden bir değişken olup, ilgili uzun seçeneğin adını tutmaktadır. * @param has_arg, "int" türden bir değişken olup, argüman bilgisini tutmaktadır. Burada no_argument", * "required_argument" ve "optional_argumen" isimli sembolik sabitler kullanabiliriz. Bu isimler sırasıyla * argümansız, argümanlı ya da isteğe bağlı argümanlı olduğunu belirtmektedir. * @param flag, "int*" türden bir değişken olup, uzun seçeneğin bulunması durumunda, bizim belirlediğimiz * rakamı iş bu adrese yazmak için kullanılmaktadır. NULL geçilmesi durumunda bu mekanizma devre dışı kalacaktır. * @param val, "int" türden bir değişken olup, uzun seçeneğin bulunması durumunda, iş bu "getopt_long" fonksiyonunun * ne ile döneceğini belirtmek için kullanılır. Eğer üçüncü parametreye bir adres bilgisi de geçersek, iş bu değer, * üçüncü parametreye geçilen adrese yazılacaktır. */ struct option options[] = { {"all", no_argument, &all_flag, 1}, {"length", required_argument, NULL, 'l'}, {"number", optional_argument, NULL, 3}, {0, 0, 0, 0} }; char* b_arg, *length_arg, *number_arg = NULL; opterr = 0; /* * Aşağıdaki "while" döngüsünde; * 'a' karakteri ile karşılaştığında 'case a', * 'b' karakteri ile karşılaştığında 'case b', * 'l' karakteri ile karşılaştığında 'case l' bölümlerindeki kodlar çalışacaktır. * Eğer "--all" ile karşılaştığında döngüye girmeyecek ve "all_flag" değişkeninin * adresine "1" yazacaktır. Böylelikle ilgili bayrak da "set" edilmiş olacaktır. * Zaten "--length" seçeneğini 'case l' bölümünde halletmişti. * "--number" gördüğünde de "3" ile geri dönecektir. */ int result; while ((result = getopt_long(argc, argv, "ab:l:", options, NULL)) != -1) { switch (result) { case 'a': a_flag = 1; break; case 'b': b_flag = 1; b_arg = optarg; break; case 'l': length_flag = 1; length_arg = optarg; break; case 3: number_flag = 1; number_arg = optarg; break; case '?': { err_flag = 1; if (optopt == 'b') { fprintf(stderr, "[ERROR] -b option was given WITHOUT an argument!.\n"); } else if(optopt == 'l') { fprintf(stderr, "[ERROR] --length option was given WITHOUT an argument\n"); } else if(optopt != 0) { fprintf(stderr, "[ERROR] invalid option: -%c\n", optopt); } else { fprintf(stderr, "[ERROR] invalid long option!\n"); } } } } if (err_flag) { exit(EXIT_FAILURE); } if (a_flag) { fprintf(stdout, "-a option was given.\n"); } if (b_flag) { fprintf(stdout, "-b option was given with an argument of [%s].\n", b_arg); } if (all_flag) { fprintf(stdout, "--all option was given.\n"); } if (length_flag) { fprintf(stdout, "--length option was given with an argument of [%s].\n", length_arg); } if (number_flag) { if (number_arg != NULL) { fprintf(stdout, "--number option was given with an argument of [%s].\n", number_arg); } else { fprintf(stdout, "--number option was given without an argument of.\n"); } } if (optind != argc) { fprintf(stdout, "Arguments without an options\n"); for (size_t i = optind; i < argc; i++) { puts(argv[i]); } puts("\n"); } } Hem kısa seçeğin hem de uzun seçeneğin aynı çıktıyı üretmesi için yapılması gereken yöntemler: * Örnek 1, "switch" merdiveni içerisinde "fallthrough" meydana getirmek. Artık "-l" ve "--length" aynı şeyi yapacaktır. #include "stdio.h" #include "stdlib.h" #include "unistd.h" #include "getopt.h" int main(int argc, char** argv) { /* # INPUT # ./ex_01 -a -b TheArgumentOfb --all --length 3000 --number=4000 5000 6000 */ /* # OUTPUT # -a option was given. -b option was given with an argument of [TheArgumentOfb]. --all option was given. --length option was given with an argument of [3000]. --number option was given with an argument of [4000]. Arguments without an options 5000 6000 */ /**type "struct option": * @param name, "const char*" türünden bir değişken olup, ilgili uzun seçeneğin adını tutmaktadır. * @param has_arg, "int" türden bir değişken olup, argüman bilgisini tutmaktadır. Burada no_argument", * "required_argument" ve "optional_argumen" isimli sembolik sabitler kullanabiliriz. Bu isimler sırasıyla * argümansız, argümanlı ya da isteğe bağlı argümanlı olduğunu belirtmektedir. * @param flag, "int*" türden bir değişken olup, uzun seçeneğin bulunması durumunda, bizim belirlediğimiz * rakamı iş bu adrese yazmak için kullanılmaktadır. NULL geçilmesi durumunda bu mekanizma devre dışı kalacaktır. * @param val, "int" türden bir değişken olup, uzun seçeneğin bulunması durumunda, iş bu "getopt_long" fonksiyonunun * ne ile döneceğini belirtmek için kullanılır. Eğer üçüncü parametreye bir adres bilgisi de geçersek, iş bu değer, * üçüncü parametreye geçilen adrese yazılacaktır. */ struct option options[] = { {"all", no_argument, NULL, 1}, {"length", required_argument, NULL, 2}, {"number", optional_argument, NULL, 3}, {0, 0, 0, 0} }; int a_flag, b_flag, all_flag, length_flag, number_flag, err_flag; a_flag = b_flag = all_flag = length_flag = number_flag = err_flag = 0; char* b_arg, *length_arg, *number_arg = NULL; opterr = 0; int result; while ((result = getopt_long(argc, argv, "ab:l:", options, NULL)) != -1) { switch (result) { case 'a': a_flag = 1; break; case 'b': b_flag = 1; b_arg = optarg; break; case 1: all_flag = 1; break; case 'l': // fallthrough case 2: length_flag = 1; length_arg = optarg; break; case 3: number_flag = 1; number_arg = optarg; break; case '?': { err_flag = 1; if (optopt == 'b') { fprintf(stderr, "[ERROR] -b option was given WITHOUT an argument!.\n"); } else if(optopt == 2) { fprintf(stderr, "[ERROR] --length option was given WITHOUT an argument\n"); } else if(optopt != 0) { fprintf(stderr, "[ERROR] invalid option: -%c\n", optopt); } else { fprintf(stderr, "[ERROR] invalid long option!\n"); } } } } if (err_flag) { exit(EXIT_FAILURE); } if (a_flag) { fprintf(stdout, "-a option was given.\n"); } if (b_flag) { fprintf(stdout, "-b option was given with an argument of [%s].\n", b_arg); } if (all_flag) { fprintf(stdout, "--all option was given.\n"); } if (length_flag) { fprintf(stdout, "--length option was given with an argument of [%s].\n", length_arg); } if (number_flag) { if (number_arg != NULL) { fprintf(stdout, "--number option was given with an argument of [%s].\n", number_arg); } else { fprintf(stdout, "--number option was given without an argument of.\n"); } } if (optind != argc) { fprintf(stdout, "Arguments without an options\n"); for (size_t i = optind; i < argc; i++) { puts(argv[i]); } puts("\n"); } } * Örnek 2, Uzun seçenek bulunması durumunda, ilgili fonksiyon kısa seçenek olan harfini döndürecektir. BU YAKLAŞIM BİÇİMİ TAVSİYE EDİLMEKTEDİR. #include "stdio.h" #include "stdlib.h" #include "unistd.h" #include "getopt.h" int main(int argc, char** argv) { /* # INPUT # ./ex_01 -a -b TheArgumentOfb --all --length 3000 --number=4000 5000 6000 */ /* # OUTPUT # -a option was given. -b option was given with an argument of [TheArgumentOfb]. --all option was given. --length option was given with an argument of [3000]. --number option was given with an argument of [4000]. Arguments without an options 5000 6000 */ /**type "struct option": * @param name, "const char*" türünden bir değişken olup, ilgili uzun seçeneğin adını tutmaktadır. * @param has_arg, "int" türden bir değişken olup, argüman bilgisini tutmaktadır. Burada no_argument", * "required_argument" ve "optional_argumen" isimli sembolik sabitler kullanabiliriz. Bu isimler sırasıyla * argümansız, argümanlı ya da isteğe bağlı argümanlı olduğunu belirtmektedir. * @param flag, "int*" türden bir değişken olup, uzun seçeneğin bulunması durumunda, bizim belirlediğimiz * rakamı iş bu adrese yazmak için kullanılmaktadır. NULL geçilmesi durumunda bu mekanizma devre dışı kalacaktır. * @param val, "int" türden bir değişken olup, uzun seçeneğin bulunması durumunda, iş bu "getopt_long" fonksiyonunun * ne ile döneceğini belirtmek için kullanılır. Eğer üçüncü parametreye bir adres bilgisi de geçersek, iş bu değer, * üçüncü parametreye geçilen adrese yazılacaktır. */ struct option options[] = { {"all", no_argument, NULL, 1}, // İş bu uzun seçenek bulunduğunda, kısa seçenek versiyonu dönecektir. {"length", required_argument, NULL, 'l'}, {"number", optional_argument, NULL, 3}, {0, 0, 0, 0} }; int a_flag, b_flag, all_flag, length_flag, number_flag, err_flag; a_flag = b_flag = all_flag = length_flag = number_flag = err_flag = 0; char* b_arg, *length_arg, *number_arg = NULL; opterr = 0; int result; while ((result = getopt_long(argc, argv, "ab:l:", options, NULL)) != -1) { switch (result) { case 'a': a_flag = 1; break; case 'b': b_flag = 1; b_arg = optarg; break; case 1: all_flag = 1; break; case 'l': length_flag = 1; length_arg = optarg; break; case 3: number_flag = 1; number_arg = optarg; break; case '?': { err_flag = 1; if (optopt == 'b') { fprintf(stderr, "[ERROR] -b option was given WITHOUT an argument!.\n"); } else if(optopt == 'l') { fprintf(stderr, "[ERROR] --length option was given WITHOUT an argument\n"); } else if(optopt != 0) { fprintf(stderr, "[ERROR] invalid option: -%c\n", optopt); } else { fprintf(stderr, "[ERROR] invalid long option!\n"); } } } } if (err_flag) { exit(EXIT_FAILURE); } if (a_flag) { fprintf(stdout, "-a option was given.\n"); } if (b_flag) { fprintf(stdout, "-b option was given with an argument of [%s].\n", b_arg); } if (all_flag) { fprintf(stdout, "--all option was given.\n"); } if (length_flag) { fprintf(stdout, "--length option was given with an argument of [%s].\n", length_arg); } if (number_flag) { if (number_arg != NULL) { fprintf(stdout, "--number option was given with an argument of [%s].\n", number_arg); } else { fprintf(stdout, "--number option was given without an argument of.\n"); } } if (optind != argc) { fprintf(stdout, "Arguments without an options\n"); for (size_t i = optind; i < argc; i++) { puts(argv[i]); } puts("\n"); } } >>> ASCII tablosundaki ilk 32 karakter ekrana basılamayan karakterdir. "getopt_long" fonksiyonunun üçüncü parametresine geçtiğimiz karakterin ASCII tablosundaki karşılığı olan sayıyı, "struct option" türündeki değişkenin dördüncü veri elemanına geçmememiz gerekiyor. >>> "getopt_long" fonksiyonunun beşinci parametresi olan "int*" türden değişkene NULL geçmezsek, yani "int" türden bir değişkenin adresini geçersek, bir uzun seçenek bulunduğunda, iş bu uzun seçeneğin "struct option" dizisinde denk gelen elemanın indeks bilgisini bu adrese yazmaktadır. Fakat pek ihtiyaç duyulan bir yöntem değildir. > Hatırlatıcı notlar; >> POSIX standartlarına göre, POSIX kütüphanelerindeki global değişken ya da fonksiyon isimlerini kullanarak başka bir değişken ya da fonksiyon oluşturmanız "Tanımsız Davranış" meydana getirir. Bu tip isimlerin hangi isimler olduğunu bilmek bizim sorumluluğumuzdadır. >> C standartlarında ise ilk karakteri "_" olan ve ikinci karakteri büyük harfle başlayanlar ile ilk iki karakteri "__" olan değişken isimleri rezerve edilmiş isimlerdir. Böyle isimlerini kullanılması yine "Tanımsız Davranış" meydana getirir. İş bu sebepten ötürü C dilinde kod yazarken "__" ile başlayan ve ilk karakteri "_" olup ikinci karakteri büyük harf olan değişken ismi kullanmamalıyız. >> "Advanced Programming In The UNIX Environment" ve "The Linux Programming Interface" isimli kitapları da takviye olarak kullanabiliriz. >> Bu kursta çalıştırılan kodların çoğu "https://www.onlinegdb.com/" isimli internet sitesinde çalıştırılmaktadır. Bu sitedeki "cwd" konumu "/home" biçimindedir. "/" ise "root" dizindir. >> Komut satırından girilen argümanların en sonuncusu daima NULL türden olmalıdır. Yani "main" fonksiyonunun ikinci parametresi olan "argv" dizisinin son elemanı her daim NULL olmalıdır. >> "https://pubs.opengroup.org/onlinepubs/9699919799/" adresindeki dökümanlar bütün POSIX dünyasına ilişkin dökümanlardır fakat "man" sayfaları sadece o sisteme ilişkindir. POSIX standartları ile "man" arasında farklılık oluşabilir. >> "types.h" isimli başlık dosyasında, türlere ilişkin "typedef" bilgileri mevcuttur.