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

如何修改scanf参数以读取(int float int/int)格式行直至空行?

解决方案

要解决这个问题,我们需要修正scanf的格式串和判断逻辑,同时避免未定义行为,以下是可行的修改方案:

核心问题分析

  1. fflush(stdin)是未定义行为:C标准仅允许对输出流使用fflush,对输入流调用它会导致不可预期的结果,必须移除。
  2. 判断条件错误:原代码仅检查scanf返回非0,但我们需要确保成功读取4个变量(返回值等于4),否则可能处理部分匹配的无效行。
  3. 未处理行边界和空行检测:原格式串没有处理行尾的多余字符,也无法准确识别空行。

修改后的代码

listNode *readLine(listNode *prvi){
    int min, mesec, dan;
    float raz;
    elem tmp;
    int ret;

    // 读取目标格式,同时跳过行尾的非换行字符
    ret = scanf("%d %f %d/%d%*[^\n]", &min, &raz, &dan, &mesec);
    
    if (ret == 4) {
        // 成功读取完整有效行
        tmp.minuti = min;
        tmp.razdaljina = raz;
        tmp.dan = dan;
        tmp.mesec = mesec;
        enqueue(prvi, tmp);
        
        // 吃掉当前行的换行符,避免影响下一次读取
        scanf("%*c");
        return prvi;
    } else if (ret == 0) {
        // 未匹配任何变量,检查是否是空行
        char c;
        // 跳过行首空白,尝试读取换行符
        if (scanf("%*[ \t]%c", &c) == 1 && c == '\n') {
            // 检测到空行,返回NULL终止读取
            return NULL;
        } else {
            // 无效行,跳过剩余内容后继续读取下一行
            scanf("%*[^\n]%*c");
            return readLine(prvi);
        }
    } else {
        // 部分匹配或EOF,跳过当前行剩余内容
        scanf("%*[^\n]%*c");
        // 若到达输入末尾,返回NULL;否则继续读取
        return feof(stdin) ? NULL : readLine(prvi);
    }
}

格式串说明

  • "%d %f %d/%d":精准匹配你需要的(int float int/int)格式。
  • %*[^\n]:跳过当前行中剩余的所有非换行字符(处理行尾可能存在的多余输入),*表示不存储这些字符。
  • %*c:单独调用吃掉换行符,确保下一次scanf从新的一行开始。
  • %*[ \t]:跳过空行中的前导空格或制表符,确保准确识别仅含空白的空行。

关键逻辑

  • 仅当scanf返回4时,才处理有效行,保证所有变量都被正确读取。
  • 当scanf返回0时,进一步检查是否是空行:若读取到换行符则终止,否则跳过无效行继续读取。
  • 处理部分匹配或EOF的情况,避免残留输入影响后续读取。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 18:22:36