2017-02-20 8 views
1

У меня есть .dat-файл, который постоянно обновляется. Я хочу получить данные из последней строки в файле. Но я получаю неточные результаты. Вот myfile.DAT:fseek и fscan дают неправильные результаты из .DAT-файла в C++

# Time forces(pressure, viscous) moment(pressure, viscous) 
0.005 (((2 10 4) (3 6 0)) ((12 60 -13) (4.88 0.5 -0.32))) 
0.01 (((2 20 2) (4 7 3)) ((0.0024 1 -70) (40 6000 -1200))) 

А вот C++ код:

#include <iostream> 
#include <fstream> 
#include <string> 

int main() 
{ 
    FILE * force; 
    force = fopen("file.dat", "r"); 
    float timestep; 
    float fxp; 
    float fyp; 
    float fzp; 
    float fxv; 
    float fyv; 
    float fzv; 
    float mxp; 
    float myp; 
    float mzp; 
    float mxv; 
    float myv; 
    float mzv; 

    char c; 

    fseek(force,-285,SEEK_END); 

    while(c != '\n') 
    { 
    c = fgetc(force); 
    } 

    fscanf(force, "%f ((%f %f %f) (%f %f %f)) ((%f %f %f) (%f %f %f))", &timestep, &fxp, &fyp, &fzp, &fxv, &fyv, &fzv, &mxp, &myp, &mzp, &mxv, &myv, &mzv); 

    fclose(force); 

    float ftotal = fxp + fxv; 

    std::cout << "Here is f_total = " << ftotal << " N" << std::endl; 

    return 0; 
} 

И вот результат:

Here is f_total = 0 N 

Очевидно, что это неправильно. Оно должно быть 2 + 4 = 6.

+0

Что такое «последняя строка» в файле, который постоянно обновляется? –

+0

Забавно, что вы '#include ' и вы не используете ни один из классов 'std :: * fstream' – WhiZTiM

+0

Если файл записывается по мере его чтения, последняя строка может быть неполной, поскольку автор имеет часть его буферизована. – Barmar

ответ

1

Ваш fscanf строка Формат:

"%f ((%f %f %f) (%f %f %f)) ((%f %f %f) (%f %f %f))" 

, но должно быть:

"%f (((%f %f %f) (%f %f %f)) ((%f %f %f) (%f %f %f)))" 

Edit: Это, скорее всего, не лучший способ сделать это (переход 2 назад, 1 вперед), но проверьте, работает ли он с этим изменением:

fseek(force, -1, SEEK_END); 

while (c != '\n') 
{ 
    c = fgetc(force); 
    fseek(force, -2, SEEK_CUR); 
} 
+0

Спасибо. Я попытался, но он дал мне «Вот f_total = 5 N». Это должно быть 6. –

+0

Это дает мне 6, и я создал этот .dat-файл с точно таким же контентом. Скомпилируйте код, который вы разместили здесь, создайте новый файл с опубликованным контентом и повторите попытку. – mpiatek

+0

Я создал новый .dat и C++-код. Результат все равно 5. Даже я изменил значения файла. Он всегда дает 5. –

0

1 fscanf возвращает количество полей, отсканированных - так что быстрая проверка заключается в том, чтобы добавить «int n = fscanf (....» - тогда проверьте, что «n» - это то, что, по вашему мнению, должно быть. Это может сэкономить вам много царапин на голове.

2: Лучше, чем предполагать длину линии с помощью поиска с конца, сканировать \ n с начала файла, а затем искать назад до последнего, прежде чем делать fscanf - это также позволит вам легко выбрать конкретный номер строки. Далее будет сканировать весь файл, а затем искать назад к последней строке (предполагается, что файл не имеет \ п в качестве последнего символа)

int lineno = 1; 
int lastLine = 0; 
while(c != EOF) 
{ 
    c = fgetc(force); 
    if(c == '\n') 
    { 
     ++lineno; 
     lastLine = ftell(force); 
    } 
} 
printf("%d lines, pos=%d\n", lineno, lastLine); 
fseek(force, lastLine, SEEK_SET); 
+0

Спасибо. Я скомбинировал ваш код с проблемой. Теперь я получаю 4 строки, pos = 182 Здесь f_total = 0 N Кстати, как вы сказали, я думаю, что настоящая проблема здесь заключается в определении -285. Я пробовал этот номер с -65 и без проблем. Это дало мне правильный ответ. Я попытаюсь найти решение и сообщить об этом позже. –

Смежные вопросы