Чтение различных данных из текстового файла, разделенного точкой с запятой в C

Как читать разные записи данных, разделенные точкой с запятой, в массив в C?

из текстового файла: текст 1; 12.25; Текст Два; 5; Текст Три; 1,253

fopen ...
for(i = 0; i < nrRecords; i++) {
fscanf(myFile, " %[^;];", myRecords[i].firstText);  /* Ok first text*/
fscanf(myFile, "%lf", &myRecords[i].myDouble1);     /* But goes wrong with first double */
fscanf(myFile, " %[^;];", myRecords[i].secondText); 
fscanf(myFile, "%d", &myRecords[i].myInt1);     
fscanf(myFile, " %[^;];", myRecords[i].thirdText); 
fscanf(myFile, "%lf",&myRecords[i].myDouble2);    
}
fclose...

person Chris_45    schedule 01.12.2009    source источник
comment
Если вы прочитаете каждое поле как строку %[^;];, получите ли вы правильный текст (например, 12.25 во втором поле)?   -  person Andreas Brinck    schedule 01.12.2009
comment
Нет, проблема в том, что я читаю его в structarray с фиксированными типами.   -  person Chris_45    schedule 01.12.2009
comment
Я попробовал, и это сработало правильно. Можете ли вы показать определение структуры myRecord?   -  person bhups    schedule 01.12.2009
comment
struct myRecord{ char text1[20]; двойная цена; символ текст2[30]; внутренний номер; символ текст3[30]; двойная цена2; };   -  person Chris_45    schedule 01.12.2009
comment
Как это может пойти не так? Почему вы не проверяете возвращаемое значение fscanf?   -  person    schedule 22.02.2010


Ответы (3)


Обычный совет — читать целые строки, а затем анализировать их с помощью sscanf, strtok или чего-то еще. Слишком легко потерять свое место во входном файле, если вы сканируете прямо из файла. (т. е. в первый раз, когда что-то не совпадает, вам нужен способ пропустить это, если вы не хотите просто прервать там.)

person Peter Cordes    schedule 10.12.2009
comment
Как легко потерять свое место? Нетрудно пропустить оставшуюся часть строки, и это все, что вы делаете в противном случае, если вы отбрасываете текущую строку при ошибке: void ignoreline(FILE* f) { char c; for (;;) switch (fgetc(f)) { case '\n': case EOF: return; default:; } . - person ; 22.02.2010

Я бы использовал fgets, чтобы прочитать строку из файла, strtok, чтобы разбить ее на точку с запятой, strcpy, чтобы скопировать строки, strtod, чтобы преобразовать в double и strtol, чтобы преобразовать в long (а затем преобразовать в целое число).

Или прочитайте строку и используйте конечный автомат для обхода каждого символа и выполнения правильной операции. Например, вы будете копировать каждый символ в firstText, пока не дойдете до точки с запятой, а затем использовать strtod, чтобы съесть двойную, пропустить точку с запятой, скопировать байты в secondText и т. д.

Или используйте одну строку формата scanf, чтобы разбить строку на все поля.

fscanf(myFile, " %[^;];%lf;%[^;];%d;%[^;];%lf", 
    myRecords[i].firstText,
    &myRecords[i].myDouble1,
    myRecords[i].secondText,
    &myRecords[i].myInt1,
    myRecords[i].thirdText,
    &myRecords[i].myDouble2);

И, как упоминалось другими, проверьте возвращаемое значение fscanf.

Я предпочитаю читать строку за раз, чтобы одна плохая строка не испортила все последующие конверсии.

person tomlogic    schedule 13.03.2010

Один из способов — использовать strtok. А затем введите результат в int или float.

person bhups    schedule 01.12.2009