国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學(xué)院 > 開發(fā)設(shè)計 > 正文

使用getopt_long()從命令行獲取參數(shù),struct option

2019-11-11 05:39:57
字體:
供稿:網(wǎng)友

本文來自:http://blog.csdn.net/yui/article/details/5669922

函數(shù)說明

#include函數(shù)說明:函數(shù)getopt用來解析命令行參數(shù)。函數(shù)getopt_long支持長選項的命令行解析。函數(shù)原型:intgetopt_long(int argc, char* constargv[],                      const char*optstring,                     const struct option*longopts,                      int*longindex);參數(shù):argc、argv直接從main函數(shù)中獲取。opting是選項參數(shù)組成的字符串,由下列元素組成:1.單個字符,表示選項,2.單個字符后接一個冒號:表示該選項后必須跟一個參數(shù)。參數(shù)緊跟在選項后或者以空格隔開。該參數(shù)的指針賦給optarg。3.單個字符后跟兩個冒號,表示該選項后可以有參數(shù)也可以沒有參數(shù)。如果有參數(shù),參數(shù)必須緊跟在選項后不能以空格隔開。該參數(shù)的指針賦給optarg。(這個特性是GNU的擴(kuò)張)。optstring是一個字符串,表示可以接受的參數(shù)。例如,"a:b:cd",表示可以接受的參數(shù)是a,b,c,d,其中,a和b參數(shù)后面跟有更多的參數(shù)值。(例如:-ahost -b name)longopts是一個結(jié)構(gòu)的實例:structoption{   constchar *name; //name表示的是長參數(shù)名   inthas_arg; //has_arg有3個值,no_argument(或者是0),表示該參數(shù)后面不跟參數(shù)值              //required_argument(或者是1),表示該參數(shù)后面一定要跟個參數(shù)值              //optional_argument(或者是2),表示該參數(shù)后面可以跟,也可以不跟參數(shù)值   int*flag;   //用來決定getopt_long()的返回值是什么。              //flag是null,則函數(shù)會返回與該項option匹配的val值。   int val;     //和flag聯(lián)合決定返回值 };int *flag 如果這個指針為NULL,那么getopt_long()返回該結(jié)構(gòu)val字段中的數(shù)值。如果該指針不NULL,getopt_long()會使得它所指向的變量中填入val字段中的數(shù)值,并且getopt_long()返回0。如果flag不是NULL,但未發(fā)現(xiàn)長選項,那么它所指向的變量的數(shù)值不變。int val 這個值是發(fā)現(xiàn)了長選項時的返回值,或者flag不是NULL時載入*flag中的值。典型情況下,若flag不是NULL,那么val是個真/假值,譬如1或0;另一方面,如果flag是NULL,那么val通常是字符常量,若長選項與短選項一致,那么該字符常量應(yīng)該與optstring中出現(xiàn)的這個選項的參數(shù)相同。=========================================================================給個例子:struct option long_options[] ={          {"a123", required_argument,0, 'a'},          {"c123", no_argument, 0,'c'},};現(xiàn)在,如果命令行的參數(shù)是-a123,那么調(diào)用getopt_long()將返回字符'a',并且將字符串123由optarg返回(注意注意!字符串123由optarg帶回!optarg不需要定義,在getopt.h中已經(jīng)有定義)。那么,如果命令行參數(shù)是-c,那么調(diào)用getopt_long()將返回字符'c',而此時,optarg是null。最后,當(dāng)getopt_long()將命令行所有參數(shù)全部解析完成后,返回-1。===========================================================================以上來自網(wǎng)絡(luò),便于學(xué)習(xí)記憶摘錄在這里,下面是自己的理解:函數(shù)原型:int getopt_long(intargc, char* const argv[],                      const char*optstring,                     const struct option*longopts,                      int*longindex);其中optstring為單個字符參數(shù),稱為short_opts。而longopts為多個字符(即一個或多個單詞連接)參數(shù),稱為long_opts。參數(shù)longindex為longopts數(shù)組中的索引返回值。具體用法參考suricata中main()函數(shù)中解析命令行參數(shù)://短字符參數(shù)charshort_opts[] = "c:TDhi:l:q:d:r:us:S:U:VF:";//長字符參數(shù) structoption long_opts[] = {       {"dump-config", 0, &dump_config, 1},  // getopt_long返回值為0,dump_config保存為1       {"pfring", optional_argument, 0, 0},  // getopt_long返回值為0       {"pfring-int", required_argument, 0, 0}, // getopt_long返回值為0,必須有參數(shù)       {"pfring-cluster-id", required_argument, 0,0},       {"pfring-cluster-type", required_argument, 0,0},       {"af-packet", optional_argument, 0, 0},       {"pcap", optional_argument, 0, 0},       {"pcap-buffer-size", required_argument, 0,0},       {"unittest-filter", required_argument, 0,'U'},// getopt_long返回值為‘U’,必須有參數(shù)       {"list-app-layer-PRotos", 0,&list_app_layer_protocols, 1},       {"list-unittests", 0, &list_unittests,1},       {"list-cuda-cards", 0, &list_cuda_cards,1},       {"list-runmodes", 0, &list_runmodes,1},       {"list-keyWords", optional_argument,&list_keywords, 1},       {"runmode", required_argument, NULL, 0},       {"engine-analysis", 0, &engine_analysis,1},       {"pidfile", required_argument, 0, 0},       {"init-errors-fatal", 0, 0, 0},       {"fatal-unittests", 0, 0, 0},       {"user", required_argument, 0, 0},       {"group", required_argument, 0, 0},       {"erf-in", required_argument, 0, 0},       {"dag", required_argument, 0, 0},       {"napatech", 0, 0, 0},       {"build-info", 0, &build_info, 1},       {NULL, 0, NULL, 0}    };   // 長字符數(shù)組索引    intoption_index = 0;  // 以下是用法  while ((opt= getopt_long(argc, argv, short_opts, long_opts,&option_index)) != -1)        switch (opt)        {      // case為函數(shù)返回值        case 0:          if(strcmp((long_opts[option_index]).name , "pfring") == 0 ||                                 strcmp((long_opts[option_index]).name , "pfring-int") ==0)                     // TO-DO...                    else if(strcmp((long_opts[option_index]).name , "pcap") ==0)                      // TO-DO...                   break;        case 'c':          break;         case 'T':          break;        default:          usage(argv[0]);           exit(EXIT_FAILURE);      }

