曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 5111|回复: 2
打印 上一主题 下一主题

getopt_long (长选项)

[复制链接]

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34395
跳转到指定楼层
楼主
发表于 2009-2-18 01:08:41 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
GNU C 库函数包含 getopt 的另外一个版本,叫做 getopt_long() .
另外,还有个 getopt_long_only() 的例程,它的作用和 getopt_long() 一样,但它只用于“所有”选项都是长选项并且选项以单 ‘-’ 开始的程序。

函数原型
int getopt_long(int argc, char * const argv[],
                  const char *optstring,
                  const struct option *longopts, int *longindex);

getopt_long 函数使用的参数比 getopt 多了两个。

第一个是一个结构体数组。结构体定义为:
struct option {
  const char *name;
  int has_arg;
  int *flag;
  int val;
}
其中,
name   为长选项的名字。长选项的长度可以进行任意缩减,但是缩减后的名称不能与其它选项相同或使人迷惑。
     
has_arg 表示这个选项是否要后接个参数。设置为 0 ( 符号常量 no_argument ),则表示后面不接参数;设这为 1( 符号常量 required_argument ),表示选项后面必须有值;
              设置为2 ( 符号常量 optional_argument ),表示后面要不要带参数是可选的。
   
flag    设置为 NULL,那么当这个使用这个选项时,getopt_long 就返回 val 中的值。否则,getopt_long 返回 0,并且 val 的值到由 flag 所指向的变量中。
  
val     这个值是发现了长选项的返回值,或者 flag 不是 NULL 要载入 *flag 中的值。典型情况下,如果 flag 不是 NULL,那么 val 是个真/假值,比如 1 或 0;
          另一方面,如果 flag 是 NULL,那么 val 通常是个字符常量。如果长选项与短选项一致,那么这个字符常量应该与 optstring 中出现的这个选项的参数相同。

第二个额外的参数是一个变量的地址,这个变量相当于 getopt 函数里的 optind 的“长选项”(long argument)版本;对于每一个能别识别的“长选项”,长选项的数组里的索引值就可以写到这个变量里。

长选项结构体定义在 getopt.h 中,并且必须包含常数 _GNU_SOURCE,以使能 getopt_long 函数。

测试代码1
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>

#define _GNU_SOURCE
#include <getopt.h>

int main(int argc, char *argv[])
{
        int opt;
        int index;
        int *longindex = &index;

struct option longopts[] = {
        {"initialize", 0, NULL, 'i'},  //使用 initialize 选项后,在调用 getopt_long 时,返回的值定义在 val 中,这里是 i
        {"file", 1, NULL, 'f'},
        {"list", 0, NULL, 'l'},
        {"restart", 0, NULL, 'r'},
        {"jump", 0, NULL, 'j'},
        {"kill", 0, NULL, 'k'},
        {0,0,0,0}};

        while((opt = getopt_long(argc, argv, ":ijkf:lr", longopts, longindex))
                != -1){
        printf("%d\n", *longindex);
        }

        return 0;
}
运行及输出
[root@localhost C]# ./getopt_long-2.exe --jump --kill --init --list
4
5
0
2

分析
可见,longindex 的值 longopts 里的元素顺序对相对,也就是它是数组的索引。如果改一下程序中的数组元素定义顺序:
struct option longopts[] = {
        {"initialize", 0, NULL, 'i'},
        {"jump", 0, NULL, 'j'},
        {"file", 1, NULL, 'f'},
        {"list", 0, NULL, 'l'},
        {"restart", 0, NULL, 'r'},
        {"kill", 0, NULL, 'k'},
        {0,0,0,0}};
那么运行输出为
[root@localhost C]# ./getopt_long-2.exe --jump --kill --init --list
1
5
0
3

测试代码2:(测试flag参数设置不同值时的情况)
01 #include <stdio.h>
02 #include <unistd.h>
03 #include <stdlib.h>
04
05 #define _GNU_SOURCE
06 #include <getopt.h>
07
08 int main(int argc, char *argv[])
09 {
10         int opt;
11         int index;
12         int *longindex = &index;
13         int flag;
14 /*
15 struct option longopts[] = {
16         {"initialize", 0, &flag, 'i'},
17         {"jump", 0, &flag, 'j'},
18         {"file", 1, &flag, 'f'},
19         {"list", 0, &flag, 'l'},
20         {"restart", 0, &flag, 'r'},
21         {"kill", 0, &flag, 'k'},
22         {0,0,0,0}};
23 */
24 struct option longopts[] = {
25         {"initialize", 0, NULL, 'i'},
26         {"jump", 0, NULL, 'j'},
27         {"file", 1, NULL, 'f'},
28         {"list", 0, NULL, 'l'},
29         {"restart", 0, NULL, 'r'},
30         {"kill", 0, NULL, 'k'},
31         {0,0,0,0}};
32
33         while((opt = getopt_long(argc, argv, ":ijkf:lr", longopts, longindex))
34                 != -1){
35         printf("The longindex: %d\n", *longindex);
36         printf("Return value is: %c\n", opt);
37         printf("The value return in variable-flag: %c\n", flag);
38         printf("----------------\n");
39
40         }
41
42         return 0;
43 }

