#c #fgets
#c #fgets
Вопрос:
Я должен прочитать из файла .txt, который выглядит следующим образом:
Нью-Йорк, 4:20,3:03 Канзас-Сити, 12:03,3:00 Северная бухта, 16:00,0:20 Завершение работы, 10:00,4:02 Тандер Бэй, 0:32,0:31
Я пытаюсь разделить каждый элемент на его собственный массив — это конечная цель, чтобы я мог использовать его для чего-то другого.
Мой цикл while правильно считывает файл, но сохраняет только последнюю строку файла в массиве, и я не могу понять причину этого. Также считываемый файл может состоять из любого количества строк. Я уверен, что он читает каждую строку, поскольку он печатает каждую строку, которую он отлично читает. Поэтому я считаю, что проблема заключается в сохранении того, что он читает.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#pragma warning(disable: 4996)
// a function to remove the trailing carriage return
void clearTrailingCarraigeReturn(char *buffer);
/* == FUNCTION PROTOTYPES == */
/* == CONSTANTS == */
#define RECORD_SIZE 256
#define NUM_RECORDS 5
#define CHUNK_SIZE 1024
#define STRING_SIZE 80
// MAIN
int main(int argc, char *argv[]) {
FILE *fp;
char flightInfo[RECORD_SIZE] = { 0 };
char cityName[20] = {};
char flightHour[20] = {};
char flightMin[20] = {};
char layoverHour[20] = {};
char layoverMin[20] = {};
int i = 0;
struct flightInfo {
char flightName[20];
double flightTime;
double layoverTime;
};
fp = fopen(argv[1], "r");
// first - we'll check the command-line arguments to ensure that the user specified
// a single argument - which we will assume is the name of a file
if (argc != 2) {
printf("Sorry - you need to specify the name of a file on the command line.n");
return -1;
}
if (fp == NULL) {
printf("Can't open the TEXT file for readingn");
return -4;
}
// get each of the lines from the file
while (fgets(flightInfo, sizeof flightInfo, fp) > 0) {
clearTrailingCarraigeReturn(flightInfo);
// display the line we got from the file
printf(" >>> read record [%s]n", flightInfo);
}
// we exited the reading loop - was it because we read the EOF?
if (feof(fp)) {
printf(" [DONE reading the file ... we've reached the EOF]n");
} else {
// we exited the loop because of an error
if (ferror(fp)) {
// there's an error
printf("Error reading a record from the filen");
if (fclose(fp) != 0) {
// we can't even close the file
printf("Can't close the TEXT file we opened for readingn");
}
return -5;
}
}
}
// This function locates any carriage return that exists in a record
// and removes it ...
void clearTrailingCarraigeReturn(char *buffer) {
char *whereCR = strchr(buffer, 'n');
if (whereCR != NULL) {
*whereCR = '';
}
}
Ответ №1:
В вашем коде множество проблем:
- вы должны проверить, присутствует ли аргумент командной строки перед попыткой открыть файл.
-
тест для вашего цикла чтения неверен:
fgets()
возвращает указатель на целевой массив orNULL
, поэтому вам следует использовать не> 0
, а это вместо:while (fgets(flightInfo, sizeof flightInfo, fp) != 0)
-
символ
'n'
называется новой строкой, а не возвратом каретки. На устаревших платформах,n
преобразуется в 2 байта в текстовых файлах0D
0A
, т.е.: возврат каретки и перевод строки. -
цикл считывает содержимое файла, но не анализирует содержимое строки и не сохраняет его в переменные, которые вы определили для этого. Вы должны проанализировать строку, преобразовать значения и сохранить информацию в следующей записи в
flighInfo
структурном массиве:if (sscanf(flightInfo, "[^,],%2[0-9]:%2[0-9],%2[0-9]:%2[0-9]", cityName, flightHour, flightMin, layoverHour, layoverMin) == 5) { /* convert the times into `double` values and store the info */ } else { /* report the error, exit */ }
-
вы используете одно и то же имя для
struct flightInfo
тега иchar
массива. Это сбивает с толку и чревато ошибками. Вам следует переименоватьchar
массивline
илиbuf
. -
вы должны закрыть файл во всех случаях.
Ответ №2:
Вы не сохраняете результаты сканирования. Эти строки:
while (fgets(flightInfo, sizeof flightInfo, fp) > 0)
{
clearTrailingCarraigeReturn(flightInfo);
// display the line we got from the file
printf(" >>> read record [%s]n", flightInfo);
}
Считывает следующую строку в flightInfo (которая является массивом char
), и когда появляется следующая строка, ее перечитывают в начало flightInfo заново. Самая последняя прочитанная строка будет сохранена в flightInfo.
Вам также нужно сохранить эту строку, если вы хотите сохранить ее. НАПРИМЕР, вы могли бы сделать что-то вроде:
char multiple_flight_info[100][1024];
int i = 0;
while (fgets(multiple_flight_info[i], 1024, fp) > 0)
{
clearTrailingCarraigeReturn(flightInfo[i]);
// display the line we got from the file
printf(" >>> read record [%s]n", flightInfo);
i ;
if (i > 100) { exit(1); } /* do better error exiting here */
}
По сути, это создает двойной массив. Первый индекс — это номер считываемой строки, а второй индекс — это позиция символа в прочитанной строке.
Для обеспечения «безопасности» необходимо сделать гораздо больше, а не читать отдельные строки, потому что одна из них слишком длинная, и т.д. Но это может помочь вам начать.
Комментарии:
1.
while (fgets(multiple_flight_info[i], 1024, fp) > 0)
должно бытьwhile (fgets(multiple_flight_info[i], 1024, fp) != NULL)