函數(shù)使用

眾所周知,C程序的主函數(shù)有兩個參數(shù),其中,第一個參數(shù)是整型,可以獲得包括程序名字的參數(shù)個數(shù),第二個參數(shù)是字符數(shù)組指針或字符指針的指針,可以按順序獲得命令行上各個字符串參數(shù)。其原形是:

int main(int argc, char *argv[]);

或者

int main(int argc, char **argv);

 

如果有一個解析CDR的程序,名叫destroy,負(fù)責(zé)將一個二進(jìn)制格式的CDR文件轉(zhuǎn)換為文本文件,輸出的文本的樣式由另外一個描述文件定義,那么,命令行要求輸入的參數(shù)就有三個:CDR文件名、輸出文件名和描述文件名。其中,前兩個參數(shù)是必須輸入的,第三個的描述文件名可以不輸入,程序會自動采用默認(rèn)的輸出樣式。很自然,主函數(shù)的三個參數(shù)就應(yīng)該這樣排列:

./destroy cdr cdr.txt [cdr.desc]

 

這樣做在一般情況下不會有太大問題,問題來源于擴(kuò)展性的需求。如果有一天,用戶要求解析程序能夠按關(guān)鍵字解析,只有含有關(guān)鍵字的CDR才能夠輸出。解決方法很簡單,只要在參數(shù)列表的最后,加上它就可以了。不過,這樣就使得原本可選的描述文件名變?yōu)楸仨気斎耄?/p>

