การส่งผ่านอาร์กิวเมนท์ไปยังโปรแกรม

บทความยังไม่เรียบร้อยครับ !!!

การเขียนโปรแกรมโดยรับข้อมูลอาร์กิวเมนท์เริ่มต้นจากผู้ใช้งานสามารถแบ่งประเภทของอาร์กิวเมนท์ออกเป็นสองส่วนใหญ่ๆ คือ ออปชัน และ อาร์กิวเมนท์อื่นๆ โดยที่ออฟชันใช้สำหรับควบคุมพฤติกรรมของโปรแกรมให้ทำงานตามที่เราต้องการ ส่วน อาร์กิวเมนท์อื่นๆ เป็นข้อมูลเพิ่มเติมที่เราต้องการให้แก่โปรแกรม โดยที่ออปชันนั้นสามารแบ่งออกเป็นสองรูปแบบคือ

  • ออปชันอย่างสั้น (Short options) จะประกอบไปด้วย hyphen (-) หนึ่งอักษร และอักษรใดๆ หนึ่งอักษร(โดยปรกติจะเป็นตัวพิมพ์ใหญ่หรือตัวพิมพ์เล็ก) เช่น -s ออปชันอย่างสั้นนั้นง่ายและรวดเร็วต่อการพิมพ์คำสั่ง
  • ออปชันอย่างยาว (Long options) จะประกอบไปด้วย hyphen (-) สองอักษรติดกัน และตามด้วยกลุ่มของตัวอักษร(โดยปรกติจะเป็นตัวพิมพ์ใหญ่หรือตัวพิมพ์เล็กหรือมี hyphen ประกอบด้วยก็ได้) ออปชันอย่างยาวง่ายต่อการจดจำและเข้าใจ

โดยปรกติโปรแกรมส่วนใหญ่จะมีออปชันให้ใช้งานทั้งสองรูปแบบเช่น $ ls -s / หรือสามารถใช้งาน $ ls --size / เป็นตัน การตั้งชื่อออปชันไม่มีข้อกำหนดที่ชัดเจนตายตัว แต่มักจะมีออปชันที่เป็นที่รู้จักกันดีคือ -h หรือ --help ใช้เป็นส่วนสำหรับช่วยเหลือสำหรับการใช้งานโปรแกรม นอกจากนี้หากเราต้องการพัฒนาโปรแกรมที่มีชื่อออปชันเหมือนกับที่กำหนดไว้ใน GNU Coding Standards จะเป็นการดีมาก เนื่องจากจะง่ายต่อการเรียนรู้ จดจำ และใช้งาน เป็นการพัฒนาโปรแกรมให้มีส่วนติดต่อใช้งานไปในทิศทางเดียวกัน

การเขียนโปรแกรมโดยใช้ไลบรารี getopt และ getopt_long
หากเราต้องการเขียนโปรแกรมโดยหาค่าออปชันที่เราต้องการโดยใช้รูปแบบออปชันอย่างสั้นเพียงอย่างเดียวเราสามารถใช้งานฟังก์ชัน getopt ซึ่งเป็นไลบรารีที่อยู่ในห unistd ได้เลย โดยที่ getopt จะนำข้อมูลจาก argc และ args มาหาออปชัน โดยที่เราต้องระบุออปชันที่เราสนใจไว้ใน optstring หากต้องการให้ออปชันใดรับอาร์กิวเมนท์เพิ่มเติ่ม สามาระระบุเครื่องหมาย ':' ไว้หลัง ออปชันนั้นได้ทันที ดังตัวอย่างโปรแกรม

#include <iostream>
using namespace std;

#include <unistd.h>

int main(int argc, char** argv){
	int option;
	char optstring[] = "abc:d:ef";
	while( (option = getopt(argc, argv, optstring)) != -1 ){
		switch(option){
			case 'a':
			case 'b':
			case 'e':
			case 'f':
				cout << "option is " << (char)option 
                                        << endl;
				break;
			case 'c':
			case 'd':
				cout << "option is " << (char)option 
                                        << " value: "  << optarg << endl;
				break;
			case '?':
				cout << "unknow option: " << (char)optopt 
                                        << endl;
				break;
	
		}
	}

	for(; optind < argc; optind++){
		cout << "unused: " << argv[optind] << endl;
	}

	return 0;
}

ตัวอย่างการใช้งาน

