【问题标题】:Reading a formatted input using scanf使用 scanf 读取格式化的输入
【发布时间】:2015-07-12 10:06:59
【问题描述】:

我想使用scanf从标准输入读取一些变量及其值。输入格式如下:

MY_VARIABLE_BEGIN
var1 
var2
...
MY_VARIABLE_END
MY_VALUES_BEGIN
val1
val2
...
MY_VALUES_END 

输入由两部分组成:

第 1 部分:该部分的变量名称由 MY_VARIABLE_BEGIN ,MY_VARIABLE_END 分隔

第 2 部分:这部分每个变量的值由 MY_VALUES_BEGIN、MY_VALUES_BEGIN 分隔

问题是我不知道变量的数量和它们的值。 任何人都可以帮我找到正确的格式来传递给 scanf 函数,或者是否有其他解决方案可以解决这个问题?

输入示例

MY_VARIABLE_BEGIN
var1 
var2
MY_VARIABLE_END
MY_VALUES_BEGIN
1
5
MY_VALUES_END 

我应该读取 2 个变量 var1 和 var2,var1=1 和 var2=5

【问题讨论】:

  • 开始和结束字符串是人造的还是真的写入标准输入?你能绝对确定每个变量都有一个值吗?
  • 您必须将每一行作为字符串读取(使用例如fgets(3)),然后扫描字符串的开头以查找MY_ 部分,如果不是,则解析变量(使用例如sscanf(3) 并将变量存储到一个数组中(根据需要增加数组,例如realloc(3))。这是一种非常通用的方法;您可以对输入数据使用一些约束。
  • 请提供一个具体的例子,使用实数和变量,我可以提供一个C代码供您阅读。
  • @cad 1) 开始和结束字符串( MY_VARIABLE_BEGIN,MY_VARIABLE_END ,MY_VALUES_BEGIN,MY_VALUES_END ) 确实写在标准输入中,它们用作分隔符。2) 我假设每个变量都有值
  • @fedi 是的,它们是分隔符,但它们之间的内容是什么。请提供有关它的信息。

标签: c scanf


【解决方案1】:

你可以试试这个

char line[256];
fgets(line, sizeof(line), stdin);
if (strcmp(line, "MY_VARIABLE_BEGIN") {
    do {
        fgets(line, sizeof(line), stdin);

        // . . . do something with the line

    } while (strcmp(line, "MY_VARIABLE_END"));
}

不确定它是否会起作用。

【讨论】:

    【解决方案2】:

    scanf 做这件事很痛苦。为什么不使用 C 中的正则表达式? 这是一个完整的工作程序,显示它是多么容易。 首先将所有数据读入一个字符串,data。我只是使用一个常数。 使用regcomp 编译您的模式,然后使用regexec 将其应用于您的字符串。 它返回一个匹配组的数组,这些组对应于模式的(.*?) 部分。 0 组在此示例中不感兴趣,因为它只是整个数据。

    对于其他 2 组,您将获得匹配开始和结束字符串中的索引。 使用strndup() 复制这些。使用 strtok 在换行符 \n 上拆分此 dupptr 在每个点上都有每个变量和值。

    /* regex example. meuh on stackoverflow */
    #include <stdlib.h>
    #include <sys/types.h>
    #include <regex.h>
    #include <errno.h>
    #include <string.h>
    #include <stdio.h>
    
    void pexit(char *str){
        extern int errno;
        perror(str);
        exit(errno);
    }
    #define NUMMATCH (1+2) /* max num matching capture groups in pattern */
    main(int argc, char **argv){
        regex_t myexpn;
        regmatch_t matches[NUMMATCH] = {0};
        int rc,i;
        char *data = "\n\
    MY_VARIABLE_BEGIN\n\
    var1 \n\
    var2\n\
    ...\n\
    MY_VARIABLE_END\n\
    MY_VALUES_BEGIN\n\
    val1\n\
    val2\n\
    ...\n\
    MY_VALUES_END\n\
    ";
        char *delim = "\n";
        char *pattern = "\\s*MY_VARIABLE_BEGIN\\s*(.*?)MY_VARIABLE_END.*?MY_VALUES_BEGIN\\s*(.*?)MY_VALUES_END";
        /* need REG_EXTENDED to use () in pattern else \\(\\) */
        rc = regcomp(&myexpn, pattern, REG_EXTENDED);
        if(rc!=0)pexit("regcomp");
        rc = regexec(&myexpn, data, NUMMATCH, matches, 0);
        if(rc==REG_NOMATCH)printf("no match\n");
        else{
            for(i = 1;i<NUMMATCH;i++){ /* ignore group 0 which is whole match */
                if(matches[i].rm_so!=-1){
                    char *dup = strndup(data+matches[i].rm_so, matches[i].rm_eo-matches[i].rm_so);
                    printf(" match %d %d..%d \"%s\"\n",i, matches[i].rm_so, matches[i].rm_eo, dup);
                    char *ptr = strtok(dup, delim);
                    while(ptr){
                        printf("    token: %s\n",ptr);
                        ptr = strtok(NULL, delim);
                    }
                    free(dup);
                }
            }
        }
        regfree(&myexpn);
    }
    

    打印出来:

     match 1 19..34 "var1 
    var2
    ...
    "
        token: var1 
        token: var2
        token: ...
     match 2 66..80 "val1
    val2
    ...
    "
        token: val1
        token: val2
        token: ...
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-06-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-05-11
      相关资源
      最近更新 更多