./destroy cdr cdr.txt cdr.desc [keyword]

 

因為不改的話,你就不知道,第三個參數(shù)究竟是描述文件名,還是關(guān)鍵字。現(xiàn)在還算好辦,如果以后陸續(xù)有增加參數(shù)的需求,關(guān)鍵字也變成必須輸入了,這個時候,如果要查找全部CDR,你還得定義一個“特殊的關(guān)鍵字”,告訴程序,把數(shù)據(jù)統(tǒng)統(tǒng)給我撈出來……

 

有鑒于此,在Unix/linux的正式的項目上,程序員通常會使用getopt()或者getopt_long()來獲得輸入的參數(shù)。兩者的一個區(qū)別在于getopt()只支持短格式參數(shù),而getopt_long()既支持短格式參數(shù),又支持長格式參數(shù)。

短格式:./destroy -f cdr -o cdr.txt -c cdr.desc -k 123456

長格式:./destroy --file cdr --output cdr.txt --config cdr.desc --keyword 123456

 

引入了getopt()和getopt_long()的項目,設(shè)計者可以按需要,方便地增加參數(shù),或者隨意地放置參數(shù)的先后次序,只需要在程序中判斷,哪些參數(shù)是必須的就可以了。關(guān)于這兩個函數(shù)的用法,大家可以上網(wǎng)搜索一下,不再累述。附件destroy_linux.c給出了在Linux下使用getopt_long()的實例。

[cpp] view plaincopy#include <stdio.h>  #include <stdlib.h>  #include <unistd.h>  #include <getopt.h>    void print_usage(const char *program_name) {      printf("%s 1.0.0 (2010-06-13)/n", program_name);      printf("This is a program decoding a BER encoded CDR file/n");      printf("Usage: %s -f <file_name> -o <output_name> [-c <config_name>] [-k <keyword>]/n", program_name);      printf("    -f --file       the CDR file to be decoded/n");      printf("    -o --output     the output file in plain text format/n");      printf("    -c --config     the descr 

另外一個區(qū)別是,getopt()幾乎通用于所有類Unix系統(tǒng),而getopt_long()只有在GNU的Unix/Linux下才能用。如果把上述程序放到Tru64上編譯,就會出現(xiàn)以下錯誤:

cc -o destroy destroy_linux.c

cc: Error: destroy_linux.c, line 24: In the initializer for long_opts, an array's element type is incomplete, which precludes its initialization. (incompelinit)

                {"help", no_argument, NULL, 'h'},

----------------^

 

所以,如果一定要在Tru64等非GNU的OS上做到長格式的效果,除了自己另起爐灶之外,基本上只好借助一些跨平臺的開源項目了。附件里的getopt_long.c和getopt.h是從opensolaris的網(wǎng)站上抄下來的,是包含在sg3_utils軟件包中的程序。sg3_utils具體是什么,我也不知道,據(jù)說是一個Linux的開發(fā)包,用來直接使用SCSI命令集訪問設(shè)備。(sg3_utils is a package of utilities for accessing devices that use SCSI command sets.)反正拿來能用就是了!

