تفسیر آرگومان های خط فرمان با سی

درود, خیلی وقت‌ها شده دیدید بعضی از برنامه‌ها یک سری آپشن ها دارند و آن ها را در خط فرمان به عنوان ورودی می گیرند؟ برای مثال شاید دیدید که دستور ps بدون آرگومان و گاهی وقت ها با آرگومان میشه اجراش کرد برای مثال ps -A یا ps aux و...حالا اگر بخواید خودتون این آپشن هارو آنالیز کنید به احتمال وقت گیر هست و ممکن هست به اون خوبی که می خواید نشه ما برای این که این کار را راحت تر انجام بدیم از کتابخونهC GNU کمک می گیریم و من در این جا قصد دارم اونو آموزش بدم.برای شروع اول هدر getopt.h رو به برنامه اینکلود کنید.#include <getopt.h>این هدر یک سری متغییر های سراسری داره که در زیر توضیح میدم(بعد در مورد همشون تک تک توضیح میدم)char *optarg وقتی آرگومانی ست بشه این متغییر مقدار دهی میشه int optind اولین آپشنی که در برنامه نباشه انیدکسش توی این ذخیره میشه int opterr وقتی عددی غیر از ۰ باشه (به صورت پیش‌فرض هست) وقتی یک متغییر نامتعبر(آپشن تعریف نشده در برنامه)ظاهر بشه اررو روی صفحه چاپ میشه int optopt وقتی یک متغییر نامتعبر(آپشن تعریف نشده در برنامه)ظاهر بشه یک مقدار ؟ یا : برگردانده میشه که این متغییر شامل مقدار نامعتبر هست.خب اگر تابع getopt() ? برگرداند یعنی این آپشن معتبر نیست(تعریف نشده) و اگر : برگرداند یعنی این اپشن یک ارگومان می‌خواهد که وارد نشده.به کد زیر توجه کنید#include <stdio.h> #include <getopt.h> #include <stdlib.h> // exit() int main(int argc,char *argv[]) { const char * const shortOptions = "ho:c"; int nextOption; while( (nextOption = getopt(argc,argv,shortOptions)) != -1) { switch(nextOption) { case 'h': printf("i got h \n"); break; case 'o': printf("i got o with arg %s \n",optarg); break; case 'c': printf("i got c with arf %s \n",optarg); break; case '?': printf("invalid arg %c \n",optopt); break; default : break; } } return 0; }اگر کد بالارو کامپایل کنید و پارامتر -h -o hello رو بهش بدید خروجی شبیه خروجی زیر خواهید داشتi got h i got o with arg hello حال اگر پارامتر -h -o hello -g رو رد کنید خروجی شبیه خروجی زیر خواهید داشتi got h i got o with arg hello ./a.out: invalid option -- 'g' invalid arg g اگر دقت کرده باشد ./a.out: invalid option – 'g' رو شما ننوشتید و خود تابع اینو چاپ کردهاگر می خواید که اررو هارو خودتون نمایش بدید و مدیریت کنید باید مقدار opterr رو قبل از فراخانی ۰ قرار بدید در این صورت دیگه اررو خود برنامه چاپ نمیکنه و مسوول مدیریتش شما هستید.به کد زیر توجه کنید#include <stdio.h> #include <getopt.h> #include <stdlib.h> // exit() int main(int argc,char *argv[]) { const char * const shortOptions = ":ho:c"; int nextOption; opterr = 0; while( (nextOption = getopt(argc,argv,shortOptions)) != -1) { switch(nextOption) { case 'h': printf("i got h \n"); break; case 'o': printf("i got o with arg %s \n",optarg); break; case 'c': printf("i got c with arg %s \n",optarg); break; case ':': printf("arg %c need arg \n",optopt); break; case '?': printf("invalid arg %c \n",optopt); break; default : break; } } return 0; }خب برای اینکه getopt() برای آپشنی که نیاز به آرگومان دارد : رو برگرونه باید به اول آپشن : اضافه کنید. ماconst char * const shortOptions = "ho:c";رو بهconst char * const shortOptions = ":ho:c";تغییر دادیم. حالا اگر یک آپشن به آرگومان نیاز داشته باشد و وارد نشده باشد تابع : بر می گرداند و می‌توانید آن را مدیریت کنید.همچنین ما مقدار opterr صفر قرار دادیم که برنامه خودش اروری رو چاپ نکنه و مدیریتش به دست خودمون باشه.حال اگر پارامتر ورودی شبیه به بود -o hello "im am here" "hahah" چی؟ به کد زیر توجه کنید#include <stdio.h> #include <getopt.h> #include <stdlib.h> // exit() int main(int argc,char *argv[]) { const char * const shortOptions = ":ho:c"; int nextOption; opterr = 0; while( (nextOption = getopt(argc,argv,shortOptions)) != -1) { switch(nextOption) { case 'h': printf("i got h \n"); break; case 'o': printf("i got o with arg %s \n",optarg); break; case 'c': printf("i got c with arg %s \n",optarg); break; case ':': printf("arg %c need arg \n",optopt); break; case '?': printf("invalid arg %c \n",optopt); break; default : break; } } while(optind < argc) { printf("%s\n",argv[optind++]); } return 0; }درواقع دو پارامتر آخر اضافی هستند و جز آپشن محسوب نمی‌شوند همانطور که گفتیم optind ایندکس اولین عضو غیر آپشن رو بر میگردونه که ما با while(optind < argc) { printf("%s\n",argv[optind++]); }اونارو چاپ کردیم.