You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言用fscanf读取JSON整数数组遇返回-1的问题排查与解决

问题分析与解决方案

咱们一步步拆解问题出在哪,然后搞定它。你遇到的fscanf返回-1的核心原因,是格式字符串太死板,和JSON数组的灵活格式不匹配。JSON数组的写法很灵活:[后面可能直接跟数字(比如[36,35]),逗号前后可能有0个或多个空格,甚至换行分隔,但你写的" [ %d , "要求必须严格匹配[ (空格)、整数、,(空格)——只要实际文本和这个格式有一点出入,fscanf就会匹配失败,返回EOF(也就是-1)。

正确的处理思路

我们只需要做两件核心事:

  1. 跳过开头的方括号[以及任意数量的空白字符(空格、制表符、换行)
  2. 循环读取整数,同时自动跳过整数后面的逗号和空白字符

完整实现代码

结合你的结构体定义,这里给出一个可运行的示例:

#include <stdio.h>
#include <stdlib.h>

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

IntArray read_json_int_array(FILE *f) {
    IntArray arr = {NULL, 0};
    int num;
    size_t capacity = 4; // 初始分配的容量,可根据需求调整

    // 第一步:跳过开头的[和所有空白字符(空格、制表符、换行)
    // %*[xxx] 表示跳过所有属于xxx集合的字符,*代表不存储这些字符
    if (fscanf(f, "%*[ \t\n[]]") == EOF) {
        return arr; // 文件开头没有找到数组标记,直接返回空数组
    }

    // 初始化动态数组
    arr.data = malloc(capacity * sizeof(int));
    if (!arr.data) {
        perror("malloc failed");
        return arr;
    }

    // 第二步:循环读取整数,同时跳过后面的逗号和空白
    // %d 读取整数,%*[ \t\n,] 跳过整数后的空白和逗号
    while (fscanf(f, "%d%*[ \t\n,]", &num) == 1) {
        // 数组容量不足时,自动扩容(每次翻倍)
        if (arr.len >= capacity) {
            capacity *= 2;
            int *temp = realloc(arr.data, capacity * sizeof(int));
            if (!temp) {
                perror("realloc failed");
                free(arr.data);
                arr.data = NULL;
                arr.len = 0;
                return arr;
            }
            arr.data = temp;
        }
        arr.data[arr.len++] = num;
    }

    // 最后跳过结尾的]和空白字符,确保文件指针位置正确
    fscanf(f, "%*[ \t\n]]");

    // 可选:将数组内存缩小到实际需要的大小,避免浪费
    int *temp = realloc(arr.data, arr.len * sizeof(int));
    if (temp) {
        arr.data = temp;
    }

    return arr;
}

// 测试用例
int main() {
    FILE *f = fopen("test.json", "r");
    if (!f) {
        perror("无法打开文件");
        return 1;
    }

    IntArray arr = read_json_int_array(f);
    fclose(f);

    printf("读取到 %u 个整数:\n", arr.len);
    for (unsigned int i = 0; i < arr.len; i++) {
        printf("%d ", arr.data[i]);
    }
    printf("\n");

    // 记得释放内存
    free(arr.data);
    return 0;
}

关键细节解释

  • %*[ \t\n[]]:这个格式符会跳过所有空格、制表符、换行符以及[,不管这些字符的顺序和数量,完美适配JSON数组开头的各种格式。
  • %d%*[ \t\n,]:先读取整数,然后自动跳过后面的空白(空格、制表符、换行)和逗号,不管逗号前后有没有空格,都能正确读取下一个整数。
  • 动态扩容:用realloc实现数组的自动扩容,避免一开始分配过大内存,也不会因为数组长度不够导致溢出。
  • 内存优化:最后用realloc把数组缩小到实际长度,减少内存浪费。

为什么你的原格式会失败?

假设你的JSON数组是[36,35,...]([后面直接跟数字),你的格式字符串" [ %d , "要求[后面必须有一个空格,而实际没有,所以fscanf找不到匹配的内容,直接返回EOF(-1)。即使你的数组是[ 36,35,...],第一个整数后面是36,(没有空格),格式字符串要求36后面必须是,(空格+逗号+空格),同样会匹配失败。

内容的提问来源于stack exchange,提问作者tz35

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 10:23:10