[cpp] view plaincopy/*  $NetBSD: getopt.h,v 1.7 2005/02/03 04:39:32 perry Exp $ */    /*-  * Copyright (c) 2000 The NetBSD Foundation, Inc.  * All rights reserved.  *  * This code is derived from software contributed to The NetBSD Foundation  * by Dieter Baron and Thomas Klausner.  *  * Redistribution and use in source and binary forms, with or without  * modification, are permitted provided that the following conditions  * are met:  * 1. Redistributions of source code must retain the above copyright  *    notice, this list of conditions and the following disclaimer.  * 2. Redistributions in binary form must reproduce the above copyright  *    notice, this list of conditions and the following disclaimer in the  *    documentation and/or other materials provided with the distribution.  * 3. All advertising materials mentioning features or use of this software  *    must display the following acknowledgement:  *        This product includes software developed by the NetBSD  *        Foundation, Inc. and its contributors.  * 4. Neither the name of The NetBSD Foundation nor the names of its  *    contributors may be used to endorse or promote products derived  *    from this software without specific prior written permission.  *  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE  * POSSIBILITY OF SUCH DAMAGE.  */    /*  * modified May 12, 2005 by Jim Basney <jbasney@ncsa.uiuc.edu>  *  * removed #include of non-POSIX <sys/cdefs.h> and <sys/featuretest.h>  * removed references to _NETBSD_SOURCE and HAVE_NBTOOL_CONFIG_H  * added #if !HAVE_GETOPT_LONG  * removed __BEGIN_DECLS and __END_DECLS  */    #ifndef _MYPROXY_GETOPT_H_  #define _MYPROXY_GETOPT_H_    #if !HAVE_GETOPT_LONG    #include <unistd.h>    /*  * Gnu like getopt_long() and BSD4.4 getsubopt()/optreset extensions  */  #define no_argument        0  #define required_argument  1  #define optional_argument  2    extern char *optarg;  extern int optind;  extern int optopt;  extern int opterr;    struct option {      /* name of long option */      const char *name;      /*      * one of no_argument, required_argument, and optional_argument:      * whether option takes an argument      */      int has_arg;      /* if not NULL, set *flag to val when option found */      int *flag;      /* if flag not NULL, value to set *flag to; else return value */      int val;  };    int getopt_long(int, char * const *, const char *,      const struct option *, int *);     #endif /* !HAVE_GETOPT_LONG */    #endif /* !_MYPROXY_GETOPT_H_ */  [cpp] view plaincopy/*  $NetBSD: getopt_long.c,v 1.17 2004/06/20 22:20:15 jmc Exp $ */    /*-  * Copyright (c) 2000 The NetBSD Foundation, Inc.  * All rights reserved.  *  * This code is derived from software contributed to The NetBSD Foundation  * by Dieter Baron and Thomas Klausner.  *  * Redistribution and use in source and binary forms, with or without  * modification, are permitted provided that the following conditions  * are met:  * 1. Redistributions of source code must retain the above copyright  *    notice, this list of conditions and the following disclaimer.  * 2. Redistributions in binary form must reproduce the above copyright  *    notice, this list of conditions and the following disclaimer in the  *    documentation and/or other materials provided with the distribution.  * 3. All advertising materials mentioning features or use of this software  *    must display the following acknowledgement:  *        This product includes software developed by the NetBSD  *        Foundation, Inc. and its contributors.  * 4. Neither the name of The NetBSD Foundation nor the names of its  *    contributors may be used to endorse or promote products derived  *    from this software without specific prior written permission.  *  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE  * POSSIBILITY OF SUCH DAMAGE.  */    /*  * modified May 12, 2005 by Jim Basney <jbasney@ncsa.uiuc.edu>  *  * removed #include of non-POSIX <sys/cdefs.h> <err.h>  * removed #include of "namespace.h"  * use local "port_getopt.h" instead of <getopt.h>  * removed REPLACE_GETOPT and HAVE_NBTOOL_CONFIG_H sections  * removed __P() from function declarations  * use ANSI C function parameter lists  * removed optreset support  * replace _DIAGASSERT() with assert()  * replace non-POSIX warnx(...) with fprintf(stderr, ...)  * added extern declarations for optarg, optind, opterr, and optopt  */    #if defined(LIBC_SCCS) && !defined(lint)  __RCSID("$NetBSD: getopt_long.c,v 1.17 2004/06/20 22:20:15 jmc Exp $");  #endif /* LIBC_SCCS and not lint */    #include <assert.h>  #include <errno.h>  #include "getopt.h"  #include <stdio.h>  #include <stdlib.h>  #include <string.h>    #ifdef __weak_alias  __weak_alias(getopt_long,_getopt_long)  #endif    #if !HAVE_GETOPT_LONG  #define IGNORE_FIRST    (*options == '-' || *options == '+')  #define PRINT_ERROR ((opterr) && ((*options != ':') /                        || (IGNORE_FIRST && options[1] != ':')))  #define IS_POSIXLY_CORRECT (getenv("POSIXLY_CORRECT") != NULL)  #define PERMUTE         (!IS_POSIXLY_CORRECT && !IGNORE_FIRST)  /* XXX: GNU ignores PC if *options == '-' */  #define IN_ORDER        (!IS_POSIXLY_CORRECT && *options == '-')    /* return values */  #define BADCH   (int)'?'  #define BADARG      ((IGNORE_FIRST && options[1] == ':') /               || (*options == ':') ? (int)':' : (int)'?')  #define INORDER (int)1    #define EMSG    ""    extern char *optarg;  extern int optind, opterr, optopt;    static int getopt_internal (int, char * const *, const char *);  static int gcd (int, int);  static void permute_args (int, int, int, char * const *);    static char *place = EMSG; /* option letter processing */    static int nonopt_start = -1; /* first non option argument (for permute) */  static int nonopt_end = -1;   /* first option after non options (for permute) */    /* Error messages */  static const char recargchar[] = "option requires an argument -- %c";  static const char recargstring[] = "option requires an argument -- %s";  static const char ambig[] = "ambiguous option -- %.*s";  static const char noarg[] = "option doesn't take an argument -- %.*s";  static const char illoptchar[] = "unknown option -- %c";  static const char illoptstring[] = "unknown option -- %s";      /*  * Compute the greatest common divisor of a and b.  */  static int  gcd(int a, int b)  {      int c;        c = a % b;      while (c != 0) {          a = b;          b = c;          c = a % b;      }               return b;  }    /*  * Exchange the block from nonopt_start to nonopt_end with the block  * from nonopt_end to opt_end (keeping the same order of arguments  * in each block).  */  static void  permute_args(int panonopt_start, int panonopt_end, int opt_end,           char * const *nargv)  {      int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;      char *swap;        assert(nargv != NULL);        /*      * compute lengths of blocks and number and size of cycles      */      nnonopts = panonopt_end - panonopt_start;      nopts = opt_end - panonopt_end;      ncycle = gcd(nnonopts, nopts);      cyclelen = (opt_end - panonopt_start) / ncycle;        for (i = 0; i < ncycle; i++) {          cstart = panonopt_end+i;          pos = cstart;          for (j = 0; j < cyclelen; j++) {              if (pos >= panonopt_end)                  pos -= nnonopts;              else                  pos += nopts;              swap = nargv[pos];              /* LINTED const cast */              ((char **) nargv)[pos] = nargv[cstart];              /* LINTED const cast */              ((char **)nargv)[cstart] = swap;          }      }  }    /*  * getopt_internal --  *  Parse argc/argv argument vector.  Called by user level routines.  *  Returns -2 if -- is found (can be long option or end of options marker).  */  static int  getopt_internal(int nargc, char * const *nargv, const char *options)  {      char *oli;              /* option letter list index */      int optchar;        assert(nargv != NULL);      assert(options != NULL);        optarg = NULL;        /*      * XXX Some programs (like rsyncd) expect to be able to      * XXX re-initialize optind to 0 and have getopt_long(3)      * XXX properly function again.  Work around this braindamage.      */      if (optind == 0)          optind = 1;    start:      if (!*place) {                      /* update scanning pointer */          if (optind >= nargc) {          /* end of argument vector */              place = EMSG;              if (nonopt_end != -1) {                  /* do permutation, if we have to */                  permute_args(nonopt_start, nonopt_end,                      optind, nargv);                  optind -= nonopt_end - nonopt_start;              }              else if (nonopt_start != -1) {                  /*                  * If we skipped non-options, set optind                  * to the first of them.                  */                  optind = nonopt_start;              }              nonopt_start = nonopt_end = -1;              return -1;          }          if ((*(place = nargv[optind]) != '-')              || (place[1] == '/0')) {    /* found non-option */              place = EMSG;              if (IN_ORDER) {                  /*                  * GNU extension:                   * return non-option as argument to option 1                  */                  optarg = nargv[optind++];                  return INORDER;              }              if (!PERMUTE) {                  /*                  * if no permutation wanted, stop parsing                  * at first non-option                  */                  return -1;              }              /* do permutation */              if (nonopt_start == -1)                  nonopt_start = optind;              else if (nonopt_end != -1) {                  permute_args(nonopt_start, nonopt_end,                      optind, nargv);                  nonopt_start = optind -                      (nonopt_end - nonopt_start);                  nonopt_end = -1;              }              optind++;              /* process next argument */              goto start;          }          if (nonopt_start != -1 && nonopt_end == -1)              nonopt_end = optind;          if (place[1] && *++place == '-') {  /* found "--" */              place++;              return -2;          }      }      if ((optchar = (int)*place++) == (int)':' ||          (oli = strchr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) {          /* option letter unknown or ':' */          if (!*place)              ++optind;          if (PRINT_ERROR)              fprintf(stderr, illoptchar, optchar);          optopt = optchar;          return BADCH;      }      if (optchar == 'W' && oli[1] == ';') {      /* -W long-option */          /* XXX: what if no long options provided (called by getopt)? */          if (*place)               return -2;            if (++optind >= nargc) { /* no arg */              place = EMSG;              if (PRINT_ERROR)                  fprintf(stderr, recargchar, optchar);              optopt = optchar;              return BADARG;          } else              /* white space */              place = nargv[optind];          /*          * Handle -W arg the same as --arg (which causes getopt to          * stop parsing).          */          return -2;      }      if (*++oli != ':') {            /* doesn't take argument */          if (!*place)              ++optind;      } else {                /* takes (optional) argument */          optarg = NULL;          if (*place)         /* no white space */              optarg = place;          /* XXX: disable test for :: if PC? (GNU doesn't) */          else if (oli[1] != ':') {   /* arg not optional */              if (++optind >= nargc) { /* no arg */                  place = EMSG;                  if (PRINT_ERROR)                      fprintf(stderr, recargchar, optchar);                  optopt = optchar;                  return BADARG;              } else                  optarg = nargv[optind];          }          place = EMSG;          ++optind;      }      /* dump back option letter */      return optchar;  }    /*  * getopt_long --  *  Parse argc/argv argument vector.  */  int  getopt_long(int nargc, char * const *nargv, const char *options,          const struct option *long_options, int *idx)  {      int retval;        assert(nargv != NULL);      assert(options != NULL);      assert(long_options != NULL);      /* idx may be NULL */        if ((retval = getopt_internal(nargc, nargv, options)) == -2) {          char *current_argv, *has_equal;          size_t current_argv_len;          int i, match;            current_argv = place;          match = -1;            optind++;          place = EMSG;            if (*current_argv == '/0') {        /* found "--" */              /*              * We found an option (--), so if we skipped              * non-options, we have to permute.              */              if (nonopt_end != -1) {                  permute_args(nonopt_start, nonopt_end,                      optind, nargv);                  optind -= nonopt_end - nonopt_start;              }              nonopt_start = nonopt_end = -1;              return -1;          }          if ((has_equal = strchr(current_argv, '=')) != NULL) {              /* argument found (--option=arg) */              current_argv_len = has_equal - current_argv;              has_equal++;          } else              current_argv_len = strlen(current_argv);                    for (i = 0; long_options[i].name; i++) {              /* find matching long option */              if (strncmp(current_argv, long_options[i].name,                  current_argv_len))                  continue;                if (strlen(long_options[i].name) ==                  (unsigned)current_argv_len) {                  /* exact match */                  match = i;                  break;              }              if (match == -1)        /* partial match */                  match = i;              else {                  /* ambiguous abbreviation */                  if (PRINT_ERROR)                      fprintf(stderr, ambig, (int)current_argv_len,                           current_argv);                  optopt = 0;                  return BADCH;              }          }          if (match != -1) {          /* option found */                  if (long_options[match].has_arg == no_argument                  && has_equal) {                  if (PRINT_ERROR)                      fprintf(stderr, noarg, (int)current_argv_len,                           current_argv);                  /*                  * XXX: GNU sets optopt to val regardless of                  * flag                  */                  if (long_options[match].flag == NULL)                      optopt = long_options[match].val;                  else                      optopt = 0;                  return BADARG;              }              if (long_options[match].has_arg == required_argument ||                  long_options[match].has_arg == optional_argument) {                  if (has_equal)                      optarg = has_equal;                  else if (long_options[match].has_arg ==                      required_argument) {                      /*                      * optional argument doesn't use                      * next nargv                      */                      optarg = nargv[optind++];                  }              }              if ((long_options[match].has_arg == required_argument)                  && (optarg == NULL)) {                  /*                  * Missing argument; leading ':'                  * indicates no error should be generated                  */                  if (PRINT_ERROR)                      fprintf(stderr, recargstring, current_argv);                  /*                  * XXX: GNU sets optopt to val regardless                  * of flag                  */                  if (long_options[match].flag == NULL)                      optopt = long_options[match].val;                  else                      optopt = 0;                  --optind;                  return BADARG;              }          } else {            /* unknown option */              if (PRINT_ERROR)                  fprintf(stderr, illoptstring, current_argv);              optopt = 0;              return BADCH;          }          if (long_options[match].flag) {              *long_options[match].flag = long_options[match].val;              retval = 0;          } else               retval = long_options[match].val;          if (idx)              *idx = match;      }      return retval;  }  #endif /* !GETOPT_LONG */  

 

