Чтение файла построчно и сохранение только последней строки в файле - PullRequest
1 голос
/ 05 апреля 2019

Мне нужно прочитать из файла .txt, который выглядит следующим образом:

New York,4:20,3:03
Kansas City,12:03,3:00
North Bay,16:00,0:20
Kapuskasing,10:00,4:02
Thunder Bay,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 reading\n");
        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 file\n");
            if (fclose(fp) != 0) {
                // we can't even close the file
                printf("Can't close the TEXT file we opened for reading\n");
            }
            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 = '\0';
    }
}

Ответы [ 2 ]

1 голос
/ 05 апреля 2019

В вашем коде несколько проблем:

  • Вы должны проверить, присутствует ли аргумент командной строки , прежде чем попытается открыть файл.
  • тест для вашего цикла чтения неверен: fgets() возвращает указатель на массив назначения или NULL, поэтому вы не должны использовать > 0, но вместо этого:

    while (fgets(flightInfo, sizeof flightInfo, fp) != 0)
    
  • символ '\n' называется перевод строки , а не возврат каретки. На устаревших платформах \n преобразуется в 2 байта в текстовых файлах 0D 0A, то есть: возврат каретки и перевод строки .

  • цикл читает содержимое файла, но не анализирует содержимое строки и сохраняет ее в переменных, которые вы для этого определили. Вы должны проанализировать строку, преобразовать значения и сохранить информацию в следующую запись в массиве структуры flighInfo:

        if (sscanf(flightInfo, "%19[^,],%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.

  • Вы должны закрыть файл во всех случаях.

1 голос
/ 05 апреля 2019

Вы не сохраняете результаты сканирования.Эти строки:

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 */
}

По сути это создает двойной массив.Первый индекс - это номер строки, которая читается, а второй индекс - это позиция символа в прочитанной строке.

Необходимо сделать гораздо больше, чтобы быть "безопасным" и не читать частичные строки, потому чтоодин слишком длинный и т. д. Но это может помочь вам начать.

...