zoukankan      html  css  js  c++  java
  • windows下的getopt/getoptlong函数

    windows下的getopt/getoptlong函数

    getopt/getopt_long函数是GNU C中的函数,在linux编程中很常用到。这里就不介绍了。

    windows下没有找到类似的函数,自己写一个又浪费时间,于是乎从glibc中找出来。

    这里放出两个版本的下载地址

    http://files.cnblogs.com/files/oloroso/getopt--from-glibc-2.15.tar.gz

    http://files.cnblogs.com/files/oloroso/getopt-win-from-glibc-2.2.5.tar.gz

    下载GLibC源码

    首先需要下载glibC的源代码文件,这个文件比较大,但是我们只需要其中的几个文件而已。

    如果是后面给出的链接下载的glibc源码包,只需要两个文件。如果是比较新版本的glibc,可能需要四个文件(getopt.h/getopt_int.h/getopt.c/getopt_init.c)

    这个只需要图中所示的两个文件即可。下载之后找到这两个文件解压出来即可。

    下载地址  http://ftp.ntu.edu.tw/gnu/libc/#glibc-2.2.5.tar.gz

    这是glibc-2.2.5的压缩包中间提取的文件

    下面是glibc-2.15中需要提取的文件

    修改getopt.c

    gettext.h头文件不存在问题(glibc-2.15

    首先需要修改的是没有“gettext.h”这个头文件的问题。这里直接将其注释掉,然后修改后面的宏定义。

    这个修改仅是glibc-2.15版本中,如果是glibc-2.2.5版本的,是没有这个问题的。

    将下面的代码(大概在70行)

    1 #ifdef _LIBC
    2 # include <libintl.h>
    3 #else
    4 # include "gettext.h"
    5 # define _(msgid) gettext (msgid)
    6 #endif

    修改为

    1 #ifdef _LIBC
    2 # include <libintl.h>
    3 #else
    4 //# include "gettext.h"
    5 # define _(msgid)  (msgid)
    6 #endif

    修改后

    alloca的问题(无法解析的外部符号 _alloca)(glibc-2.15)

    关于alloca这个函数,从百度百科中摘抄下来一点。

    alloca内存分配函数,与malloc,calloc,realloc类似。但是注意一个重要的区别,_alloca是在栈(stack)上申请空间,用完马上就释放.

    包含在头文件malloc.h中.在某些系统中会宏定义_alloca使用。

    在glibc-2.2.5版本是没有这个问题的,这个问题存在于glibc-2.15版本中。

    编译生成的时候会报错

    1>  getopt.c
    1>e:getopt-wingetopt.c(571): warning C4013: “alloca”未定义;假设外部返回 int
    1>e:getopt-wingetopt.c(571): warning C4047: “初始化”:“option_list *”与“int”的间接级别不同
    1>getopt.obj : error LNK2019: 无法解析的外部符号 _alloca,该符号在函数 __getopt_internal_r 中被引用

    这里保存的原因是alloca这个函数没有定义,那么我们使用已经定义好的版本就是了。修改成如下图所示即可

    strings.h头文件不存在问题(glibc-2.2.5

    这个修改和前面的gettext.h文件的修改类似,但是区别是这个问题在glibc-2.15中不存在。

    这里的修改很简单,添加一个 HAVE_STRING_H 的宏定义即可。

    修改前                                                                      修改后

     

    添加getopt_long/getopt_long_only的定义

    这两个函数在getopt.h文件中声明了,但是其定义在getopt1.c中,可以直接将getopt1.c文件也拿过来用。因为这个文件中的内容不多,为了减少文件的数量,直接将其中有用的部分拷贝到getopt.c文件中是个不错的主意。

    glibc-2.2.5版本中,要拷贝的内容如下

     1 int
     2 getopt_long (argc, argv, options, long_options, opt_index)
     3      int argc;
     4      char *const *argv;
     5      const char *options;
     6      const struct option *long_options;
     7      int *opt_index;
     8 {
     9   return _getopt_internal (argc, argv, options, long_options, opt_index, 0);
    10 }
    11 
    12 /* Like getopt_long, but '-' as well as '--' can indicate a long option.
    13    If an option that starts with '-' (not '--') doesn't match a long option,
    14    but does match a short option, it is parsed as a short option
    15    instead.  */
    16 
    17 int
    18 getopt_long_only (argc, argv, options, long_options, opt_index)
    19      int argc;
    20      char *const *argv;
    21      const char *options;
    22      const struct option *long_options;
    23      int *opt_index;
    24 {
    25   return _getopt_internal (argc, argv, options, long_options, opt_index, 1);
    26 }

    如果是glibc-2.15版本的,除了这两个函数之外,还有两个可重入版本的可以添加进去

     1 int
     2 getopt_long(int argc, char *const *argv, const char *options,
     3 const struct option *long_options, int *opt_index)
     4 {
     5     return _getopt_internal(argc, argv, options, long_options, opt_index, 0, 0);
     6 }
     7 
     8 int
     9 _getopt_long_r(int argc, char *const *argv, const char *options,
    10 const struct option *long_options, int *opt_index,
    11 struct _getopt_data *d)
    12 {
    13     return _getopt_internal_r(argc, argv, options, long_options, opt_index,
    14         0, d, 0);
    15 }
    16 
    17 /* Like getopt_long, but '-' as well as '--' can indicate a long option.
    18 If an option that starts with '-' (not '--') doesn't match a long option,
    19 but does match a short option, it is parsed as a short option
    20 instead.  */
    21 
    22 int
    23 getopt_long_only (int argc, char *const *argv, const char *options,
    24 const struct option *long_options, int *opt_index)
    25 {
    26     return _getopt_internal (argc, argv, options, long_options, opt_index, 1, 0);
    27 }
    28 
    29 int
    30 _getopt_long_only_r(int argc, char *const *argv, const char *options,
    31 const struct option *long_options, int *opt_index,
    32 struct _getopt_data *d)
    33 {
    34     return _getopt_internal_r(argc, argv, options, long_options, opt_index,
    35         1, d, 0);
    36 }

    测试一下

    经过上面的修改,可以进行一点简单的测试了。

    测试用例不用自己写了,在getopt.cgetopt1.c文件中都有,直接拿过来用了。

    这里测试的时候没有区分是glibc-2.2.5还是glibc-2.15版本的getopt/getopt_long,因为两个测试的结果是一样的。

    getopt()函数的测试

    测试代码

     1 #include "getopt.h"
     2 #include <stdlib.h>
     3 #include <stdio.h>
     4 
     5 int
     6 main(int argc, char **argv)
     7 {
     8     int c;
     9     int digit_optind = 0;
    10 
    11     while (1)
    12     {
    13         int this_option_optind = optind ? optind : 1;
    14 
    15         c = getopt(argc, argv, "abc:d:0123456789");
    16         if (c == -1)
    17             break;
    18 
    19         switch (c)
    20         {
    21             case '0':
    22             case '1':
    23             case '2':
    24             case '3':
    25             case '4':
    26             case '5':
    27             case '6':
    28             case '7':
    29             case '8':
    30             case '9':
    31                 if (digit_optind != 0 && digit_optind != this_option_optind)
    32                     printf("digits occur in two different argv-elements.
    ");
    33                 digit_optind = this_option_optind;
    34                 printf("option %c
    ", c);
    35                 break;
    36             case 'a':
    37                 printf("option a
    ");
    38                 break;
    39             case 'b':
    40                 printf("option b
    ");
    41                 break;
    42             case 'c':
    43                 printf("option c with value '%s'
    ", optarg);
    44                 break;
    45             case '?':
    46                 break;
    47             default:
    48                 printf("?? getopt returned character code 0%o ??
    ", c);
    49         }
    50     }
    51 
    52     if (optind < argc)
    53     {
    54         printf("non-option ARGV-elements: ");
    55         while (optind < argc)
    56             printf("%s ", argv[optind++]);
    57         printf("
    ");
    58     }
    59 
    60     exit(0);
    61 }

    测试结果

    getopt_long的测试

     1 #include "getopt.h"
     2 #include <stdlib.h>
     3 #include <stdio.h>
     4 int
     5 main(argc, argv)
     6     int argc;        //这是早期的C语言函数参数的写法
     7     char **argv;    //现在不提倡这么写
     8 {
     9     int c;
    10     int digit_optind = 0;
    11 
    12     while (1)
    13     {
    14         int this_option_optind = optind ? optind : 1;
    15         int option_index = 0;
    16         static struct option long_options[] =
    17         {
    18             { "add", 1, 0, 0 },
    19             { "append", 0, 0, 0 },
    20             { "delete", 1, 0, 0 },
    21             { "verbose", 0, 0, 0 },
    22             { "create", 0, 0, 0 },
    23             { "file", 1, 0, 0 },
    24             { 0, 0, 0, 0 }
    25         };
    26 
    27         c = getopt_long(argc, argv, "abc:d:0123456789",
    28             long_options, &option_index);
    29         if (c == -1)
    30             break;
    31 
    32         switch (c)
    33         {
    34             case 0:
    35                 printf("option %s", long_options[option_index].name);
    36                 if (optarg)
    37                     printf(" with arg %s", optarg);
    38                 printf("
    ");
    39                 break;
    40 
    41             case '0':
    42             case '1':
    43             case '2':
    44             case '3':
    45             case '4':
    46             case '5':
    47             case '6':
    48             case '7':
    49             case '8':
    50             case '9':
    51                 if (digit_optind != 0 && digit_optind != this_option_optind)
    52                     printf("digits occur in two different argv-elements.
    ");
    53                 digit_optind = this_option_optind;
    54                 printf("option %c
    ", c);
    55                 break;
    56             case 'a':
    57                 printf("option a
    ");
    58                 break;
    59             case 'b':
    60                 printf("option b
    ");
    61                 break;
    62             case 'c':
    63                 printf("option c with value `%s'
    ", optarg);
    64                 break;
    65             case 'd':
    66                 printf("option d with value `%s'
    ", optarg);
    67                 break;
    68             case '?':
    69                 break;
    70             default:
    71                 printf("?? getopt returned character code 0%o ??
    ", c);
    72         }
    73     }
    74 
    75     if (optind < argc)
    76     {
    77         printf("non-option ARGV-elements: ");
    78         while (optind < argc)
    79             printf("%s ", argv[optind++]);
    80         printf("
    ");
    81     }
    82 
    83     exit(0);
    84 }

     测试结果

  • 相关阅读:
    Java EE 经验
    Java界面设计 Swing(1)
    Java开源库
    Java Abstract Class & Interface
    Selenium WebDriver Code
    Json在PHP与JS之间传输
    Live YUV420 和 OpenCV Mat 的互相转换
    Visual C++ 升级到 Visual Studio
    Sentiment Analysis resources
    C# XMLDocument
  • 原文地址:https://www.cnblogs.com/oloroso/p/4856104.html
Copyright © 2011-2022 走看看