首页 > 解决方案 > 如何从文件的一行中读取多个浮点数

问题描述

我有以下代码,它从给定的输入文件中读取,然后读取到我制作的结构中。

    OFFFile ReadOFFFile(OFFFile fileData, FILE* srcFile)
{
    int nvert, nfaces;
    fscanf(srcFile, "%s\n");
    fscanf(srcFile, "%d %d %s\n", &nvert, &nfaces);
    fileData.nvert = nvert;
    fileData.nfaces = nfaces;
    
    fileData.vertices = (int *) malloc(fileData.nvert * sizeof(float));
    fileData.triFaces = (int *) malloc(fileData.nfaces * sizeof(int));

    // Print to check correct size was allocated
    printf("%d\n", (fileData.nvert * sizeof(float)));
    printf("%d\n", (fileData.nfaces * sizeof(int)));

    int i;
    float ftemp1, ftemp2, ftemp3;
    int itemp1, itemp2, itemp3;

    fscanf(srcFile, "%f", &ftemp1);
    printf("%lf", ftemp1);
    fscanf(srcFile, "%f", &ftemp2);
//    fscanf(srcFile, " %lf", &ftemp3);

/*    for (i = 0; i < nvert; ++i)
    {
        fscanf(srcFile, "%f %f %f\n", &ftemp1, &ftemp2, &ftemp3);
        fileData.vertices[i].x = ftemp1;
        fileData.vertices[i].y = ftemp2;
        fileData.vertices[i].z = ftemp3;
    }
*/
    return(fileData);
}

我遇到的问题是当前在引号中的整个最后一部分(上面的 2 fscanf 行是我试图测试的)。如果我只读取一个浮点数,它可以正常工作,但是当我添加第二个或第三个浮点数时,整个函数甚至都无法运行,尽管它仍然可以编译。我认为这是由输入中的负号引起的,但我不知道如何解决它。

数据在表格中

OFF
4000 7000 0
0.8267261981964111 -1.8508968353271484 0.6781123280525208
0.7865174412727356 -1.8490413427352905 0.7289819121360779

浮点数持续 4000 行(因此为循环)。这些是我制作的结构

typedef struct
{
    float x;
    float y;
    float z;
} Point3D;

typedef struct
{
    int face1;
    int face2;
    int face3;
} triFace;

typedef struct
{
    int nvert;
    int nfaces;
    Point3D *vertices;
    triFace *triFaces;
} OFFFile;

另一个文件的文本转储行少得多,在 for 循环中也不起作用。仅用于测试。https://justpaste.it/9ohcc

标签: cfile

解决方案


该行:

fscanf(srcFile, "%s\n");

正在调用未定义的行为。编译器应该警告你。一旦您调用了 UB,就没有必要进一步推测正在发生的事情。

我不清楚你打算用那条线做什么,但如果你%s在 scanf 中使用,你需要给它一个有效的地方来写入数据。您应该始终检查 scanf 返回的值,以确保您确实读取了一些数据,并且永远不要"%s"在没有宽度修饰符的情况下使用。也许你想要类似的东西:

char buf[256];
if( fscanf(srcFile, "%255s ", buf) == 1 ){
        /* Do something with the string in buf */
}

从您的评论来看,您似乎打算使用该 scanf 来跳过一行。我强烈建议使用while(fgetc)循环而不是 scanf 来做到这一点。如果您确实想使用 scanf,您可以尝试类似的方法fscanf(srcFile, "%*s\n"),但请注意它会在第一个空格处停止,并且不一定会占用整行。你也可以fscanf(srcFile, "%*[^\n]%*c");消耗这条线,但你最好fgetc在一个while循环中使用。


推荐阅读