getopt() 没有 return 下一个参数
getopt() doesn't return the next argument
看看这段代码:-
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[]){
char ch;
int value;
while((ch = getopt(argc, argv, "n: o"))!=EOF){
switch(ch){
case 'n':
value = atoi(optarg);
fprintf(stdout,"\nParameter n");
//Do something
break;
case 'o':
fprintf(stdout,"\nParameter 0");
//Do something
break;
default:
fprintf(stdout,"\nInvalid!");
}
argc -= optind;
argv += optind;
}
}
当我传递以下参数时
./program -n 123 -o
我得到这个结果
Parameter n
虽然我希望得到这个
Parameter n
Parameter o
为什么 getopt() 在循环的第 2 次迭代中不返回下一个参数?
更新
所以代码应该是这样的:-
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[]){
char ch;
int value;
while((ch = getopt(argc, argv, "n:o"))!=-1){
switch(ch){
case 'n':
value = atoi(optarg);
fprintf(stdout,"Parameter n (%d)\n", value);
//Do something
break;
case 'o':
fprintf(stdout,"Parameter o\n");
//Do something
break;
default:
fprintf(stdout,"Invalid!\n");
break;
}
}
}
主要问题
在循环中,你有:
argc -= optind;
argv += optind;
那是一场灾难——不要这样做。您可以在循环完成后(一次)使用这些语句,但不能在循环体中使用。它强制代码跳过选项;在严重的情况下,它最终可能会尝试解析空指针或环境,这两者都可能无济于事(并且都是未定义的行为,所以 YMMV)。
切题
请注意,您已指定空白是选项之一。因此有人可以写:
./a.out -' ' -n 123 -o
并且空白将被视为标志选项(如 -o
)。这可能不是你想要的。使用没有 space 的 "n:o"
。
你打印:
fprintf(stdout,"\nParameter 0");
该声明的三个小问题:
0
应该是 o
— 它们是不同的。
- 将换行符放在输出格式的末尾而不是开头(除非您想要双倍行距)。请注意,在打印换行符之前可能不会生成输出,因此末尾的换行符可确保打印数据更及时。
- 习惯上使用
fprintf(stdout, …)
而不是printf(…)
。不完全错误,但不寻常。
getopt()
函数在完成选项处理时由POSIX到return-1
定义,而不是EOF
。这是为了使其在 <unistd.h>
中的声明与 <stdio.h>
中 EOF
的定义无关。 (基本原理部分明确指出:getopt()
函数应 return -1
,而不是 EOF
,因此不需要 <stdio.h>
。 ) 历史上,某些系统在 <stdio.h>
中声明了 getopt()
,但 POSIX 将其置于 <unistd.h>
中并表示它 returns -1
.
你应该在 switch 的 default:
case 之后包含一个 break;
。这是一种基本的防御性编程措施 - 即使有人在 default:
标签后添加另一个 case 标签,它也能确保不会失败。
看看这段代码:-
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[]){
char ch;
int value;
while((ch = getopt(argc, argv, "n: o"))!=EOF){
switch(ch){
case 'n':
value = atoi(optarg);
fprintf(stdout,"\nParameter n");
//Do something
break;
case 'o':
fprintf(stdout,"\nParameter 0");
//Do something
break;
default:
fprintf(stdout,"\nInvalid!");
}
argc -= optind;
argv += optind;
}
}
当我传递以下参数时
./program -n 123 -o
我得到这个结果
Parameter n
虽然我希望得到这个
Parameter n
Parameter o
为什么 getopt() 在循环的第 2 次迭代中不返回下一个参数?
更新
所以代码应该是这样的:-
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char *argv[]){
char ch;
int value;
while((ch = getopt(argc, argv, "n:o"))!=-1){
switch(ch){
case 'n':
value = atoi(optarg);
fprintf(stdout,"Parameter n (%d)\n", value);
//Do something
break;
case 'o':
fprintf(stdout,"Parameter o\n");
//Do something
break;
default:
fprintf(stdout,"Invalid!\n");
break;
}
}
}
主要问题
在循环中,你有:
argc -= optind;
argv += optind;
那是一场灾难——不要这样做。您可以在循环完成后(一次)使用这些语句,但不能在循环体中使用。它强制代码跳过选项;在严重的情况下,它最终可能会尝试解析空指针或环境,这两者都可能无济于事(并且都是未定义的行为,所以 YMMV)。
切题
请注意,您已指定空白是选项之一。因此有人可以写:
./a.out -' ' -n 123 -o
并且空白将被视为标志选项(如 -o
)。这可能不是你想要的。使用没有 space 的 "n:o"
。
你打印:
fprintf(stdout,"\nParameter 0");
该声明的三个小问题:
0
应该是o
— 它们是不同的。- 将换行符放在输出格式的末尾而不是开头(除非您想要双倍行距)。请注意,在打印换行符之前可能不会生成输出,因此末尾的换行符可确保打印数据更及时。
- 习惯上使用
fprintf(stdout, …)
而不是printf(…)
。不完全错误,但不寻常。
getopt()
函数在完成选项处理时由POSIX到return-1
定义,而不是EOF
。这是为了使其在 <unistd.h>
中的声明与 <stdio.h>
中 EOF
的定义无关。 (基本原理部分明确指出:getopt()
函数应 return -1
,而不是 EOF
,因此不需要 <stdio.h>
。 ) 历史上,某些系统在 <stdio.h>
中声明了 getopt()
,但 POSIX 将其置于 <unistd.h>
中并表示它 returns -1
.
你应该在 switch 的 default:
case 之后包含一个 break;
。这是一种基本的防御性编程措施 - 即使有人在 default:
标签后添加另一个 case 标签,它也能确保不会失败。