【问题标题】:C: read json array using fscanfC: 使用 fscanf 读取 json 数组
【发布时间】:2018-03-17 06:35:26
【问题描述】:

我在这样的文件中有一个任意长度的 JSON 数组:

[ 36, 35, 34, 33, 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, 18 ]

我想获取整数并将它们存储在一个新数组中。

我尝试使用fscanf(f, " [ %d , ", data); 捕获第一个整数,但 fscanf 返回 -1(在 Ubuntu 终端上使用 gcc)。

格式说明符错了吗?如何跳过方括号,用逗号分隔不同的整数?

我的代码在这里:

typedef struct {
    int *data;
    unsigned int len;
} intarr_t;    

intarr_t *intarr_load_json(const char *filename) {

    if (filename == NULL) {
        return NULL;
    }

    FILE *f = fopen(filename, "r");

    if (f == NULL) {
        printf("file open failed\n");
        return NULL;
    }

    int char_input = 0;
    int count = 0;
    int num_count = 0;

    //count the # of numbers in the file by counting # of ","
    while ((char_input = fgetc(f)) != EOF) {
        if (char_input == 44) {
            count++;
        }
    }

    num_count = count+1;

    printf("num_count is %d\n", num_count);

    intarr_t *intarr_loaded_json = malloc(sizeof(intarr_t));

    if (intarr_loaded_json == 0) {
        return NULL; // intarr_loaded_json malloc failed
    }

    if (num_count == 0) {
        intarr_loaded_json->len = num_count;
        intarr_loaded_json->data = NULL;
        return intarr_loaded_json;
    }

    intarr_loaded_json->len = num_count;
    intarr_loaded_json->data = malloc(sizeof(int) * num_count);

    if (intarr_loaded_json->data == 0) {
        printf("Malloc failed\n");
        return NULL; 
    }

    int a = 0;
    int b = 0;
    int i = 0;
    //char temp;
    int value = 0;

    //printf("a is %d\n", a);

    if ((a = fscanf(f, "[ %d , ", intarr_loaded_json->data + i) > 0) {
        printf("got first number\n");
        i++;
    }

    //printf("temp is %c\n", temp);
    printf("a is %d\n", a);

    while ((b = fscanf(f, " , %d", intarr_loaded_json->data + i)) == 1) {
        i++;
        printf("do while loop %d th time\n", i);
    }

    printf("b is %d\n", b);
    // printf("intarr_loaded_json->len is %d\n", intarr_loaded_json->len);

    return intarr_loaded_json;

    fclose(f);
}

【问题讨论】:

  • 欢迎来到 Stack Overflow。请尽快阅读 AboutHow to Ask 页面,但更紧急的是,阅读有关如何创建 MCVE (minimal reproducible example) 的信息。您提供的内容过于零碎,无法进行大量分析。我们需要更多信息来帮助您——通过提供信息来帮助我们帮助您。
  • 一般来说,scanf()-family 格式规范上的尾随空格是个坏主意。但是,它在形式上并不是不正确的,应该可以工作。令人惊讶的是*data 的使用——您还没有展示data 是如何定义的。使用&data 或只使用data 会更正常。使用*data 意味着代码被传递了一个指向指针的指针,为数据分配空间,现在在所示的fscanf() 调用中初始化它。但是出了点问题,报告了-1——这意味着检测到 EOF 或硬错误(f 初始化是否正确?)。
  • 使用一些 JSON 库。喜欢jansson 或许多其他人
  • data 是指向先前 malloc 的数组的指针(为粗心的错误道歉)。 f 是由 fopen 正确初始化的流。
  • 感谢您添加代码。原来的两行代码无法解决问题;使用完整的代码,发现问题并不难。这就是 MCVE 很重要的原因。

标签: c json


【解决方案1】:

您将文件通读到 EOF 以计算逗号的数量。您永远不会倒带文件,因此当您开始尝试读取 [ 时,您处于文件末尾,并且 fscanf() 正确返回 EOF(又名 -1 — 从技术上讲,EOF 可以是任何负数,但实际上它总是-1)。

在尝试第二次读取数据之前添加rewind(f);

或者,最好不要预先计算 - 根据需要分配更多空间,通常每次需要更多空间时将分配的数组大小加倍以避免二次复制行为。

可能还有其他问题——比使用if (char_input == 44) 而不是if (char_input == ',') 或放错位置且无法访问的fclose(f); 更严重。但主要是您已读取 EOF,并且在尝试重新读取数据之前不会倒带。

【讨论】:

  • 成功了。我使用 realloc() 而不是计算整数的数量。感谢您指出我的错误并提供策略
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-22
  • 2018-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多