热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

getoptjava_windows下的getopt/getoptlong函数

windows下的getoptgetoptlong函数getoptgetopt_long函数是GNUC中的函数,在linux编程中很常用到。这里就不介绍了。windo

windows下的getopt/getoptlong函数

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

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

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

下载GLibC源码

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

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

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

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

4f6ace348eea85a7cb2bed1df14e4eb8.png

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

a23dbe5e7c05b9cf0a77a32d6f2abeef.png

修改getopt.c

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

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

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

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

1 #ifdef _LIBC2 # include

3 #else

4 # include "gettext.h"

5 # define _(msgid) gettext (msgid)6 #endif

修改为

1 #ifdef _LIBC2 # include

3 #else

4 //# include "gettext.h"

5 # define _(msgid) (msgid)6 #endif

4c6be33442b5b776ac193abb89ff3fc4.png

修改后

7ec766204876c70a251adca1b96aaf75.png

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

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

malloc,calloc,realloc类似。但是注意一个重要的区别,

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

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

编译生成的时候会报错

1> getopt.c1>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 中被引用

1244dfc6e6c58d41e32a942ce51cec42.png

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

2b08ceb524f07abb565a1ce28a51c8e6.png

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

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

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

修改前                                                                      修改后

a03e9abd2efcc6aa61f894a5f8654569.png

d7af247c8909929a4483fd8f156dd5a6.png

添加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 intargc;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 option15 instead.*/

16

17 int

18 getopt_long_only (argc, argv, options, long_options, opt_index)19 intargc;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 option20 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

3 #include

4

5 int

6 main(int argc, char **argv)7 {8 intc;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

60 exit(0);61 }

测试结果

3c2e0e431ddfe1f2b3b2d4cfe03489fe.png

getopt_long的测试

1 #include "getopt.h"

2 #include

3 #include

4 int

5 main(argc, argv)6 int argc; //这是早期的C语言函数参数的写法

7 char **argv; //现在不提倡这么写

8 {9 intc;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

83 exit(0);84 }

测试结果

267bdb58c842a4e1adac04f03f0191da.png



推荐阅读
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • 本文介绍了使用Java实现大数乘法的分治算法,包括输入数据的处理、普通大数乘法的结果和Karatsuba大数乘法的结果。通过改变long类型可以适应不同范围的大数乘法计算。 ... [详细]
  • 《数据结构》学习笔记3——串匹配算法性能评估
    本文主要讨论串匹配算法的性能评估,包括模式匹配、字符种类数量、算法复杂度等内容。通过借助C++中的头文件和库,可以实现对串的匹配操作。其中蛮力算法的复杂度为O(m*n),通过随机取出长度为m的子串作为模式P,在文本T中进行匹配,统计平均复杂度。对于成功和失败的匹配分别进行测试,分析其平均复杂度。详情请参考相关学习资源。 ... [详细]
  • 动态规划算法的基本步骤及最长递增子序列问题详解
    本文详细介绍了动态规划算法的基本步骤,包括划分阶段、选择状态、决策和状态转移方程,并以最长递增子序列问题为例进行了详细解析。动态规划算法的有效性依赖于问题本身所具有的最优子结构性质和子问题重叠性质。通过将子问题的解保存在一个表中,在以后尽可能多地利用这些子问题的解,从而提高算法的效率。 ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
  • 本文详细介绍了GetModuleFileName函数的用法,该函数可以用于获取当前模块所在的路径,方便进行文件操作和读取配置信息。文章通过示例代码和详细的解释,帮助读者理解和使用该函数。同时,还提供了相关的API函数声明和说明。 ... [详细]
  • 本文介绍了如何在给定的有序字符序列中插入新字符,并保持序列的有序性。通过示例代码演示了插入过程,以及插入后的字符序列。 ... [详细]
  • 本文介绍了一种划分和计数油田地块的方法。根据给定的条件,通过遍历和DFS算法,将符合条件的地块标记为不符合条件的地块,并进行计数。同时,还介绍了如何判断点是否在给定范围内的方法。 ... [详细]
  • Java String与StringBuffer的区别及其应用场景
    本文主要介绍了Java中String和StringBuffer的区别,String是不可变的,而StringBuffer是可变的。StringBuffer在进行字符串处理时不生成新的对象,内存使用上要优于String类。因此,在需要频繁对字符串进行修改的情况下,使用StringBuffer更加适合。同时,文章还介绍了String和StringBuffer的应用场景。 ... [详细]
  • 本文介绍了C函数ispunct()的用法及示例代码。ispunct()函数用于检查传递的字符是否是标点符号,如果是标点符号则返回非零值,否则返回零。示例代码演示了如何使用ispunct()函数来判断字符是否为标点符号。 ... [详细]
  • Python正则表达式学习记录及常用方法
    本文记录了学习Python正则表达式的过程,介绍了re模块的常用方法re.search,并解释了rawstring的作用。正则表达式是一种方便检查字符串匹配模式的工具,通过本文的学习可以掌握Python中使用正则表达式的基本方法。 ... [详细]
  • 本文介绍了PE文件结构中的导出表的解析方法,包括获取区段头表、遍历查找所在的区段等步骤。通过该方法可以准确地解析PE文件中的导出表信息。 ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
  • C++字符字符串处理及字符集编码方案
    本文介绍了C++中字符字符串处理的问题,并详细解释了字符集编码方案,包括UNICODE、Windows apps采用的UTF-16编码、ASCII、SBCS和DBCS编码方案。同时说明了ANSI C标准和Windows中的字符/字符串数据类型实现。文章还提到了在编译时需要定义UNICODE宏以支持unicode编码,否则将使用windows code page编译。最后,给出了相关的头文件和数据类型定义。 ... [详细]
author-avatar
无限制空间689
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有