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

如何仅用C语言fscanf()读取逗号分隔的多类型变量

问题:使用fscanf读取带特殊前缀的数值字段

给定格式的文本文件:

a,b,c
x,y,z

其中a为char*类型,b为float类型,c为double类型。示例输入文件如下:

apple,$12.34,test130.8
x,y,z

需要用fscanf()读取a、b、c并赋值给对应变量:将"apple"赋值给同类型的A;将"12.34"(而非"$12.34")赋值给float类型的B,以此类推。

尝试过两种代码:

  1. 用%[^,]匹配字段,但%[^,]仅适用于char*类型,无法直接赋值给float/double变量:
fp = the file pointer

char A[50];
float B;
double C;

fscanf(fp, "%[^,],%[^,],%[^,]\n", A, B, C);
  1. 用%s,%f,%lf格式,但会因b字段的$导致读取异常,B得到0.000000:
fscanf(fp, "%s,%f,%lf\n", A, B, C);

问题:能否解析%[^,]使其适配float类型?或者有其他正确读取的方法?


解决方法

方法1:固定前缀时直接跳过

如果数值字段的前缀是固定的(比如示例中的$),可以直接在fscanf格式串中指定跳过该前缀,再读取数值:

#include <stdio.h>

int main() {
    FILE *fp = fopen("test.txt", "r");
    if (!fp) {
        perror("Failed to open file");
        return 1;
    }

    char A[50];
    float B;
    double C;

    // %[^,]读取A,跳过$后读取float,再读取double
    int ret = fscanf(fp, "%[^,],$%f,%lf\n", A, &B, &C);
    if (ret == 3) {
        printf("A: %s, B: %.2f, C: %.1lf\n", A, B, C);
    } else {
        printf("Failed to read all fields\n");
    }

    fclose(fp);
    return 0;
}

方法2:先读字符串再转换数值(通用方案)

如果前缀不固定,可先用%[^,]把数值字段读取到临时字符串,再通过strtof/strtod提取有效数值:

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

int main() {
    FILE *fp = fopen("test.txt", "r");
    if (!fp) {
        perror("Failed to open file");
        return 1;
    }

    char A[50], temp_b[50], temp_c[50];
    float B;
    double C;

    int ret = fscanf(fp, "%[^,],%[^,],%[^,]\n", A, temp_b, temp_c);
    if (ret == 3) {
        // 跳过temp_b中的非数值字符,定位到数字起始位置
        char *num_start = temp_b;
        while (*num_start != '\0' && !((*num_start >= '0' && *num_start <= '9') || *num_start == '.')) {
            num_start++;
        }
        B = strtof(num_start, NULL);

        // 同理处理C字段
        num_start = temp_c;
        while (*num_start != '\0' && !((*num_start >= '0' && *num_start <= '9') || *num_start == '.')) {
            num_start++;
        }
        C = strtod(num_start, NULL);

        printf("A: %s, B: %.2f, C: %.1lf\n", A, B, C);
    } else {
        printf("Failed to read all fields\n");
    }

    fclose(fp);
    return 0;
}

方法3:用格式控制跳过非数值字符

利用fscanf的%*[...]匹配并忽略非数值字符,直接读取后面的数值:

#include <stdio.h>

int main() {
    FILE *fp = fopen("test.txt", "r");
    if (!fp) {
        perror("Failed to open file");
        return 1;
    }

    char A[50];
    float B;
    double C;

    // %[^,]读取A,%*[^0-9.]跳过所有非数字/小数点字符,再读取数值
    int ret = fscanf(fp, "%[^,],%*[^0-9.]%f,%*[^0-9.]%lf\n", A, &B, &C);
    if (ret == 3) {
        printf("A: %s, B: %.2f, C: %.1lf\n", A, B, C);
    } else {
        printf("Failed to read all fields\n");
    }

    fclose(fp);
    return 0;
}

注:%*[...]中的*表示匹配该模式但不存储到变量中,适合处理任意前缀的场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 02:06:04