【问题标题】:fseek() sets the pointer to wrong positionfseek() 将指针设置为错误的位置
【发布时间】:2015-11-01 01:25:31
【问题描述】:

我有一个具有以下结构的 .dat 文件:

Object name | Area | Length |Form Factor

我正在尝试找出哪个对象的面积最小。我读取了整个文件并使用 ftell() 跟踪具有最小区域的对象及其位置。当我读完文件后,我将流位置指示器设置为从 ftell() 获得的任何值。然后我读了那行作为我的最终结果,但现在,我读错了。

objects.dat:

toy1 12785.00 550.70 23.22
toy2 11506.50 495.63 0.48
Pen 35008.65 1450.98 0.17
Pencil 42788.35 1773.42 0.209
card7 128433.00 1552.67 0.67

代码:

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

using namespace std;

int main()
{
    FILE *cfPtr;
    errno_t err;

    char name[15];
    double area, length, fF;
    double minArea = 100000.0;
    long address, minAreaAdd;

    char string[100];

    if ((err = fopen_s(&cfPtr, "objects.dat", "r")) != 0)   // Check if we can reach the file
        printf("The file 'objecs.dat' was not opened to read.\n");
    else
    {
        while (fgets(string, 100, cfPtr)) 
        {
            address = ftell(cfPtr);
            sscanf_s(string,"%s %lf %lf %lf", &name, sizeof name, &area, &length, &fF);

            if (area < minArea)
            {
                minArea = area;
                minAreaAdd = address;
            }
        }

        cout << "Min Area: " << minArea << " Address: " << minAreaAdd << "\n\n";

        fseek(cfPtr, minAreaAdd, SEEK_SET);
        fgets(string, 100, cfPtr);
        sscanf_s(string, "%s %lf %lf %lf", &name, sizeof name, &area, &length, &fF);

        cout << "Name: " << name << " Area : " << area << " Length: " << length << " Form factor: " << fF << "\n";

        fclose(cfPtr);
    }
    return 0;
}

输出:

Min Area: 11506.5 Address: 55

Name: Pen Area : 35008.7 Length: 1450.98 Form factor: 0.17

【问题讨论】:

  • fseek() 工作正常,你的逻辑全错了。
  • 类似地,标记为 C C++。

标签: c++ fgets fseek ftell


【解决方案1】:

当您获得文件位置并将其存储到address 时,即是在您读入该行之后,因此当您寻求它以获取答案时,您将在 之后得到该行> 正确的。

【讨论】:

    【解决方案2】:

    正如“1201ProgramAlarm”所提到的,您在读取要保存的行后获取地址。也就是说,你在fgets之后使用ftell

    发生的情况是fgets 在读取数据时移动了文件位置指示器。这是因为fgets需要为下一次读取操作准备文件,否则你会卡在同一个位置,读取相同的数据。

    你需要颠倒这个逻辑。举一个例子:

    address = -1
    do
    {
        if (address >= 0) {
            sscanf_s(string,"%s %lf %lf %lf", &name, sizeof name, &area, &length, &fF);
    
            if (area < minArea)
            {
                minArea = area;
                minAreaAdd = address;
            }
        }
        address = ftell(cfPtr);
    } while (ret = fgets(string, 100, cfPtr));
    

    【讨论】:

    • while (address = ftell(cfPtr), fgets(string, 100, cfPtr)) { ... } 对我来说似乎不那么混乱......
    • 太好了,谢谢。 if 条件不应该是 if (address >= 0) 吗?否则,我相信它会跳过从位置 0 开始的第一行。
    • 是的,已修复。谢谢
    • 我同意,rici,我也会这样做,但它只是少了一些说教性。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-02
    • 2017-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多