fgets()+sscanf() 的意外行为:第一行错误和舍入浮点数

问题描述 投票:0回答:0

我对这种行为感到非常惊讶。我一定是做错了什么,但我不知道是什么。

我在

.xml
文件中有一个 133*21 的表格,并将其转换为
.csv
。在此 excel 转换中我没有丢失任何信息。

然后,我做了一个简单的程序,将那个表读取到不同的

structs

typedef struct{
    float xval;
    float yval;
    float zval;
} tTuple_float;

typedef struct{
    int A;
    int B;
    int C;
} tTuple_int;

节目是这样的:

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define MAXCHAR 1000

int main(void) {
    tTuple_float C1[133], C2[133], C3[133], C4[133], C5[133], C6[133];
    tTuple_int ref[133];
    FILE *fp;
    int i=0;
    char row[MAXCHAR];
    fp = fopen("filename.csv","r");
    if (fp==NULL){
        printf("Error opening file\n");
        return 1;
    }
    i=0;
    setbuf(stdout, NULL);
    while (i<133){
        fgets(row, MAXCHAR, fp);
        printf("%s", row);         //To compare with the row printed with the arrays
        sscanf(row, "%d;%d;%d;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f",
            &ref[i].A, &ref[i].B, &ref[i].C,
            &C1[i].xval, &C1[i].yval, &C1[i].zval,
            &C2[i].xval, &C2[i].yval, &C2[i].zval,
            &C3[i].xval, &C3[i].yval, &C3[i].zval,
            &C4[i].xval, &C4[i].yval, &C4[i].zval,
            &C5[i].xval, &C5[i].yval, &C5[i].zval,
            &C6[i].xval, &C6[i].yval, &C6[i].zval);
        printf("%d;%d;%d;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f;%f\n",
            ref[i].A, ref[i].B, ref[i].C,
            C1[i].xval, C1[i].yval, C1[i].zval,
            C2[i].xval, C2[i].yval, C2[i].zval,
            C3[i].xval, C3[i].yval, C3[i].zval,
            C4[i].xval, C4[i].yval, C4[i].zval,
            C5[i].xval, C5[i].yval, C5[i].zval,
            C6[i].xval, C6[i].yval, C6[i].zval);
        i++;
        setbuf(stdout, NULL);
    }
    fclose(fp);
    return 0;
}

我添加了

printf("%s", row);
来比较我从
fgets()
获得的字符串与我使用
sscanf()
保存的值。

看前两行:

我们可以看到:

  1. sscanf()
    在第一个根本不起作用
  2. 第二行第一个
    float
    715.973
    转换为
    715.973022
    ,而不是
    715.973000
  3. 第二行第五个
    float
    619.22
    转换为
    619.219971
    ,而不是
    619.220000

所以,在某些情况下它是加小数,在其他情况下它是减去小数。在 Stack Overflow 中进行了一些挖掘之后,我了解到 浮点数是不准确的 但是,我不知道的是:我该如何解决这个问题?有什么方法可以截断浮点数或将其四舍五入到小数点后三位的最佳方法是什么

除此之外,我们非常欢迎对代码本身进行任何偏离主题的改进。

编辑:提供最小可行示例(MWE)如下

#include <stdio.h>
#include <stdlib.h>
#define MAXCHAR 1000

typedef struct{
    float xval;
    float yval;
    float zval;
} tTuple_float;

typedef struct{
    int A;
    int B;
    int C;
} tTuple_int;

int main(void) {
    tTuple_float C1[3];
    tTuple_int  ref[3];
    FILE *fp;
    int i=0;
    char row[MAXCHAR];
    setbuf(stdout, NULL);
    fp = fopen("three_row.csv","r");
    if (fp==NULL){
        printf("Error opening file\n");
        return 1;
    }
    i=0;
    while (i<3){
        fgets(row, MAXCHAR, fp);
        printf("%s", row);
        sscanf(row, "%d;%d;%d;%f;%f;%f;",&ref[i].A, &ref[i].B, &ref[i].C,
                &C1[i].xval, &C1[i].yval, &C1[i].zval);
        printf("%d;%d;%d;%f;%f;%f\n",ref[i].A, ref[i].B, ref[i].C,
                C1[i].xval, C1[i].yval, C1[i].zval);
        i++;
        setbuf(stdout, NULL);
    }
    fclose(fp);
    return 0;
}

three_row.csv

1;2;3;111.111;222.222;333.333
4;5;6;444.444;555.555;666.666
7;8;9;777.777;888.888;999.999

运行 MWE 时我的控制台输出:

1;2;3;111.111;222.222;333.333
524294;0;-13376;0.000000;0.000000;0.000000
4;5;6;444.444;555.555;666.666
4;5;6;444.444000;555.554993;666.666016
7;8;9;777.777;888.888;999.999
7;8;9;777.776978;888.888000;999.999023
c scanf fgets
© www.soinside.com 2019 - 2024. All rights reserved.