خانواده‌ی توابع کتابخانه‌ای getopt(3)

تابع کتابخانه‌ای getopt(3)

منوال تابع getopt(3)

تابع کتابخانه‌ای getopt(3) آرگومان‌های خط فرمان را parse می‌کند.

#include <unistd.h>

int getopt(int argc, char *argv[], const char *optstring);
          returns next option character on success,
          -1 if all command-line options have been parsed,
          ? if option character is not in optstring,
          ? (or :) if required argument is not provided.

المانی که در خط فرمان باشد و با - شروع شده باشد و دقیقا - و -- نباشد یک option است. کاراکتری که دقیقا بعد از - می‌آید کاراکتر optioin نامیده می‌شود. اگر تابع getopt را به صورت متوالی فراخوانی کنیم در هر بار کاراکتر option بعدی را باز می‌گرداند.

optind ایندکس عنصر بعدی در آرایه‌ی argv است که باید پردازش شود. سیستم آن را با ۱ مقداردهی اولیه می‌کند و ما می‌توانیم بعدا نیز به آن مقدار ۱ بدهیم تا آرایه‌ی آرگومانهای خط فرمان یا هر آرایه‌ی دیگری را از نو پردازش کنیم.

کاراکتر option نباید - و : , ; باشد.

اگر بعد از کاراکتر آپشن : باشد آن option نیاز به یک آرگومان بعد از خود دارد. :: می‌گوید که آرگومان این کاراکتر آپشن اختیاری است.

اگر آرگومان کاراکتر آپشن اجباری باشد یعنی بعد از کاراکتر آپشن فقط یک: آمده باشد در این صورت آرگومان هم می‌تواند به کاراکتر آپشن بچسبد و هم اینکه با space از کاراکتر آپشن جدا شده باشد.

getopt(argc, argv, "c:")

$ program_name -csalam
$ program_name -c salam

با این کد موضوع را بررسی کنید.

اما اگر کاراکتر آپشن با :: درخواست یک آرگومان اختیاری کند در این صورت در خط فرمان آرگومان باید به کاراکتر آپشن بچسبد. در غیر این صورت optarg با NULL پر می‌شود.

getopt(argc, argv, "c::");

$ program_name -csalam  # correct
$ program_name -c salam # incorrect

با کد داده شده این موضوع را بررسی کنید.

در مورد W در optstring مطالعه شود و مثال getopt3.c تکمیل گردد.

آرگومانهای خط فرمان به شکل سفت و سخت پردازش می‌شوند به این معنی که اگر یک آپشن نیاز به یک آرگومان اجباری داشته باشد، آرگومان بعدی را مصرف می‌کند فارغ از این که آرگومان بعدی واقعا آرگومانی است که برای آن آپشن فراهم شده است یا اینکه آپشن بعدی است (در این صورت کاربر در فراهم کردن اطلاعات اشتباه کرده است.)

در هنگام پردازش آپشن‌های موجود در خط فرمان با دو نوع خطا ممکن است مواجه شویم:

  1. کاراکتر آپشن در خط فرمان در optstring تعریف نشده است.
  2. یک آرگومان اجباری برای یک کاراکتر آپشن وارد نشده باشد. به طور دقیق‌تر یک کاراکتر آپشن در انتهای خط فرمان که نیاز به یک آرگومان اجباری دارد ولی آرگومانی برای آن وارد نشده است.

به طور کلی getopt(3) این نوع خطاها را به صورت زیر مدیریت می‌کند:

  1. به صورت پیش فرض ()getopt یک پیغام خطا در stderr می‌نویسد، کاراکتر آپشن سرمنشا خطا را در متغیر optopt می‌نویسد و به عنوان نتیجه‌ی تابع کاراکتر ? را برمی‌گرداند.
  2. با مقداردهی متغیر سراسری opterr به صفر می‌توانیم چاپ اتوماتیک پیغام خطا در خروجی استاندارد را غیر فعال کنیم. در این صورت وقوع خطا را می‌توان از خروجی تابع ()getopt تشخیص داد.

اگر اول optstring (در صورت وجود + و − بعد از آنها) : بذاریم اولا بدون opterr=0 چاپ خطا در خروجی استاندارد سرکوب می‌شود و دوما در صورت نبودن آرگومان اجباری برای یک کاراکتر آپشن تابع به جای ? مقدار : را برمی‌گرداند. در این صورت به راحتی می‌توانیم بین دو نوع خطا تمیز دهیم.

موارد فوق را با این مثال بررسی کنید.

به صورت پیش‌فرض تابع ()getopt ترتیب عناصر آرایه‌ی argv را تغییر می‌دهد. لذا سرانجام تمام المان‌هایی که آپشن نیستند در انتهای آرایه قرار می‌گیرند.

این موضوع را با این مثال و با دستور زیر تست کنید:

$ ./a.out -a -b  man  -c -e -d

