解析C中的可选命令行参数

解析C中的可选命令行参数,c,command-line,getopt,C,Command Line,Getopt,我有一个接受可选参数的程序。必要的参数是文件和整数(1或更多)。可选参数是字符串和整数的混合 因此,命令行上的正确输入可能是: ./main trace_file 8 12 # (only necessary arguments) ./main –n 3000000 –p page.txt trace_file 8 7 4 # (with optional arguments) 我需要将trace\u file之后的整数放入数组。在启用可选参数时,我很难理解如何执行此操作,因为命令行上有另一

我有一个接受可选参数的程序。必要的参数是文件和整数(1或更多)。可选参数是字符串和整数的混合

因此,命令行上的正确输入可能是:

./main trace_file 8 12 # (only necessary arguments)

./main –n 3000000 –p page.txt trace_file 8 7 4 # (with optional arguments)
我需要将
trace\u file
之后的整数放入数组。在启用可选参数时,我很难理解如何执行此操作,因为命令行上有另一个整数。如果能朝着正确的方向努力,我将不胜感激,因为我不知道该怎么做

编辑: 到目前为止,我所能分析的参数是:

for(j=2, k=0; j<argc; j++, k++) {
    shift += atoi(argv[j]);
    shiftArr[k] = 32 - shift;
    bitMaskArr[k] = (int)(pow(2, atoi(argv[j])) - 1) << (shiftArr[k]);
    entryCnt[k] = (int)pow(2, atoi(argv[j]));
}

for(j=2,k=0;j我已经对此进行了一些思考,getopt没有简单的方法返回多个参数。我确实想知道如何定义“y::”,但已经忽略了这一点。选项包括

1) 有两个选项y和y每个int使用一个选项,并使用一个布尔标志捕获定义了y但未定义y的异常

2) 在getopt循环中保留像y这样的复杂选项。一旦getopt处理了选项和无序参数。预处理这些参数以捕获-y操作数,并在处理参数中编写代码以跳过-y及其操作数


3) 跨*nix命令提供多个值作为单个参数更为常见,该参数本身是一个逗号分隔的值列表。您可以通过在getopt处理中添加“y:”来实现这一点。它指向的字符串也需要解析为字符串A、B中的2个标记A和B,如果使用与POSIX兼容的版本,我看不出有任何重大问题

源代码(
goo.c
) 示例运行 如果您不能使用getopt()或其他一些为您做艰苦工作的函数,那么可能的策略是:

  • 创建新变量myargc、myargv,并将argc和argv复制到其中

  • 编写处理成对参数(如“-n 300000”或“-p page.txt”)的函数。通过引用将myargc和myargv传递到这些函数中。如果找到与参数相关联的值(如300000或page.txt),则每个此类函数返回该值,或者返回无效值(如-1或“”)如果不是。在任何一种情况下,该函数都会从myargv中删除这两项,并将myargc减量2

  • 如果您也有只是单个标志的参数,请为那些返回布尔值的参数编写函数,指示是否找到标志,从myargv中删除标志,并将myargc减1。(您可以用这种方式处理trace_文件,即使它不是可选的。我假设trace_文件只是一个标志,与它后面的8无关。)

  • 首先为每个可选参数调用函数。调用完myargc和myargv后,留在myargc和myargv中的内容应该只是您所需的参数,您可以像平常一样处理它们

如果您不能使用getopt()或其他一些为您做艰苦工作的函数,那么可能的策略是:

创建新变量myargc、myargv,并将argc和argv复制到其中

编写处理成对参数(如“-n 300000”或“-p page.txt”)的函数。通过引用将myargc和myargv传递到这些函数中。如果找到与参数相关联的值(如300000或page.txt),则每个此类函数返回该值,或者返回无效值(如-1或“”)如果不是。在任何一种情况下,该函数都会从myargv中删除这两项,并将myargc减量2

如果您也有只是单个标志的参数,请为那些返回布尔值的参数编写函数,指示是否找到标志,从myargv中删除标志,并将myargc减1。(您可以用这种方式处理trace_文件,即使它不是可选的。我假设trace_文件只是一个标志,与它后面的8无关。)


首先调用每个可选参数的函数。

到目前为止,您编写的代码是什么样子的?发布的内容很多。该程序是为学校的作业编写的,我们在那里模拟地址分页。因此,我问的问题实际上只是我程序的一个“简单”部分,但您希望看到什么?我真的只是ant想知道如何获取“trace_file”后面的整数,而不管用户如何在命令行上输入它们(例如../main trace_file 8 7 4–n 3000000–p page.txt),请参见如何创建MCVE()或SSCCE()-相同基本思想的两个名称和链接。您应该能够将代码缩减到主程序中管理选项的部分,并在打印其他参数的选项处理代码之后创建一个循环。您应该能够在大约30行内完成此操作,可能更少。您也可以在此处搜索类似问题;因此我肯定有很多。只是编辑了一下。谢谢你的回复。如果在可选参数之前列出了非可选参数,这会起同样的作用吗@JonathanLeffler@Ybarra:它取决于
getopt()的版本
您使用.POSIX时需要在非选项参数之前显示选项;BSD、Solaris、AIX和HP-UX、AFAICR.GNU也不需要(除非您将环境变量POSIXLY_设置为正确).我可能是少数,但我不喜欢GNU的行为,也不经常使用它。在以前的工作中,我有一套非常正确的设置,并且设法打破了其他人的脚本,该脚本依赖于它没有被设置。就我而言,这显然是令人讨厌的(或粗心的)。
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

/*
   ./main trace_file 8 12 # (only necessary arguments)

   ./main –n 3000000 –p page.txt trace_file 8 7 4 # (with optional arguments)
 */

static void usage(const char *argv0)
{
    fprintf(stderr, "Usage: %s [-n number][-p pagefile] trace n1 n2 ...\n", argv0);
    exit(EXIT_FAILURE);
}

int main(int argc, char **argv)
{
    int number = 0;
    char *pagefile = "default.txt";
    char *tracefile;
    int opt;

    while ((opt = getopt(argc, argv, "n:p:")) != -1)
    {
        switch (opt)
        {
        case 'p':
            pagefile = optarg;
            break;
        case 'n':
            number = atoi(optarg);
            break;
        default:
            usage(argv[0]);
        }
    }

    if (argc - optind < 3)
    {
        fprintf(stderr, "%s: too few arguments\n", argv[0]);
        usage(argv[0]);
    }

    tracefile = argv[optind++];
    printf("Trace file: %s\n", tracefile);
    printf("Page file:  %s\n", pagefile);
    printf("Multiplier: %d\n", number);
    for (int i = optind; i < argc; i++)
        printf("Processing number: %d (%s)\n", atoi(argv[i]), argv[i]);
    return 0;
}
$ gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
>      -Wold-style-definition -Werror goo.c -o goo
$ ./goo trace_file 8 12
Trace file: trace_file
Page file:  default.txt
Multiplier: 0
Processing number: 8 (8)
Processing number: 12 (12)
$ ./goo -n 3000000 -p page.txt trace_file 8 7 4
Trace file: trace_file
Page file:  page.txt
Multiplier: 3000000
Processing number: 8 (8)
Processing number: 7 (7)
Processing number: 4 (4)
$