运行及输出
[root@localhost C]# ./getopt_long-2.exe --jump --kill --init --list
The longindex: 1
Return value is: j
The value return in variable-flag:
----------------
The longindex: 5
Return value is: k
The value return in variable-flag:
----------------
The longindex: 0
Return value is: i
The value return in variable-flag:
----------------
The longindex: 3
Return value is: l
The value return in variable-flag:
----------------
由上输出可见,设置了 flag 参数为 NULL 后,函数返回 val 中的值并存往 opt 变量中。由于 flag 的值为内存中的随机值,所以这里没有对应的 ASCKII 码,故在输出时看到为空。

如果不设置 flag 为 NULL,函数返回0,val 中的值存在 flag 变量中,运行输出
[root@localhost C]# ./getopt_long-2.exe --jump --kill --init --list
The longindex: 1
Return value is: 0
The value return in variable-flag: j
----------------
The longindex: 5
Return value is: 0
The value return in variable-flag: k
----------------
The longindex: 0
Return value is: 0
The value return in variable-flag: i
----------------
The longindex: 3
Return value is: 0
The value return in variable-flag: l
----------------

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34395
沙发
 楼主| 发表于 2009-2-18 16:53:33 | 只看该作者

示例代码-2

01 #include <stdio.h>
02 #include <unistd.h>
03 #include <stdlib.h>
04
05 #define _GNU_SOURCE
06 #include <getopt.h>
07
08 int main(int argc, char *argv[])
09 {
10         int opt;
11         struct option longopts[] = {
12                 {"initialize", 0, NULL, 'i'},
13                 {"file", 1, NULL, 'f'},
14                 {"list", 0, NULL, '1'},
15                 {"restart", 0, NULL, 'r'},
16                 {0,0,0,0}};
17
18         while((opt = getopt_long(argc, argv, ":if:lr", longopts, NULL)) != -1) {
19                 switch(opt) {
20                         case 'i':
21                         case 'l':
22                         case 'r':
23                                 printf("option: %c\\n", opt);
24                                 break;
25                         case 'f':
26                                 printf("filename: %s\\n", optarg);
27                                 break;
28                         case ':':
29                                 printf("option needs a value\\n");
30                                 break;
31                         case '?':
32                                 printf("unknown option: %c\\n", optopt);
33                                 break;
34                         }
35                 }
36
37                 for(; optind < argc; optind++)
38                         printf("argument: %s\\n", argv[optind]);
39                 exit(0);
40 }

可以这么用
./longopt --init -l --file=fred.c 'hi there'

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34395
板凳
 楼主| 发表于 2009-4-14 14:10:21 | 只看该作者

用户程序中使用 GNU getopt() 或者 getopt_long()

可能希望在自己的程序中使用 GNU getopt() 或者 getopt_long(),并且可能让它们在 Linux  以外的系统上运行。这是可以的,只要从 GNU 程序或者从 GNU C Library (GLIBC) CVS 档案文件中拷贝源文件即可(http://sources.redhat.com)。这些源文件是 getopt.h、getopt.c 和 getopt1.c。他们处于 GNU Lesser GPL 的授权下,GNU Lesser GPL 允许在私权的程序中包含库函数。你的程序应该在包含 getopt.h,getopt.c 和 getopt1.c 文件的同时包含一份 COPYING.LIB 文件的拷贝。

如果只是调用这些函数,那么就在程序的发行版中包含这些源文件,然后将它们与其他的源文件一起编译。在那些调用 getopt_long() 的源代码中,应该使用
#include <getopt.h> ,而不是 #include "getopt.h" 。然后在编译的时候,在 C 编译器的命令行上加上 -I 。后面那种方式会首先寻找头文件的本地拷贝。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2025-5-3 23:15 , Processed in 0.084180 second(s), 21 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表