亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 學院 > 開發設計 > 正文

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

2019-11-11 06:12:55
字體:
來源:轉載
供稿:網友

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

函數說明

#include函數說明:函數getopt用來解析命令行參數。函數getopt_long支持長選項的命令行解析。函數原型:intgetopt_long(int argc, char* constargv[],                      const char*optstring,                     const struct option*longopts,                      int*longindex);參數:argc、argv直接從main函數中獲取。opting是選項參數組成的字符串,由下列元素組成:1.單個字符,表示選項,2.單個字符后接一個冒號:表示該選項后必須跟一個參數。參數緊跟在選項后或者以空格隔開。該參數的指針賦給optarg。3.單個字符后跟兩個冒號,表示該選項后可以有參數也可以沒有參數。如果有參數,參數必須緊跟在選項后不能以空格隔開。該參數的指針賦給optarg。(這個特性是GNU的擴張)。optstring是一個字符串,表示可以接受的參數。例如,"a:b:cd",表示可以接受的參數是a,b,c,d,其中,a和b參數后面跟有更多的參數值。(例如:-ahost -b name)longopts是一個結構的實例:structoption{   constchar *name; //name表示的是長參數名   inthas_arg; //has_arg有3個值,no_argument(或者是0),表示該參數后面不跟參數值              //required_argument(或者是1),表示該參數后面一定要跟個參數值              //optional_argument(或者是2),表示該參數后面可以跟,也可以不跟參數值   int*flag;   //用來決定getopt_long()的返回值是什么。              //flag是null,則函數會返回與該項option匹配的val值。   int val;     //和flag聯合決定返回值 };int *flag 如果這個指針為NULL,那么getopt_long()返回該結構val字段中的數值。如果該指針不NULL,getopt_long()會使得它所指向的變量中填入val字段中的數值,并且getopt_long()返回0。如果flag不是NULL,但未發現長選項,那么它所指向的變量的數值不變。int val 這個值是發現了長選項時的返回值,或者flag不是NULL時載入*flag中的值。典型情況下,若flag不是NULL,那么val是個真/假值,譬如1或0;另一方面,如果flag是NULL,那么val通常是字符常量,若長選項與短選項一致,那么該字符常量應該與optstring中出現的這個選項的參數相同。=========================================================================給個例子:struct option long_options[] ={          {"a123", required_argument,0, 'a'},          {"c123", no_argument, 0,'c'},};現在,如果命令行的參數是-a123,那么調用getopt_long()將返回字符'a',并且將字符串123由optarg返回(注意注意!字符串123由optarg帶回!optarg不需要定義,在getopt.h中已經有定義)。那么,如果命令行參數是-c,那么調用getopt_long()將返回字符'c',而此時,optarg是null。最后,當getopt_long()將命令行所有參數全部解析完成后,返回-1。===========================================================================以上來自網絡,便于學習記憶摘錄在這里,下面是自己的理解:函數原型:int getopt_long(intargc, char* const argv[],                      const char*optstring,                     const struct option*longopts,                      int*longindex);其中optstring為單個字符參數,稱為short_opts。而longopts為多個字符(即一個或多個單詞連接)參數,稱為long_opts。參數longindex為longopts數組中的索引返回值。具體用法參考suricata中main()函數中解析命令行參數://短字符參數charshort_opts[] = "c:TDhi:l:q:d:r:us:S:U:VF:";//長字符參數 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,必須有參數       {"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’,必須有參數       {"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}    };   // 長字符數組索引    intoption_index = 0;  // 以下是用法  while ((opt= getopt_long(argc, argv, short_opts, long_opts,&option_index)) != -1)        switch (opt)        {      // case為函數返回值        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);      }

函數使用

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

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

或者

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

 

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

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

 

這樣做在一般情況下不會有太大問題,問題來源于擴展性的需求。如果有一天,用戶要求解析程序能夠按關鍵字解析,只有含有關鍵字的CDR才能夠輸出。解決方法很簡單,只要在參數列表的最后,加上它就可以了。不過,這樣就使得原本可選的描述文件名變為必須輸入:

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

 

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

 

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

短格式:./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()的項目,設計者可以按需要,方便地增加參數,或者隨意地放置參數的先后次序,只需要在程序中判斷,哪些參數是必須的就可以了。關于這兩個函數的用法,大家可以上網搜索一下,不再累述。附件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 

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

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的網站上抄下來的,是包含在sg3_utils軟件包中的程序。sg3_utils具體是什么,我也不知道,據說是一個Linux的開發包,用來直接使用SCSI命令集訪問設備。(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”,就能夠編譯運行了。而且,這樣改好后,不僅在Tru64上能運行,在Linux、SunOS上也能運行。

[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

漏掉一個必須輸入的參數會報錯

-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”有什么區別,是面試C程序員經常問到的一個問題。答案大家都知道了,#include <filename.h>,編譯器從標準庫路徑搜索filename.h,而#include “filename.h”,編譯器從用戶的工作路徑搜索filename.h。

 

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

 

在這個小實驗的過程中,還發現了C語言在各個OS下的一些細小差異,比如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行不設置空指針的默認值,Linux和Tru64都會自動幫你轉換而避免運行時錯誤,但是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也公認是可移植性比較好的語言,但是在跨平臺的項目中,也應該注意這些微小的差別。

轉自:http://blog.csdn.net/lanmanck/article/details/11999345


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美夫妻性生活xx| 欧美午夜激情在线| 亚洲美女www午夜| 中文字幕国产亚洲2019| 国产一区二区三区欧美| 日韩av综合网| 91影视免费在线观看| 在线观看国产精品日韩av| 久久国产天堂福利天堂| 欧美另类在线观看| 在线视频日韩精品| 亚洲成人久久电影| 97成人超碰免| 国产一区二区三区毛片| 国产日韩欧美另类| 亚洲香蕉伊综合在人在线视看| xxxx性欧美| 久久韩剧网电视剧| 亚洲欧美福利视频| 国产婷婷成人久久av免费高清| 热久久视久久精品18亚洲精品| 欧美激情在线一区| 久久精品国产96久久久香蕉| 国产精品无av码在线观看| 这里只有精品丝袜| 亚洲一区二区三区毛片| 国产精品日韩在线播放| 亚洲精品一区中文字幕乱码| 成人在线免费观看视视频| 成人欧美一区二区三区在线湿哒哒| 亚洲色无码播放| 久久国产天堂福利天堂| 欧美日韩国产在线播放| 精品亚洲国产成av人片传媒| 欧美床上激情在线观看| 91在线免费网站| 国产欧美日韩视频| 欧洲成人在线观看| 欧美午夜丰满在线18影院| 国产99在线|中文| 欧美激情在线有限公司| 国产日韩视频在线观看| 中文日韩电影网站| 欧美国产极速在线| 色噜噜狠狠色综合网图区| 91久久精品久久国产性色也91| 精品国产老师黑色丝袜高跟鞋| 欧美日韩国产在线看| 亚洲精品美女在线观看| 久久资源免费视频| 91国产一区在线| 亚洲电影第1页| 国产精品h片在线播放| 91在线视频九色| 免费91麻豆精品国产自产在线观看| 久久久免费电影| 日韩av快播网址| 国产精品99久久久久久久久久久久| 亚洲第一天堂av| 国产精品91免费在线| 在线丨暗呦小u女国产精品| 欧美一级淫片丝袜脚交| 国产精品永久在线| 色综合色综合久久综合频道88| 亚洲性日韩精品一区二区| 欧美激情免费看| 91精品久久久久久久久久久久久| 国产成人精品电影| 欧美精品一区二区三区国产精品| 国产成人精品一区二区在线| 国产午夜精品麻豆| 国产日韩精品在线观看| 美女视频黄免费的亚洲男人天堂| 国产精品普通话| 韩国福利视频一区| 日韩av在线网址| 欧美亚洲另类激情另类| 在线播放精品一区二区三区| 国产精品日韩在线观看| 欧美国产极速在线| 亚洲激情视频在线播放| 成人久久18免费网站图片| 欧美性猛交xxxx乱大交蜜桃| 亚洲精品一区av在线播放| 97热在线精品视频在线观看| 成人免费在线视频网站| 久久久这里只有精品视频| 久久久久国产精品免费网站| 久久久影视精品| 久久国产精品99国产精| 日韩成人激情视频| 国产精品久久久久久久美男| 日韩中文字幕在线精品| 色婷婷综合成人| 欧美极度另类性三渗透| 隔壁老王国产在线精品| 亚洲加勒比久久88色综合| 久久久女女女女999久久| 欧美国产日韩一区二区| 久久天天躁狠狠躁老女人| 亚洲999一在线观看www| 日韩在线观看成人| 高清欧美电影在线| 97久久精品视频| 欧美日韩亚洲系列| 日韩影视在线观看| 18一19gay欧美视频网站| 亚洲国产高潮在线观看| 日韩电影视频免费| 日韩欧美高清视频| 欧美人交a欧美精品| 亚洲欧美另类在线观看| 欧美国产亚洲视频| 日韩69视频在线观看| 亚洲视频axxx| 国产精品无av码在线观看| 亚洲精品美女在线观看| 久久高清视频免费| 一区二区三区视频在线| 亚洲视频第一页| 欧美日韩国产一区中文午夜| 国产精品av网站| 91精品综合视频| 亚洲最新中文字幕| 亚洲精品国产综合久久| 欧美大片大片在线播放| 亚洲国产成人91精品| 性色av一区二区三区红粉影视| 亚洲视频综合网| 日韩免费在线免费观看| 97av在线视频免费播放| 91亚洲va在线va天堂va国| 成人在线国产精品| 日韩一中文字幕| 国产精品高潮呻吟久久av黑人| 国产在线观看一区二区三区| 久久深夜福利免费观看| 国内精品一区二区三区四区| 精品爽片免费看久久| 日韩视频第一页| 久久久精品日本| 深夜福利国产精品| 深夜精品寂寞黄网站在线观看| 九色精品美女在线| 欧美中文字幕视频在线观看| 尤物yw午夜国产精品视频明星| 在线观看欧美日韩| 亚洲性日韩精品一区二区| 国产91精品黑色丝袜高跟鞋| 精品久久久在线观看| 欧美丰满少妇xxxxx| 国产日韩欧美日韩大片| 成人国产亚洲精品a区天堂华泰| 亚洲在线视频福利| 国产第一区电影| 国产成人精品在线视频| 综合欧美国产视频二区| 国产91精品网站| 欧美日本高清视频| 国产激情久久久久| 国产成人啪精品视频免费网| 中文字幕欧美日韩va免费视频| www.欧美三级电影.com| 亚洲大胆美女视频|