【问题标题】:What is the easiest way to parse arguments from a file in C?从 C 文件中解析参数的最简单方法是什么?
【发布时间】:2017-02-11 22:45:30
【问题描述】:

考虑一个文件ArgumentFile.txt

int a=100;
int b[3] = { 5, 2, 5 };
double c = 0.0014;

还有主代码code.c

int main(int argc, char *argv[])
{
   if (argc > 1) FILE *f = fopen(argv[1], "r");
   ParseFile(f); // Set the parameters based on file
   DoStuff(a,b,c); // Run the process based on the parsed arguments
}

然后用户可以通过以下方式传递参数

./CodeExecutable ArgumentFile.txt

是否有从文件解析参数的标准解决方案?从命令行解析参数将相当于getopt?

【问题讨论】:

  • 请注意,fopen(argv[1], "r") 和 Source(argv[1])太简单了。应该是if (argc > 1) { FILE *f = fopen(argv[1], "r"); ...
  • modern 从命令行获取参数的方法是使用getopt 或getopt_long。详情见此帖:stackoverflow.com/questions/1973742/…
  • @bruceg 谢谢!是否有与getopt 等效的方法,它可以方便地不解析命令行参数而是来自文件的参数?
  • @chux 感谢帖子已编辑!
  • 作为 C 代码变量声明的输入文本文件的格式与问题的其余部分完全不一致,这表明该文件将包含与getopts() 可以处理的命令行参数等效的内容。

标签: c file parameters arguments parameter-passing


【解决方案1】:

使用纯 C 代码无法做到这一点。您必须编写特定于平台的汇编语言代码来处理它。

您最好的选择是使用 C 处理器。

int main(int argc, char *argv[])
{
#include "myfile.txt"
   // Do Stuff 
}

话虽如此,我不知道你会从中得到什么,而不是直接将myfile.txt 的内容放在main() 中。

【讨论】:

  • 显然你可以做到这一点,你可能只需要编写一个函数或一些代码来做到这一点。
  • 我很确定他并没有要求这样做;你完全误解了我认为的问题。
  • @MDXF,根据source(argv[1]); 位判断,OP 想要相当于 C 预处理器的 #include 语句。我不确定你在想什么。
  • 很抱歉给您带来了困惑。这显然是我的错误。我删除了source(argv[1]); 声明。该语句主要是为了举例说明我正在寻找的解析函数所期望的输出类型(或结果,而不是变量赋值)。
  • @Remi.b,也许您可​​以详细说明代码的“做事”部分。
【解决方案2】:

您不需要与getopt() 等效的,您可以完全使用getopt()。 getopt() 函数不专门处理命令行参数;它将处理任何指向命令行参数样式中的字符串的指针数组。

#define MAX_ARGS 256
#define MAX_FILE_LEN 4096

int main(int argc, char *argv[])
{
   if( argc > 1 )
   {
      FILE *f = fopen(argv[1], "r");
      if( f != 0 )
      {
         char fargs[MAX_FILE_LEN] = "" ;
         fread( fargs, 1, MAX_FILE_LEN, f ) ;

         // Build fargv from file content
         char* fargv[MAX_ARGS] ;
         int fargc = 0 ;

         fargv[fargc] = strtok( fargs, " \n\r" ) ;

         while( fargc < MAX_ARGS && fargv[fargc] != 0 )
         {
            fargc++ ;
            fargv[fargc] = strtok( 0, "\n\r" ) ;
         }

         // Process fargv using getopt()
         while( (char c = getopt( fargc, fargv, "a:b:c:")) != -1 )
         {
            switch( c )
            {
               ...
            }
         }
      }
   }

   ...

   return 0 ;
}

使用实际文件长度动态分配fargs 可能会更好,但以上只是说明性的。

您的输入文件可能如下所示:

-a 100
-b 5,2,5
-c 0.0014

getopt() 循环必须根据需要处理参数 - 例如使用 sscanf()。

        switch( c )
        {
           case 'a' : sscanf( optarg, "%i", a ) ; break ;
           case 'b' : sscanf( optarg, "%i,%i,%i", b[0], b[1], b[2] ) ; break ;
           case 'c' : sscanf( optarg, "%f", c ) ; break ; 
        }

        DoStuff( a, b, c ) ;

【讨论】:

    【解决方案3】:

    我使用 getopt()。这是一个允许更多灵活性的示例。这个例子演示了如何处理可选的 optarg 和多个 optargs。

    #include <stdio.h>
    #include <unistd.h>
    #include <string.h>
    
    void usage(void)
    {
        printf("usage: \n"
               "This example demonstrates how to add flexibility to the traditional linux getopt()\n"
               "This help text is printed if the program is executed without arguments\n"
               "or with an invalid argument configuration.\n"
               "to view the help file run without arguments or with -h\n"
               "Oterwise the program accepts two options: -d, -u\n"
               "-d: can come with 0 or one option argument\n"
               "-u: can come with one or more option arguments\n"
               "try this to see the output:\n"
               "./test -d aaa -u ccc 4 \"quoted multi token string\" -d -u\n");
    }
    
    int main(int argc, char **argv)
    {
        char data[101];
        int opt;
    
        memset(data, 0, 101);
        while ((opt = getopt(argc, argv, "hd:u:t:")) != -1) {
            switch (opt) {
            case 'h':
                usage();
                return 0;
            case 'd': // can accept 0 or 1 parameters
                if (optarg[0] == '-') { //not an optarg of ours...
                    optind--;
                    printf("option: -d. no tokens (another option follows)\n");
                    break;
                }
                strncpy(data, optarg, 100);
                printf("option: -d. tokens: %s\n", data);
                break;
            case 'u': //can accept one or more parameters ...
                strncpy(data, optarg, 100);
                printf("option: -u. tokens: %s", data);
                //do we have more arguments for 'u'?
                while( optind <= argc && argv[optind][0] != '-') {
                    strncpy(data, argv[optind], 100);
                    printf(", %s", data);
                    optind++;
                }
                printf(".\n");
                break;
            case ':': //this happens if we got an option which expects an arg without any optarg.
                if(optopt == 'd') {//lets allow a '-d' without its optarg
                    printf("option: -d. no tokens\n");
                    break;
                }
                //otherwise fall through to the default handler
            default: //covers ':' '?' for missing value,  '-h' for help, etc.
                printf("on error you get: opt=%c. optopt=%c opterr=%d\n", opt, optopt, opterr);
                return 0;
            }
        }
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 2013-07-06
      • 2010-09-05
      • 2023-03-17
      • 1970-01-01
      • 1970-01-01
      • 2011-02-08
      • 2014-05-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多