C 中的 getopt() 在 if 语句后无法正常工作
getopt() in C not working correctly after if statement
我想实现 Linux 方法 head 命令的副本。如果用户输入 ./cprogram head -(option here)
我希望出现该选项,但由于某种原因我的代码从未输入选项 switch
语句。例如,命令行代码 ./cprogram head -n
永远不会进入 case 'n':
语句。该代码在 if
语句之前运行以检查 argv[1]
是否为 "head"
.
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv) {
int b;
int c;
int nflag = 0;
int Vflag = 0;
int hflag = 0;
int eflag = 0;
int oflag = 0;
char str[] = "head";
if (strcmp(argv[1], str) == 0) {
while ((c = getopt(argc, argv, "nVheo")) != -1) {
switch (c) {
case 'n':
if (nflag||Vflag||hflag||eflag||oflag) {
printf("only one option\n");
exit(1);
} else {
nflag++;
printf("n option\n");
}
break;
case 'V':
if (nflag||Vflag||hflag||eflag||oflag) {
printf("only one option\n");
exit(1);
} else {
Vflag++;
}
break;
case 'h':
if (nflag||Vflag||hflag||eflag||oflag) {
printf("only one option\n");
exit(1);
} else {
hflag++;
}
break;
case 'e':
if (nflag||Vflag||hflag||eflag||oflag) {
printf("only one option\n");
exit(1);
} else {
eflag++;
}
break;
case 'o':
if (nflag||Vflag||hflag||eflag||oflag) {
printf("only one option\n");
exit(1);
} else {
oflag++;
}
break;
default:
printf("invalid options\n");
abort();
}
}
} else {
}
}
我将不胜感激专家的眼光,看看我遗漏了什么。提前致谢。
结合最高评论中的所有建议:
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(int argc, char **argv)
{
int b;
int c;
int nflag = 0;
int Vflag = 0;
int hflag = 0;
int eflag = 0;
int oflag = 0;
char str[] = "head";
if (argc < 2) {
printf("not enough arguments\n");
exit(1);
}
if (strcmp(argv[1], str) != 0) {
printf("1st argument is not '%s'\n",str);
exit(1);
}
// skip over the [matched] str
--argc;
++argv;
while ((c = getopt(argc, argv, "nVheo")) != -1) {
if (nflag || Vflag || hflag || eflag || oflag) {
printf("only one option\n");
exit(1);
}
switch (c) {
case 'n':
nflag++;
printf("n option\n");
break;
case 'V':
Vflag++;
break;
case 'h':
hflag++;
break;
case 'e':
eflag++;
break;
case 'o':
oflag++;
break;
default:
printf("invalid options\n");
abort();
break;
}
}
return 0;
}
要测试,请使用这些 [a shell 脚本 test
] 调用:
./myprogram
./myprogram foo
./myprogram head
./myprogram head -n
./myprogram head -n -n
这是 sh -x ./test
输出:
+ ./myprogram
not enough arguments
+ ./myprogram foo
1st argument is not 'head'
+ ./myprogram head
+ ./myprogram head -n
n option
+ ./myprogram head -n -n
n option
only one option
更新:
上面的代码有点“作弊”。它通过将 str
(例如 "head"
)移动到程序名称 argv[0]
(例如 ./myprogram
)中来消除它。实际的程序名称被丢弃了。
更正确的做法是“滑动”argv
删除字符串,保留程序名:
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(int argc, char **argv)
{
int b;
int c;
int nflag = 0;
int Vflag = 0;
int hflag = 0;
int eflag = 0;
int oflag = 0;
char str[] = "head";
if (argc < 2) {
printf("not enough arguments\n");
exit(1);
}
if (strcmp(argv[1], str) != 0) {
printf("1st argument is not '%s'\n",str);
exit(1);
}
// skip over the [matched] str
for (int avidx = 1; avidx < argc; ++avidx)
argv[avidx] = argv[avidx + 1];
--argc;
while ((c = getopt(argc, argv, "nVheo")) != -1) {
if (nflag || Vflag || hflag || eflag || oflag) {
printf("only one option\n");
exit(1);
}
switch (c) {
case 'n':
nflag++;
printf("n option\n");
break;
case 'V':
Vflag++;
break;
case 'h':
hflag++;
break;
case 'e':
eflag++;
break;
case 'o':
oflag++;
break;
default:
printf("invalid options\n");
abort();
break;
}
}
return 0;
}
要让 getopt()
跳过 argv[1]
并从下一个元素解析选项,您应该在调用 getopt()
:
之前设置 optind
optind = 2;
另请注意,在将 argv[1]
与 "head"
进行比较之前,您还应检查是否 argc > 1
。
这是修改后的版本:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char **argv) {
int b;
int c;
int nflag = 0;
int Vflag = 0;
int hflag = 0;
int eflag = 0;
int oflag = 0;
char str[] = "head";
if (argc > 1 && strcmp(argv[1], str) == 0) {
optind = 2; // skip argv[1]
while ((c = getopt(argc, argv, "nVheo")) != -1) {
if (nflag | Vflag | hflag | eflag | oflag) {
fprintf(stderr, "only one option\n");
exit(1);
}
switch (c) {
case 'n':
nflag++;
printf("n option\n");
break;
case 'V':
Vflag++;
break;
case 'h':
hflag++;
break;
case 'e':
eflag++;
break;
case 'o':
oflag++;
break;
default:
fprintf(stderr, "invalid option `%c'\n", c);
abort();
}
}
/* perform head on files starting at argv[optind] */
} else {
/* test some other command */
}
}
我想实现 Linux 方法 head 命令的副本。如果用户输入 ./cprogram head -(option here)
我希望出现该选项,但由于某种原因我的代码从未输入选项 switch
语句。例如,命令行代码 ./cprogram head -n
永远不会进入 case 'n':
语句。该代码在 if
语句之前运行以检查 argv[1]
是否为 "head"
.
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv) {
int b;
int c;
int nflag = 0;
int Vflag = 0;
int hflag = 0;
int eflag = 0;
int oflag = 0;
char str[] = "head";
if (strcmp(argv[1], str) == 0) {
while ((c = getopt(argc, argv, "nVheo")) != -1) {
switch (c) {
case 'n':
if (nflag||Vflag||hflag||eflag||oflag) {
printf("only one option\n");
exit(1);
} else {
nflag++;
printf("n option\n");
}
break;
case 'V':
if (nflag||Vflag||hflag||eflag||oflag) {
printf("only one option\n");
exit(1);
} else {
Vflag++;
}
break;
case 'h':
if (nflag||Vflag||hflag||eflag||oflag) {
printf("only one option\n");
exit(1);
} else {
hflag++;
}
break;
case 'e':
if (nflag||Vflag||hflag||eflag||oflag) {
printf("only one option\n");
exit(1);
} else {
eflag++;
}
break;
case 'o':
if (nflag||Vflag||hflag||eflag||oflag) {
printf("only one option\n");
exit(1);
} else {
oflag++;
}
break;
default:
printf("invalid options\n");
abort();
}
}
} else {
}
}
我将不胜感激专家的眼光,看看我遗漏了什么。提前致谢。
结合最高评论中的所有建议:
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(int argc, char **argv)
{
int b;
int c;
int nflag = 0;
int Vflag = 0;
int hflag = 0;
int eflag = 0;
int oflag = 0;
char str[] = "head";
if (argc < 2) {
printf("not enough arguments\n");
exit(1);
}
if (strcmp(argv[1], str) != 0) {
printf("1st argument is not '%s'\n",str);
exit(1);
}
// skip over the [matched] str
--argc;
++argv;
while ((c = getopt(argc, argv, "nVheo")) != -1) {
if (nflag || Vflag || hflag || eflag || oflag) {
printf("only one option\n");
exit(1);
}
switch (c) {
case 'n':
nflag++;
printf("n option\n");
break;
case 'V':
Vflag++;
break;
case 'h':
hflag++;
break;
case 'e':
eflag++;
break;
case 'o':
oflag++;
break;
default:
printf("invalid options\n");
abort();
break;
}
}
return 0;
}
要测试,请使用这些 [a shell 脚本 test
] 调用:
./myprogram
./myprogram foo
./myprogram head
./myprogram head -n
./myprogram head -n -n
这是 sh -x ./test
输出:
+ ./myprogram
not enough arguments
+ ./myprogram foo
1st argument is not 'head'
+ ./myprogram head
+ ./myprogram head -n
n option
+ ./myprogram head -n -n
n option
only one option
更新:
上面的代码有点“作弊”。它通过将 str
(例如 "head"
)移动到程序名称 argv[0]
(例如 ./myprogram
)中来消除它。实际的程序名称被丢弃了。
更正确的做法是“滑动”argv
删除字符串,保留程序名:
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int
main(int argc, char **argv)
{
int b;
int c;
int nflag = 0;
int Vflag = 0;
int hflag = 0;
int eflag = 0;
int oflag = 0;
char str[] = "head";
if (argc < 2) {
printf("not enough arguments\n");
exit(1);
}
if (strcmp(argv[1], str) != 0) {
printf("1st argument is not '%s'\n",str);
exit(1);
}
// skip over the [matched] str
for (int avidx = 1; avidx < argc; ++avidx)
argv[avidx] = argv[avidx + 1];
--argc;
while ((c = getopt(argc, argv, "nVheo")) != -1) {
if (nflag || Vflag || hflag || eflag || oflag) {
printf("only one option\n");
exit(1);
}
switch (c) {
case 'n':
nflag++;
printf("n option\n");
break;
case 'V':
Vflag++;
break;
case 'h':
hflag++;
break;
case 'e':
eflag++;
break;
case 'o':
oflag++;
break;
default:
printf("invalid options\n");
abort();
break;
}
}
return 0;
}
要让 getopt()
跳过 argv[1]
并从下一个元素解析选项,您应该在调用 getopt()
:
optind
optind = 2;
另请注意,在将 argv[1]
与 "head"
进行比较之前,您还应检查是否 argc > 1
。
这是修改后的版本:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char **argv) {
int b;
int c;
int nflag = 0;
int Vflag = 0;
int hflag = 0;
int eflag = 0;
int oflag = 0;
char str[] = "head";
if (argc > 1 && strcmp(argv[1], str) == 0) {
optind = 2; // skip argv[1]
while ((c = getopt(argc, argv, "nVheo")) != -1) {
if (nflag | Vflag | hflag | eflag | oflag) {
fprintf(stderr, "only one option\n");
exit(1);
}
switch (c) {
case 'n':
nflag++;
printf("n option\n");
break;
case 'V':
Vflag++;
break;
case 'h':
hflag++;
break;
case 'e':
eflag++;
break;
case 'o':
oflag++;
break;
default:
fprintf(stderr, "invalid option `%c'\n", c);
abort();
}
}
/* perform head on files starting at argv[optind] */
} else {
/* test some other command */
}
}