این رفتار را به دو صورت می‌توان تغییر داد:

  1. اگر اولین کاراکتر optstring کاراکتر + باشد یا متغیر محیطی POSIXLY_CORRECT ست شده باشد در این صورت تابع getopt به محض روبرو شدن با اولین آرگومانی که آپشن نیست متوقف می‌شود. مثال فوق را با این دو مورد بررسی کرده و نتیجه را ببینید.
    اگر + اولین کاراکتر optstring نباشد به عنوان یک کاراکتر آپشن معمولی لحاظ خواهد شد. مثال.
    اگر به دنبال رفتار POSIXLY_CORRECT باشیم در این صورت optstring حاوی دو + خواهد بود. اولی به معنای POSIXLY_CORRECT و دومی که در میانه یا انتهای optstring است به عنوان کاراکتر آپشن خواهد بود.
  2. اگر اولین کاراکتر optstring - باشد در این صورت تمامی المان‌های غیر آپشن آرایه‌ی argv به عنوان آرگومان آپشن کاراکتر با کد ۱ منظور خواهد شد. مثال

آرگومان مخصوص -- در خط فرمان به معنای پایان اسکن کردن آپشن‌ها فارغ از هر نوع مد اسکن کردن (موارد ۱ و ۲) است.

If an option was successfully found, then getopt() returns the option character. If all command line options have been parsed, then getopt() returns -1. If getopt() encounters an option character that was not in optstring, then '?' is returned. If getopt() encounters an option with a missing argument, then the return value depends on the first character in optstring: if it is ':', then ':' is returned; otherwise '?' is returned.

مثال از تابع getopt

تابع کتابخانه‌ای getopt_long(3)

منوال تابع کتابخانه‌ای getopt_long(3)

تابع (3)getopt_long مثل (3)getopt عمل می‌کند با این تفاوت که این تابع علاوه بر آپشن‌های کوتاه، آپشن‌های طولانی نیز می‌پذیرد که با -- شروع می‌شوند.

اگر برنامه فقط آپشن‌های طولانی می‌پذیرد و آپشن‌های کوتاه را پشتیبانی نمی‌کند باید optstring را رشته‌ی خالی یعنی "" قرار داد و نه NULL.

آپشن‌های طولانی پارامترهای مورد نیاز خود را در خط فرمان به صورت --arg=param یا --arg param می‌پذیرند.

#include <getopt.h>

struct option {
    const char *name,    /* the name of the long option */
    int         has_arg; /* no_argument|required_argument|optional_argument */
    int        *flag;
    int         val;    /* is the value to return, or to load into
                               the variable pointed to by flag */
};

int getopt_long(int argc, char *argv[], const char *optstring,
                          const struct option *longopts, int *longindex);

int getopt_long_only(int argc, char *argv[], const char *optstring,
                           const struct option *longopts, int *longindex);
  1. اگر flag برابر با NULL باشد در این صورت تابع مقدار val را برمی‌گرداند (برای مثال می‌توانیم کاراکتر معادل آپشن کوتاه آن را در val قرار دهیم.) در غیر این صورت تابع getopt_long مقدار صفر بر می‌گرداند و اگر آپشن طولانی پیدا شده باشد محتوای جایی که flag به آن اشاره می‌کند با val پر می‌شود و در صورت عدم وجود آپشن طولانی در خط فرمان محتوای جایی که flag به آن اشاره می‌کند دست نخورده باقی می‌ماند.
  2. آخرین عنصر آرایه‌ی struct option باید با صفر پر شده باشد.
  3. پارامتر پنجم تابع که به نام longindex است در صورت NULL نبودن، محتوای جایی که این اشاره‌گر به آن اشاره می‌کند با اندیس مرتبط با آرایه‌ی longopts پر می‌شود.

در تابع (3)getopt_long مانند تابع (3)getopt دسترسی کامل به متغیرهای optind و optarg داریم.

مثال از تابع getopt_long

تابع کتابخانه‌ای(3)getopt_long_only

منوال تابع کتابخانه‌ای getopt_long_only(3)

تابع getopt_long_only(3) دقیقا مانند getopt_long(3) است با این تفاوت که - مانند -- می‌تواند یک آپشن طولانی را مشخص کند. به این صورت که آپشن وارد شده با - ابتدا در لیست آپشن‌های طولانی جستجو می‌شود و اگر یافت نشود در ادامه لیست آپشن‌های کوتاه نیز جستجو می‌شود.

getopt_long() and getopt_long_only() return the option character when a short option is recognized. For a long option, they return val if flag is NULL, and 0 otherwise. Error and -1 returns are the same as for getopt(), plus '?' for an ambiguous match or extraneous parameter.

نوشته شده در: 1405-03-11 (1 هفته 8 ساعت 19 دقیقه پیش)

من محسن هستم؛ برنامه‌نویس تفننی!

برای ارتباط با من یا در همین سایت کامنت بگذارید و یا به dokaj.ir(at)gmail.com ایمیل بزنید.

در مورد این مطلب یادداشتی بنویسید.