c - 使用 fscanf,将文件扫描到 C 中的结构中,但第一个参数已经失败

标签 c struct scanf byte-order-mark

我有一个文件,我试图将每一行读入 C 中的结构中以进一步使用它。

该文件如下所示:

Bread,212,2.7,36,6,9.8,0.01,0.01,10,500 
Pasta,347,2.5,64,13,7,0.01,0.01,6,500 
Honey,340,0.01,83,0.01,0.01,0.01,0.01,22.7,425 
Olive-oil,824,92,0.01,0.01,0.01,0.01,13.8,35,500 
White-beans,320,2.7,44,21,18,0.01,0.01,11,400 
Flaxseed-oil,828,92,0.01,0.01,0.01,52,14,100,100 
Cereal,363,6.5,58,13,9.9,0.01,0.01,11,1000 
Hazelnuts,644,61.6,10.5,12,0.01,0.09,7.83,16.74,252 

因此,我编写了一个 for 循环来迭代文件中的行,尝试将每个值存储到 struct 的字段中。我尝试打印结构体的字段,但第一个参数字符串已经出了问题。

正在打印:

scanresult: 1, name:  ■B, kcal: 0.00, omega 3: 0.00, omega 6: 0.00, carb: 0.00, protein: 0.00, fib: 0.00, price: 0.00, weight: 0.00g

Scanres 应为 10,而不是 1,并且值应与文件第一行的值匹配。

我尝试过在格式化字符串的参数前面有或没有空格。我还尝试了编译器警告 -Wall-pedantic。没有发现问题。

还有什么可能导致此问题?

代码如下所示:

#include <stdio.h>

#define MAX_CHAR 100
#define SIZE_OF_SHELF 8

typedef struct {
    char name[MAX_CHAR];
    double kcal, fat, omega_3, omega_6, carb, protein, fib, price, weight;
} Food;

int main(void) {
    int i = 0, scanresult;
    Food Shelf[SIZE_OF_SHELF];
    FILE *fp;

    fp = fopen("foods.txt", "r");

    if (! fp) {
        printf("error loading file. bye.\n");
        return 0;
    }

    for (i = 0; !feof(fp); i++) {
        scanres = fscanf(fp, " %[^,],%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf ",
                         Shelf[i].name,
                         &Shelf[i].kcal, &Shelf[i].fat,
                         &Shelf[i].carb, &Shelf[i].protein,
                         &Shelf[i].fib, &Shelf[i].omega_3,
                         &Shelf[i].omega_6, &Shelf[i].price,
                         &Shelf[i].weight);
        
        printf("scanres: %d, name: %s, kcal: %.2f, omega 3: %.2f, omega 6: %.2f, carb: %.2f, protein: %.2f, fib: %.2f, price: %.2f, weight: %.2fg\n",
               scanres, Shelf[i].name, Shelf[i].kcal,
               Shelf[i].omega_3, Shelf[i].omega_6, Shelf[i].carb, 
               Shelf[i].protein, Shelf[i].fib, Shelf[i].price,
               Shelf[i].weight);
    }
    return 0;
}

如果有人发现我做错了什么,请告诉我。

最佳答案

检查文件的前三个字符中是否有字节顺序标记 (BOM)。您可以使用hexdump(或任何二进制编辑器)来检查它。

文件带有 BOM:


00000000  ef bb bf 42 72 65 61 64  2c 32 31 32 2c 32 2e 37  |...Bread,212,2.7|
00000010  2c 33 36 2c 36 2c 39 2e  38 2c 30 2e 30 31 2c 30  |,36,6,9.8,0.01,0|
00000020  2e 30 31 2c 31 30 2c 35  30 30 20 0a 50 61 73 74  |.01,10,500 .Past|
00000030  61 2c 33 34 37 2c 32 2e  35 2c 36 34 2c 31 33 2c  |a,347,2.5,64,13,|
...

文件不带 BOM:


00000000  42 72 65 61 64 2c 32 31  32 2c 32 2e 37 2c 33 36  |Bread,212,2.7,36|
00000010  2c 36 2c 39 2e 38 2c 30  2e 30 31 2c 30 2e 30 31  |,6,9.8,0.01,0.01|
00000020  2c 31 30 2c 35 30 30 20  0a 50 61 73 74 61 2c 33  |,10,500 .Pasta,3|
00000030  34 37 2c 32 2e 35 2c 36  34 2c 31 33 2c 37 2c 30  |47,2.5,64,13,7,0|
...

关于c - 使用 fscanf,将文件扫描到 C 中的结构中,但第一个参数已经失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70315096/

相关文章:

c - C 中 double 的二元运算

c++ - IUnknown 中的 addref 和 release,它们实际上是做什么的?

go - 试图将文字转换为 Golang 中的指针

c - 如何制作包含结构的堆栈?

c - 为什么我会出现分段失败?

C 结构不扫描所有输入

c - 如果分配了该区域,则访问超出其末尾的数组是否是未定义的行为?

c - 二进制补码形式的 64 位负整数

c - 逐行读取文本文件并从缓冲区扫描 - C

c - 用C读取和写入二进制文件