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-win\getopt.c(571): warning C4013: “alloca”未定义;假设外部返回 int
1>e:\getopt-win\getopt.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.c和getopt1.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.\n");
33 digit_optind = this_option_optind;
34 printf("option %c\n", c);
35 break;
36 case 'a':
37 printf("option a\n");
38 break;
39 case 'b':
40 printf("option b\n");
41 break;
42 case 'c':
43 printf("option c with value '%s'\n", optarg);
44 break;
45 case '?':
46 break;
47 default:
48 printf("?? getopt returned character code 0%o ??\n", 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("\n");
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("\n");
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.\n");
53 digit_optind = this_option_optind;
54 printf("option %c\n", c);
55 break;
56 case 'a':
57 printf("option a\n");
58 break;
59 case 'b':
60 printf("option b\n");
61 break;
62 case 'c':
63 printf("option c with value `%s'\n", optarg);
64 break;
65 case 'd':
66 printf("option d with value `%s'\n", optarg);
67 break;
68 case '?':
69 break;
70 default:
71 printf("?? getopt returned character code 0%o ??\n", 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("\n");
81 }
82
83 exit(0);
84 }
测试结果
来源:oschina
链接:https://my.oschina.net/u/4324616/blog/4397491