拿過來后,把他們放到與destroy_linux.c同一目錄下,只需要把destroy_linux.c的頭文件改一個地方,#include <getopt.h>改為#include “getopt.h”,就能夠編譯運(yùn)行了。而且,這樣改好后,不僅在Tru64上能運(yùn)行,在Linux、SunOS上也能運(yùn)行。

[cpp] view plaincopy#include <stdio.h>  #include <stdlib.h>  #include <unistd.h>  #include "getopt.h"    void print_usage(const char *program_name) {      printf("%s 1.0.0 (2010-06-13)/n", program_name);      printf("This is a program decoding a BER encoded CDR file/n");      printf("Usage: %s -f <file_name> -o <output_name> [-c <config_name>] [-k <keyword>]/n", program_name);      printf("    -f --file       the CDR file to be decoded/n");      printf("    -o --output     the output file in plain text format/n");      printf("    -c --config     the description file of the CDR file, if not given, use default configuration/n");      printf("    -k --keyword    the keyword to search, if not given, all records will be written into output file/n");  }    int main(int argc, char *argv[]) {      char *file_name = NULL;      char *output_name = NULL;      char *config_name = NULL;      char *keyword = NULL;        const char *short_opts = "hf:o:c:k:";      const struct option long_opts[] = {          {"help", no_argument, NULL, 'h'},          {"file", required_argument, NULL, 'f'},          {"output", required_argument, NULL, 'o'},          {"config", required_argument, NULL, 'c'},          {"keyword", required_argument, NULL, 'k'},          {0, 0, 0, 0}      };      int hflag = 0;        int c;      opterr = 0;        while ( (c = getopt_long(argc, argv, short_opts, long_opts, NULL)) != -1 ) {          switch ( c ) {              case 'h' :                  hflag = 1;                  break;              case 'f' :                  file_name = optarg;                  break;              case 'o' :                  output_name = optarg;                  break;              case 'c' :                  config_name = optarg;                  break;              case 'k' :                  keyword = optarg;                  break;              case '?' :                  if ( optopt == 'f' || optopt == 'o' || optopt == 'c' || optopt == 'k' )                      printf("Error: option -%c requires an argument/n", optopt);                  else if ( isprint(optopt) )                      printf("Error: unknown option '-%c'/n", optopt);                  else                      printf("Error: unknown option character '//x%x'/n", optopt);                  return 1;              default :                  abort();          }      }        if ( hflag || argc == 1 ) {          print_usage(argv[0]);          return 0;      }      if ( !file_name ) {          printf("Error: file name must be specified/n");          return 1;      }      if ( !output_name ) {          printf("Error: output name must be specified/n");          return 1;      }        // if not setting default, Linux OK, but SunOS core dump      if ( !config_name ) config_name = "(null)";      if ( !keyword ) keyword = "(null)";      printf("Parameters got: file_name = %s, output_name = %s, config_name = %s, keyword = %s/n", file_name, output_name, config_name, keyword);      return 0;  }  

 

