繁体   English   中英

在ANSI C中将命令行参数传递给程序的不同部分

[英]Passing command line arguments to different parts of my program in ANSI C

我试图阅读有关该主题的内容,但是当我尝试运行我认为正确的东西时,它并没有完成我想要的事情:)

我有一个主程序,该程序应带有三个强制性参数,我们称它们为t, p and s 然后,我有几个模块,作为其初始化的一部分,它们也依赖于命令行参数。 这些模块有一个命令行自变量,表明将要使用它们。

当我在主程序中构建可能的命令行选项字符串时,它看起来像t:p:s:并且我还循环了所有模块并请求它们的“触发”选项字符。 因此,完成的字符串可能看起来像t:p:s:iv ,其中iv是两个不同模块的触发器。

然后在while循环中,我做类似的事情(选项是上述字符串)

while ((opt = getopt(argc, argv, options)) != -1) {
        switch (opt) {
            case 't':
                break;
            case 's':
                break;
            case 'p':
                break;
            case 'h':
            default:
                ShowHelp(this, argc, argv);
                exit(EXIT_FAILURE);
        }

        /*
         * Check all available modules and see if options should be passed to it
         */
        i = 0;
        while((module = this->availablemodules[i++]) != NULL) {
            if(opt == module->triggerArg) {
                output = module->ParseOptions(module, argc, argv);
                AddActiveModule(this, module);
            }
        }
    }

this->availablemodules变量是指向现有模块的NULL终止指针数组。 如您所见,我首先检查主程序使用的选项,然后检查给定的选项是否是模块的触发选项,在这种情况下,我将发送该模块要解析的参数。

然后,该模块可能会使用不同的选项集。 所以输入的参数可能看起来像这样

./myprog -t foo -s bar -p 10 -i -c 2 -v -c 1 -t bar

其中-i-v是模块“触发器”,其后的选项应在该模块解析功能中处理。

我如何最好地完成这项工作? 我如何最好地处理这样一个事实:模块触发的选择可能是一样的(由主要程序所需的选项之一,即t:既用作主程序一个选项, t作为一个模块“触发”)? 是否可以强制某些命令为强制性命令,或者在解析所有选项后是否必须手动检查该命令?

首先,我使用每个模块的optionstring构造了主程序optionstring,但是如果不调用一个模块,则会使系统感到困惑。

我希望一切都清楚了,但如果不仅仅是问...我对此应该如何处理有些困惑,因此可能无法很好地解释它。

更新:我只是读了一些有关getopt_long的内容,并在想,是否有可能这样做

./myprog -t foo -s bar -p 10 --module=module1 -c 2 --module=module2 -c 1 -t bar

并且让module1module2是什么来标识要激活的模块? 还是会让解析器多次使用--module

一种方法是将参数的引号括在引号中:

./myprog -t foo -s bar -p 10 -i="-c 2" -v="-c1 -t bar"

然后将引用的参数传递给模块。 这使您可以在每个模块的有效参数集中重复参数标识符。

或者,使用.ini文件:

[global]
t=foo
s=bar
p=10

[i]
c=2

[v]
c1=true
t=bar

并将其作为唯一参数传递给应用程序。 有很多库可以解析这种文件(我认为它甚至是Win32 API的一部分)。

.ini文件的替代方案是.xml格式,但解析起来更复杂,但是您可以使用模式来验证文件。 同样,有些库可以为您做到这一点。

正如我在最初的更新中所述,我做了。 现在,我传递--module=nameofModule然后传递该模块的所有选项。 当识别到--module选项时,我停止在常规while循环中评估这些选项,而是将所有以下所有选项放在新数组中,以传递给指定模块的parseOptions函数。 我一直这样做,直到找到新的--module选项或EOF为止。 如建议的那样,我不对--module选项使用可打印的字符,因为如果现有选项具有相同的字符,则可能会混淆解析算法,而我使用字符0x07f (DEL)

 struct option long_options[] = {
      { "module", required_argument, &long_val, 0x7f   },
      { "src", required_argument, &long_val, 's'  },
      { "dst", required_argument, &long_val, 'd' },
      { 0,    0,    0,    0   }       /* terminating -0 item */
  };

我的解析选项循环看起来像这样

      // Hold pointer to a module activated by being declared in the arguments
      module* found_module = NULL;
      // Hold options to pass to module
      char* module_options[256];
      int  module_argc = 0;

      int arg_index = 0;

        while ((opt = getopt_long(argc, argv, "-0x7fsd", long_options, &long_opt_index)) != EOF) {
            ++arg_index;
            /*
             * If we have found a module declaration store all following options until EOF or a new
             * module is declared to be sent to the modules argument parsing function
             */
            if(found_module && long_val != 0x7f) {
                strcpy(module_options[module_argc], argv[arg_index]);
                ++module_argc;
            }
            else {

                if(found_module) {
                    output = found_module->ParseOptions(found_module, module_argc, module_options);
                    fprintf(stderr, "Adding module %s as active!\n", found_module->name);
                    AddActiveModule(this, found_module);
                    found_module = NULL;
module_argc = 0;
// todo: also empty the module_options array
                }

                switch (opt) {
                    case 0: /* this is returned for long options with option[i].flag set (not NULL).
    the flag itself will point out the option recognized, and long_opt_index is now relevant */
                        switch(long_val)
                        {
                            case 0x7f:
                                printf("Option --module,  Argument: %s.\n", long_opt_index, optarg);
                                i = 0;
                                while((module = this->availablemodules[i++]) != NULL) {
                                    if(strcmp(optarg, module->optmoduleName)) {
                                        found_module = module;
                                        continue;
                                    }
                                }

                                break;
                                /* there's no default here */
                        }
                        break;
                    case 'h':
                    default:
                        ShowHelp(this, argc, argv);
                        exit(EXIT_FAILURE);
                } // switch
            } // else
        } // while

    /*
     * Have a trailing check here since EOF will terminate while loop but we might have a
     * module left to activate
     */
        if(found_module) {
            output = found_module->ParseOptions(found_module, module_argc, module_options);
            fprintf(stderr, "Adding module %s as active!\n", found_module->name);
            AddActiveModule(this, found_module);
            found_module = NULL;
        }

这似乎很完美,但是我可能还是错过了一些东西。 如前所述,我有点对getopt和似乎能够进行的自动重新排序感到困惑。 当我收集-选项字符串开头的-可以防止这种情况,对吗?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM