【问题标题】:Reading a file line by line and it is only storing the last line in the file逐行读取文件,它只存储文件中的最后一行
【发布时间】:2019-04-05 05:57:14
【问题描述】:

我必须读取如下所示的 .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 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';
    }
}

【问题讨论】:

    标签: c fgets


    【解决方案1】:

    您的代码中存在多个问题:

    • 您应该在尝试打开文件之前测试命令行参数是否存在。
    • 您的阅读循环测试不正确:fgets() 返回指向目标数组或NULL 的指针,因此您不应使用&gt; 0,而是改为:

      while (fgets(flightInfo, sizeof flightInfo, fp) != 0)
      
    • 字符 '\n' 被称为 newline,而不是回车。在旧平台上,\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 数组重命名为linebuf

    • 在所有情况下都应该关闭文件。

    【讨论】:

      【解决方案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 */
      }
      

      本质上,这会创建一个双精度数组。第一个索引是正在读取的行号,第二个索引是读取的行中的字符位置。

      为了“安全”,还有很多工作要做,而不是因为一行太长而阅读部分行,等等。但这可能会让你开始。

      【讨论】:

      • while (fgets(multiple_flight_info[i], 1024, fp) &gt; 0) 应该是while (fgets(multiple_flight_info[i], 1024, fp) != NULL)
      猜你喜欢
      • 1970-01-01
      • 2020-12-28
      • 1970-01-01
      • 2013-03-07
      • 2013-01-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-27
      相关资源
      最近更新 更多