问题描述
我想实现一份 Linux 方法头命令的副本。如果用户输入 ./cprogram head -(option here)
,我希望该选项出现,但由于某种原因,我的代码从未输入 options 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 {
}
}
我非常感谢专家的眼光来看看我遗漏了什么。提前致谢。
解决方法
结合最热门评论中的所有建议:
.done
要测试,请使用这些 [a shell 脚本 #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;
}
] 进行调用:
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
,
为了让 getopt()
跳过 argv[1]
并解析下一个元素的选项,您应该在调用 optind
之前设置 getopt()
:
optind = 2;
另请注意,在将 argc > 1
与 argv[1]
进行比较之前,您还应该检查是否 "head"
。
这是修改后的版本:
#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,"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 */
}
}