Linux下編譯

-bash-3.2$ gcc -o destroy destroy.c getopt_long.c

短格式,全部輸入

-bash-3.2$ ./destroy -f aaa -o aaa.txt -c ccc -k 222

Parameters got: file_name = aaa, output_name = aaa.txt, config_name = ccc, keyword = 222

前兩個長格式,后兩個短格式

-bash-3.2$ ./destroy --file aaa --output aaa.txt -c ccc -k 222

Parameters got: file_name = aaa, output_name = aaa.txt, config_name = ccc, keyword = 222

漏掉一個必須輸入的參數(shù)會報錯

-bash-3.2$ ./destroy -output aaa.txt

Error: file name must be specified

次序隨意,長短混用

-bash-3.2$ ./destroy -c ccc -o aaa.txt -k 222 --file aaa

Parameters got: file_name = aaa, output_name = aaa.txt, config_name = ccc, keyword = 222

 

題外話,#include <filename.h>與#include “filename.h”有什么區(qū)別,是面試C程序員經(jīng)常問到的一個問題。答案大家都知道了,#include <filename.h>,編譯器從標(biāo)準(zhǔn)庫路徑搜索filename.h,而#include “filename.h”,編譯器從用戶的工作路徑搜索filename.h。

 

此外,網(wǎng)上也有人說從glibc(http://sourceware.org/glibc/)上把getopt.h、getopt.c和getoptl.c拿過來也能夠用。我也試過,但是不清楚什么原因不成功。

 

在這個小實驗的過程中,還發(fā)現(xiàn)了C語言在各個OS下的一些細(xì)小差異,比如destroy.c里,79行到82行:

// if not setting default, Linux OK, but SunOS core dump

if ( !config_name ) config_name = "(null)";

if ( !keyword ) keyword = "(null)";

printf("Parameters got: file_name = %s, output_name = %s, config_name = %s, keyword = %s/n", file_name, output_name, config_name, keyword);

 

如果在81行和82行不設(shè)置空指針的默認(rèn)值,Linux和Tru64都會自動幫你轉(zhuǎn)換而避免運(yùn)行時錯誤,但是SunOS不會,它會死給你看。

./destroy -f aaa -o aaa.txt

Segmentation Fault (core dumped)

 

再比如第62行的abort()在頭文件stdlib.h中定義,如果不包含此文件,SunOS與Tru64編譯都沒問題,Linux編譯時會警告:

warning: incompatible implicit declaration of built-in function abort

 

由此看來,雖然C也公認(rèn)是可移植性比較好的語言,但是在跨平臺的項目中,也應(yīng)該注意這些微小的差別。

轉(zhuǎn)自:http://blog.csdn.net/lanmanck/article/details/11999345


發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 临夏市| 兴山县| 五指山市| 盈江县| 蓬莱市| 神农架林区| 台南市| 山东省| 黄大仙区| 聂拉木县| 丁青县| 维西| 渝北区| 高要市| 江都市| 饶平县| 香河县| 白山市| 巴南区| 喀什市| 井研县| 武定县| 万山特区| 巴塘县| 息烽县| 舟曲县| 洛阳市| 招远市| 称多县| 三明市| 屯留县| 吉首市| 中超| 北川| 柳州市| 韶山市| 囊谦县| 名山县| 张家口市| 河北区| 诏安县|