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

C语言中使用fscanf区分存储double或字符串值的问题

C语言中使用fscanf区分存储double或字符串值的问题

我来帮你分析下你遇到的问题,核心原因是fscanf在匹配double类型失败时的行为和你预期的不一样,咱们一步步拆解:

问题根源

你当前的代码逻辑是先尝试用%lf读取浮点数,失败后再用%31s读取字符串,但fscanf处理%lf时的匹配规则会坑到你:
当fscanf("%lf", num)遇到类似+这样的符号(后面没有数字)时,它会先消耗掉这个符号,然后发现后续没有有效数字,于是返回0。此时文件指针已经移动到了符号后面的位置,后续调用%31s时,%s会自动跳过空白字符,直接读取后面的数字(比如你的例子里的3),导致原本的操作符+被彻底跳过,完全丢失。

解决方案

要解决这个问题,我们需要在尝试读取double之前,先记录当前文件指针的位置。如果读取失败(返回0),就把指针回溯到原来的位置,再尝试读取字符串。这样就能保证读取操作符时,不会跳过那些被%lf错误消耗的字符。

修改后的代码如下:

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

/*  A) Tries to read a double from the file and asign its value to the double pointed by num. If it was possible returns 1.
B) In other case, tries to read a string up to 31 chars and stores its value on the string
pointed by op, if it was possible returns 2.
C) In any other case it returns 0 (end of file, etc)*/
int num_or_op(FILE* f, double *num, char *op) {
    // 记录当前文件指针位置,用于回溯
    long current_pos = ftell(f);
    if (current_pos == -1) {
        // 获取位置失败,直接返回0
        return 0;
    }

    int read = fscanf(f, "%lf", num);
    if (read == 1) {
        // 成功读取double,返回1
        return 1;
    } else if (read == -1) {
        // 到达EOF或读取错误,返回0
        return 0;
    } else {
        // 读取double失败,回溯到之前的位置
        if (fseek(f, current_pos, SEEK_SET) != 0) {
            return 0;
        }
        // 尝试读取字符串
        int aux = fscanf(f, "%31s", op);
        if (aux == 1) {
            return 2;
        } else {
            // 读取字符串失败(EOF或错误),返回0
            return 0;
        }
    }
}

代码解释

  1. 指针回溯:用ftell记录读取double前的文件位置,失败时用fseek把指针移回去,确保后续读取字符串时能拿到原本的字符。
  2. 错误处理:增加了对ftell和fseek失败的判断,让代码更健壮。
  3. 逻辑对齐:严格按照题目要求的A→B→C顺序执行,没有偏离要求的读取方式。

用你的测试输入1 2 + 3来验证:

  • 前两次调用会成功读取1和2,返回1;
  • 第三次调用尝试读取+作为double失败,回溯指针后读取+作为字符串,返回2;
  • 第四次调用读取3,返回1。
    完全符合你的预期。

备注:内容来源于stack exchange,提问作者ELiJuY

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.22 10:58:07