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://down1.chinaunix.net/distfiles/glibc-2.2.5.tar.bz2

这是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.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.\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 }

测试结果

时间: 2024-12-22 19:14:14

windows下的getopt/getoptlong函数的相关文章

[笔记]linux下和windows下的 创建线程函数

linux下和windows下的 创建线程函数 1 #ifdef __GNUC__ 2 //Linux 3 #include <pthread.h> 4 #define CreateThreadEx(tid,threadFun,args) pthread_create(tid, 0, threadFun, args) 5 #define CloseHandle(ph) 6 7 int pthread_create( 8 //指向线程标识符的指针. 9 pthread_t *restrict t

一个简单的Windows下的socket程序

服务器端代码server.cpp: 1 #include <stdio.h> 2 #include <WinSock2.h> 3 #pragma comment(lib,"ws2_32.lib") //加载ws2_32.dll 4 5 int main() 6 { 7 //初始化DLL 8 /************************************************************************/ 9 /*调用WSASta

使用cygwin移植Linux的项目到Windows下之总结(转)

使用cygwin移植Linux的项目到Windows下之总结(转) 原文 http://my.oschina.net/michaelyuanyuan/blog/68615?p=1 一.why 接到一个任务,把公司的某个在Linux下开发的项目(也就是一个程序啦)移植到Windows下,使得其可以在Windows下运行,并且运行的结果当然要是正确的啦,何谓正确,当然就是和Linux运行结果比对,一样就行. 二.难在何处 难就难在如何在Windows下编译通过.假设你在Linux下开发了一个这样的程

【转载】c/c++在windows下获取时间和计算时间差的几种方法总结

一.标准C和C++都可用 1.获取时间用time_t time( time_t * timer ),计算时间差使用double difftime( time_t timer1, time_t timer0 ). 精确到秒. 测试程序如下: #include <time.h> #include <stdio.h> int main() { time_t start ,end ; double cost; time(&start); sleep(1); time(&en

c和c++在windows下获取时间和计算时间差的方法总结

c/c++在windows下获取时间和计算时间差的几种方法总结 一.标准C和C++都可用 1.获取时间用time_t time( time_t * timer ),计算时间差使用double difftime( time_t timer1, time_t timer0 ). 精确到秒. 测试程序如下: 1 #include <time.h> 2 #include <stdio.h> 3 4 int main() 5 { 6 time_t start, end; 7 double c

windows下实现微秒级的延时

1.微秒级的延时肯定不能基于消息(SetTimer函数),因为一出现消息堵塞等就会影响精度,而且setTimer单位才是毫秒.实际响应时间可能要到55毫秒左右. 2.微秒级的延时也不能不能基于中断,VxD最快的时钟服务程序Set_Global_Time_Out函数才能保证1毫秒的精度.其他挂接int 8H中断处理函数等,只能保证55ms的精度.(有时还不能) 3.因此可以想到汇编下的那种基于循环执行语句的那种延时.但汇编那种代码不通用,跟cpu的频率有关. 所以可以用windows下的几个函数来

一个复杂的Windows下的socket程序

上节演示了 Linux 下的 socket 程序,这节来看一下 Windows 下的 socket 程序.异样,server.cpp 为效劳器端代码,client 为客户端代码.效劳器端代码 server.cpp: #include <stdio.h> #include <winsock2.h> #pragma comment (lib, "ws2_32.lib") //加载 ws2_32.dll int main(){ //初始化 DLL WSADATA ws

Windows下程序打包发布时的小技巧(使用Dependency Walker侦测不理想,改用VS自带的dumpbin则万无一失,还可查看dll导出的函数)

Windows下开发的应用程序在发布时,需要将其依赖的一些动态链接库一起打进安装包里面去.这个时候,快速确定这个程序到底依赖哪些动态链接库变得非常重要.很久以前写过一篇关于Qt程序安装包制作的博客,里面介绍了Dependency Walker这个小工具.但是实际操作起来并不理想,因为Dependency Walker将exe文件依赖的所有动态库以及动态库所依赖的动态库都列出来了.看得你一脸懵逼: 你很难分清楚:倒底哪些DLL是需要打包的,哪些DLL是系统自带的.而作为打包过程中的一个小步骤,我根

在 Windows 下用 TDM-GCC(MinGW)开发 DLL 涉及到数据同步锁及 DLL 初始化终止化函数的问题

在 Windows 下用 TDM-GCC(MinGW)开发 DLL 如果要用到数据同步锁,理论上可以采用 Windows API 提供的临界区实现(需要用到的函数有 InitializeCriticalSection.DeleteCriticalSection.EnterCriticalSection.LeaveCriticalSection),也可以采用 GCC 的 pthread 库中的 pthread mutex lock 互斥锁来实现(需要用到的函数有 pthread_mutex_ini