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

fscanf及同类函数使用细节:Todo应用ID检查的参数匹配优化问询

解决Todo应用ID检查的fscanf问题及优化方案

原代码的核心问题

你当前的fscanf调用存在格式说明符与参数数量不匹配的错误:格式串"%i: %s%c%s"包含4个格式说明符(%i、%s、%c、%s),但仅传入了1个参数&current_id。这属于C语言中的未定义行为,尽管当前程序能运行,但可能在不同环境下出现崩溃、数据错乱等问题,必须修正。

优化实现方案

方案1:修正fscanf参数匹配(基础修复)

首先要为每个格式说明符提供对应变量,同时针对你的存储格式,用%[^\x1F]替代%s(避免%s遇到空格就停止读取的问题),并限制读取长度防止缓冲区溢出:

FILE *file_in = fopen("todo.data", "r");
if (!file_in) { /* 处理文件打开失败 */ }

int target_id = current_id;
int id;
char title[256], desc[256];
char unit_sep;
int duplicate_found;

do {
    duplicate_found = 0;
    fseek(file_in, 0, SEEK_SET); // 每次检查前重置文件指针到开头
    // 读取格式:ID: 标题<Unit Separator>描述
    while (fscanf(file_in, "%i: %255[^\x1F]%c%255[^\n]", &id, title, &unit_sep, desc) == 4) {
        if (id == target_id) {
            duplicate_found = 1;
            target_id++; // 发现重复,ID自增
            break; // 跳出循环,重新检查新ID
        }
    }
} while (duplicate_found);

current_id = target_id;
fclose(file_in);

注意点:

  • %255[^\x1F]表示最多读取255个字符,直到遇到Unit Separator(ASCII 0x1F)
  • 每次发现重复ID后,必须重置文件指针到开头,重新检查新ID是否被占用

方案2:逐行读取后解析(更可靠)

fscanf对复杂格式的容错性较差,推荐用fgets逐行读取整行数据,再手动解析,更容易处理格式错误的行:

FILE *file_in = fopen("todo.data", "r");
if (!file_in) { /* 处理文件打开失败 */ }

int target_id = current_id;
char line[512];
int duplicate_found;

do {
    duplicate_found = 0;
    fseek(file_in, 0, SEEK_SET);
    while (fgets(line, sizeof(line), file_in)) {
        // 提取ID部分(找到第一个冒号)
        char *colon_pos = strchr(line, ':');
        if (!colon_pos) continue; // 跳过格式错误的行
        *colon_pos = '\0'; // 截断字符串,仅保留ID部分
        int id = atoi(line);
        
        if (id == target_id) {
            duplicate_found = 1;
            target_id++;
            break;
        }
    }
} while (duplicate_found);

current_id = target_id;
fclose(file_in);

优势:

  • 可以跳过格式不符合要求的行,避免解析错误
  • 手动解析逻辑更直观,便于调试和扩展
  • 更好控制缓冲区大小,降低溢出风险

方案3:直接获取最大ID(更高效)

如果你的需求只是找到未被占用的最小ID,没必要逐个检查current_id是否存在,直接遍历所有ID记录最大值,新ID设为max_id + 1即可:

FILE *file_in = fopen("todo.data", "r");
if (!file_in) { /* 处理文件打开失败 */ }

int max_id = 0;
char line[512];

while (fgets(line, sizeof(line), file_in)) {
    char *colon_pos = strchr(line, ':');
    if (!colon_pos) continue;
    *colon_pos = '\0';
    int id = atoi(line);
    if (id > max_id) {
        max_id = id;
    }
}

current_id = max_id + 1;
fclose(file_in);

适用场景:当你的ID是连续递增分配时,该方案效率最高,无需循环检查重复。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.13 17:10:14