$ ./opt -abcdef
option is a
option is b
option is c value: def
$ ./opt -ab -c 123 -d
option is a
option is b
option is c value: 123
./opt: option requires an argument -- 'd'
unknow option: d
$ ./opt -abef -un
option is a
option is b
option is e
option is f
./opt: invalid option -- 'u'
unknow option: u
./opt: invalid option -- 'n'
unknow option: n

หากสังเกตดูจะพบว่าเมื่อออปชันที่ให้ไปกับโปรแกรมเมื่อไม่ตรงตามที่ต้องการ getopt จะแสดงข้อผิดพลาดออกทาง stderr ทันที

ตัวอย่างต่อมาเป็นการใช้งาน getopt_long จาก Advance Linux Programming

#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
/* The name of this program.  */
const char* program_name;
/* Prints usage information for this program to STREAM (typically
   stdout or stderr), and exit the program with EXIT_CODE. Does not
   return. */
void print_usage(FILE* stream, int exit_code);

/* Main program entry point. ARGC contains number of argument list
   elements; ARGV is an array of pointers to them. */
int main(int argc, char* argv[]) {
    int next_option;
    /* A string listing valid short options letters.  */
    const char* const short_options = "ho:v";
    /* An array describing valid long options. */
    const struct option long_options[] = {
        { "help", 0, NULL, 'h'},
        { "output", 1, NULL, 'o'},
        { "verbose", 0, NULL, 'v'},
        { NULL, 0, NULL, 0}
        /* Required at end of array. */
    };

    /* The name of the file to receive program output, 
       or NULL for standard output. */
    const char* output_filename = NULL;

    /* Whether to display verbose messages. */
    int verbose = 0;

    /* Remember the name of the program, 
        to incorporate in messages.
        The name is stored in argv[0]. */
    program_name = argv[0];

    do {
        next_option = getopt_long(argc, argv, short_options,
                long_options, NULL);
        switch (next_option) {
            case 'h': /* -h or --help */
                /* User has requested usage information. 
                   Print it to standard output, and exit with exit code zero 
                   (normal termination). */
                print_usage(stdout, 0);

            case 'o': /* -o or --output */
                /* This option takes an argument, 
                    the name of the output file. */
                output_filename = optarg;
                break;

            case 'v': /* -v or  --verbose */
                verbose = 1;
                break;

            case '?': /* The user specified an invalid option. */
                /* Print usage information to standard error, 
                    and exit with exit  code one 
                    (indicating abnormal termination). */
                print_usage(stderr, 1); 

            case -1: /* Done with options.  */
                break;

            default: /* Something else: unexpected.  */
                abort();
        }
    } while (next_option != -1);
    /* Done with options. OPTIND points to 
        first nonoption argument.
        For demonstration purposes, 
        print them if the verbose option was
        specified. */

    if (verbose) {
        int i;
        for (i = optind; i < argc; ++i)
            printf("Argument : % s\n", argv[i]);
    }
    /* The main program goes here.  */
    return 0;
}

void print_usage(FILE* stream, int exit_code) {
    fprintf(stream, "Usage: %s options [ inputfile ... ]\n", 
                program_name);
    fprintf(stream,
            " -h --help               Display this usage information.\n"
            " -o --output filename    Write output to file.\n"
            " -v --verbose            Print verbose messages.\n");
    exit(exit_code);
}

ตัวอย่างผลการทำงาน

$ ./opt_long -o 123  456 -v 789
Argument : 123
Argument : 456
Argument : 789
$ ./opt_long --help
Usage: ./opt_long options [ inputfile ... ]
 -h --help               Display this usage information.
 -o --output filename    Write output to file.
 -v --verbose            Print verbose messages.
boatkrap@sdayu:~/tmp$ ./opt_long --h
Usage: ./opt_long options [ inputfile ... ]
 -h --help               Display this usage information.
 -o --output filename    Write output to file.
 -v --verbose            Print verbose messages.
Taxonomy upgrade extras: 
Creative Commons License ลิขสิทธิ์ของบทความเป็นของเจ้าของบทความแต่ละชิ้น
ผลงานนี้ ใช้สัญญาอนุญาตของครีเอทีฟคอมมอนส์แบบ แสดงที่มา-อนุญาตแบบเดียวกัน 3.0 ที่ยังไม่ได้ปรับแก้