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-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 }

 測試結果

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM