У меня проблема с чтением TXT-файла в DLL-файле Windows NT 4.0; и, прежде чем вы спросите, я не заинтересован в переносе этого на новую ОС. Я просто хочу решить эту проблему и позволить другим после меня беспокоиться о переносе этого супер-унаследованного программного обеспечения.
Проблема возникает, когда я читаю текстовый файл с помощью fscanf, как показано:
infile_ptr = fopen("c:\\LumaGem\\orbit.txt", "r");
byteoffset=0;
while(!feof(infile_ptr) )
{
r=0.0; s1=0.0; s2=0.0; e1=0.0; e2=0.0; e3=0.0; d=0.0; f=0.0;
fseek(infile_ptr, byteoffset, SEEK_SET);
fscanf(infile_ptr,"%7lf %7lf %7lf %7lf %7lf %7lf %7lf %7lf", &r, &s1, &s2, &e1, &e2, &e3, &d, &f);
byteoffset=0; byteoffset = ftell(infile_ptr);
}
fclose(infile_ptr);
Файл txt, созданный с помощью MATLAB, состоит из 128 строк по 8 столбцов, разделенных 5 пробелами, и отформатирован так же, как и в MATLAB:
fprintf(fid,'%7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f %7.3f \n', variables);
Этот код не был написан мной, и работал в течение нескольких лет. Однако недавно нам пришлось перестраивать / переустанавливать ОС Windows NT 4.0 и программное обеспечение, и теперь я получаю странную ошибку. Программа прекрасно читает txt-файл, используя код, представленный сверху, пока не дойдет до строки 123, после чего дважды читает 8-й столбец, в результате чего все последующие переменные будут сдвинуты на одну позицию, полностью испортив последнюю несколько строчек программы. Интересно, что эту проблему можно решить, вручную скопировав и вставив первые 123 строки в новый текстовый файл, а затем последние несколько строк одну за другой в тот же новый текстовый файл и используя его в качестве входных данных (копирование выполнено на машине NT внутри компа). Это устраняет проблему двойного чтения. Я понятия не имею, какие проблемы могут вызвать эту ошибку, но также и позволить исправить ее таким странным / неуклюжим методом. Проблема возникает с новыми и старыми входами, поэтому я не думаю, что входные файлы являются проблемой, так как они не изменились.
Да, и дополнительно, если я изменю количество пробелов между каждым столбцом в текстовом файле, местоположение ошибки будет смещено. Уменьшение его до 1 пробела приводит к возникновению ошибки в строке 120 или около того, в то время как увеличение количества пробелов (пробовал 7 вместо 5) толкнул ошибку до строки 124.
Я не эксперт по программированию (я всегда учился так, как мне нужно), так что помощь в выяснении этого будет очень признательна. Спасибо!
Кандидатское упрощение
не нашел источник проблемы, но рекомендовал это, чтобы упростить отладку. Это заботится об окончаниях строк ПК, чрезмерных манипуляциях с указателем файла, ненужном ограничении %7lf
и обеспечивает лучшую проверку ошибок.
FILE *infile_ptr = fopen("c:\\LumaGem\\orbit.txt", "rt"); // PC text file
char buf[1000];
while (fgets(buf, sizeof(buf), infile_ptr)) { // separate I/O from scanning
int count = sscanf(buf,"%lf%lf%lf%lf%lf%lf%lf%lf", &r, &s1, &s2, &e1, &e2, &e3, &d, &f);
if (count != 8) { // check for correct scan count
; //handle error;
}
}
if (ferror(infile_ptr)) {
; //handle error;
}
fclose(infile_ptr);
[Редактировать] OP опубликовал оригинальный текстовый файл.
Также добавьте эту строку в цикл, чтобы позаботиться о конечных строках, состоящих только из пробелов.
if (count <= 0) continue;
[Править] Заключение.
Использование fseek()
а также ftell()
, обычно используемый с бинарными файлами, здесь IMHO не нужен, это ошибка Window, читающая текстовый файл UNIX (\n
) открывается в Windows в двоичном режиме "r"
и используя fscanf()
который работает лучше всего, чтение текстовых файлов открыть "rt"
, Ничего не найдено, чтобы указать на линию 123 или ее соседей в качестве проблемной области.
Беда с твоим fscanf()
директивы.
Рекомендую %lf
вместо %7lf
,
Ваш fprintf()
с "%7.3f"
печатает числа с плавающей запятой, используя в наименее 7 символов для заполнения ' '
по мере необходимости.
Ваше последующее использование "%7lf"
в fscanf()
говорит сканировать на самый 7 символов. Поэтому, когда вы печатаете ff / scanf 999.999, все в порядке, но с большими числами, такими как 1000.007, ваше сканирование принимает значение «1000.00» и оставляет «7» для следующего "%7lf"
,
int main(void) {
char buf[1000];
double f1, f2;
int r;
sprintf(buf, "%7.3f %7.3f", 1.23, 4.56);
r = sscanf(buf, "%7lf %7lf", &f1, &f2);
printf("'%s'\n%d %g %g\n", buf, r, f1, f2);
sprintf(buf, "%7.3f %7.3f", 999.999, 4.56);
r = sscanf(buf, "%7lf %7lf", &f1, &f2);
printf("'%s'\n%d %.10g %.10g\n", buf, r, f1, f2);
sprintf(buf, "%7.3f %7.3f", 1000.007, 4.56);
r = sscanf(buf, "%7lf %7lf", &f1, &f2);
printf("'%s'\n%d %.10g %.10g\n", buf, r, f1, f2);
return 0;
}
Output:
' 1.230 4.560'
2 1.23 4.56
'999.999 4.560'
2 999.999 4.56
'1000.007 4.560'
2 1000 7
Кстати: для fscanf()
, "%lf%lf%lf ..."
все в порядке. Добавление пробелов между %lf
не меняет функциональность.