如何以更简洁的方式处理 C 命令行参数标志?
How to handle C command line argument flags in a neater way?
我有一小段 C 代码,它采用一组命令行参数 --help
、-h
、-d
和 -o
(每个对应地代表“Help”、“Hexadecimal”、“Decimal”、“Octal”),我根据传递的参数调用某些函数,-h
将调用 hexaFlag()
,-dh
将调用hexaFlag()
和 decFlag()
。但是,为了做到这一点,我使用了一个混乱的 if else
块。有没有更简单的方法来实现这一目标?我被告知要使用 switch
语句,但考虑到我每次都检查不同的条件,我不知道如何在这里使用它。
main()
函数我指的代码:
int main(int argc, char* argv[]){
if(argc == 1){
printf("%s",usage());
printf("Use --help for more options.\n");
}
else if(strcmp(argv[1], "--help") == 0){
printf("%s", usage());
printf("Options are:\n -h = Hexadecimal values\n -d = Decimal values\n -o = Octal values\n --help = Shows this message\n");
}
else if(strchr(argv[1], '-') != NULL){
if(strchr(argv[1], 'h') != NULL){
hexaFlag(argc, argv);
}
if(strchr(argv[1], 'd') != NULL){
decFlag(2, argc, argv);
}
if(strchr(argv[1], 'o') != NULL){
octaFlag(argc, argv);
}
}
else {
decFlag(1, argc, argv);
}
return 0;
}
我的基本开关处理(示例),非常实用但可能不美观,是:
int main (int argc, char *argv[])
{
int i=0, number, files=0;
/* process switches; other prms are considered files (2)
that are opened for input/output. Files not specified
are taken as stdin and stdout. Prms can be in any order.
*/
while (++i < argc)
switch (argv[i][0]) {
case '-': while (*++argv[i])
switch (*argv[i]) {
case 'N':
++argv[i]; number= 0;
while (isdigit(*argv[i]))
number = number *10 + *argv[i]++ - '0';
argv[i]--;
break;
case 'P' : printf ("Prm: P\n"); break;
case 'O' : printf ("Prm: O\n"); break;
case 'o' : printf ("Prm: o\n"); break;
default :
printf ("Bad switch %c, ignored.\n",*argv[i]);
}
break;
default :
switch (files) {
case 0: if ((inf=fopen(argv[i],"r")) == 0)
pexit("Error opening input file %s.", argv[i]);
files++; break;
case 1: if ((outf=fopen(argv[i],"w")) == 0)
pexit ("Error creating output file %s.", argv[i]);
files++; break;
case 2: fprintf (stderr,"Too many file arguments: %s ignored.\n",argv[i]);
break;
} /* end switch files */
} /* end switch argc */
if (files <1) inf = stdin;
if (files <2) outf = stdout;
我认为您应该稍微修改函数签名以使它们保持一致。这将允许你做类似的事情:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libgen.h>
void hexaFlag(int x, int argc, char **argv) { printf("%d:%s\n", x, __func__); }
void decFlag(int x, int argc, char **argv) { printf("%d:%s\n", x, __func__); }
void octaFlag(int x, int argc, char **argv) { printf("%d:%s\n", x, __func__); }
struct args {
void (*f)(int, int, char **);
int x;
};
void
parse_args(int argc, char *argv[], struct args *A)
{
int c;
if( argc == 1 || !strcmp(argv[1], "--help") ){
printf("usage: %s [-hdo] [--help] arg [arg...]\n",
basename(argv[0]));
exit(EXIT_SUCCESS);
}
A->f = decFlag;
A->x = 1;
while( (c = getopt(argc, argv, "hdo")) != -1 ) {
switch( c ){
case 'h': A->f = hexaFlag; break;
case 'd': A->f = decFlag; A->x = 2; break;
case 'o': A->f = octaFlag; break;
default: exit(EXIT_FAILURE);
}
}
}
int
main(int argc, char* argv[])
{
struct args A;
parse_args(argc, argv, &A);
A.f(A.x, argc, argv);
return 0;
}
您可能不应该将 argc/argv 直接传递给辅助函数,但应该从它们中提取您需要的内容到 parse_args() 中的结构参数中。
我有一小段 C 代码,它采用一组命令行参数 --help
、-h
、-d
和 -o
(每个对应地代表“Help”、“Hexadecimal”、“Decimal”、“Octal”),我根据传递的参数调用某些函数,-h
将调用 hexaFlag()
,-dh
将调用hexaFlag()
和 decFlag()
。但是,为了做到这一点,我使用了一个混乱的 if else
块。有没有更简单的方法来实现这一目标?我被告知要使用 switch
语句,但考虑到我每次都检查不同的条件,我不知道如何在这里使用它。
main()
函数我指的代码:
int main(int argc, char* argv[]){
if(argc == 1){
printf("%s",usage());
printf("Use --help for more options.\n");
}
else if(strcmp(argv[1], "--help") == 0){
printf("%s", usage());
printf("Options are:\n -h = Hexadecimal values\n -d = Decimal values\n -o = Octal values\n --help = Shows this message\n");
}
else if(strchr(argv[1], '-') != NULL){
if(strchr(argv[1], 'h') != NULL){
hexaFlag(argc, argv);
}
if(strchr(argv[1], 'd') != NULL){
decFlag(2, argc, argv);
}
if(strchr(argv[1], 'o') != NULL){
octaFlag(argc, argv);
}
}
else {
decFlag(1, argc, argv);
}
return 0;
}
我的基本开关处理(示例),非常实用但可能不美观,是:
int main (int argc, char *argv[])
{
int i=0, number, files=0;
/* process switches; other prms are considered files (2)
that are opened for input/output. Files not specified
are taken as stdin and stdout. Prms can be in any order.
*/
while (++i < argc)
switch (argv[i][0]) {
case '-': while (*++argv[i])
switch (*argv[i]) {
case 'N':
++argv[i]; number= 0;
while (isdigit(*argv[i]))
number = number *10 + *argv[i]++ - '0';
argv[i]--;
break;
case 'P' : printf ("Prm: P\n"); break;
case 'O' : printf ("Prm: O\n"); break;
case 'o' : printf ("Prm: o\n"); break;
default :
printf ("Bad switch %c, ignored.\n",*argv[i]);
}
break;
default :
switch (files) {
case 0: if ((inf=fopen(argv[i],"r")) == 0)
pexit("Error opening input file %s.", argv[i]);
files++; break;
case 1: if ((outf=fopen(argv[i],"w")) == 0)
pexit ("Error creating output file %s.", argv[i]);
files++; break;
case 2: fprintf (stderr,"Too many file arguments: %s ignored.\n",argv[i]);
break;
} /* end switch files */
} /* end switch argc */
if (files <1) inf = stdin;
if (files <2) outf = stdout;
我认为您应该稍微修改函数签名以使它们保持一致。这将允许你做类似的事情:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <libgen.h>
void hexaFlag(int x, int argc, char **argv) { printf("%d:%s\n", x, __func__); }
void decFlag(int x, int argc, char **argv) { printf("%d:%s\n", x, __func__); }
void octaFlag(int x, int argc, char **argv) { printf("%d:%s\n", x, __func__); }
struct args {
void (*f)(int, int, char **);
int x;
};
void
parse_args(int argc, char *argv[], struct args *A)
{
int c;
if( argc == 1 || !strcmp(argv[1], "--help") ){
printf("usage: %s [-hdo] [--help] arg [arg...]\n",
basename(argv[0]));
exit(EXIT_SUCCESS);
}
A->f = decFlag;
A->x = 1;
while( (c = getopt(argc, argv, "hdo")) != -1 ) {
switch( c ){
case 'h': A->f = hexaFlag; break;
case 'd': A->f = decFlag; A->x = 2; break;
case 'o': A->f = octaFlag; break;
default: exit(EXIT_FAILURE);
}
}
}
int
main(int argc, char* argv[])
{
struct args A;
parse_args(argc, argv, &A);
A.f(A.x, argc, argv);
return 0;
}
您可能不应该将 argc/argv 直接传递给辅助函数,但应该从它们中提取您需要的内容到 parse_args() 中的结构参数中。