在C语言中,如何将文本文件的不同行保存到不同的变量

时间:2018-11-20 22:58:56

标签: c file file-io

如何将文本文件中的不同行保存到不同数据类型的不同变量中;所有这些变量组成一个结构(在我的示例中为带有以下内容的Flight结构)。

struct Flight
{
     int flightNum;
     char desination[30];
     char departDay[15];
};

我想通过文本文件添加的信息示例。

111
NYC
Monday

我显然想将单词NYC和Monday保存到一个char数组中,但是我想将111保存到一个整数变量中

到目前为止我有

while (fscanf(flightInfo, "%s", tempName) != EOF)
{
     fscanf(flightInfo, "%d\n", &tempNum);
     flight.flightNumber = tempNum;
     fscanf(flightInfo, "%s\n", tempName);
     strcpy(flight.desination, tempName);
     fscanf(flightInfo, "%s\n", tempName)
     strcpy(flight.departDay, tempName);
}

假设flightInfo是指向文件名的指针,tempNum是整数,tempName是char数组

2 个答案:

答案 0 :(得分:2)

听起来你在正确的轨道上。

那这样的事情呢?

select
    ot.id, nz(t.cnt, 0) as positions
from
    tblopeningtypes ot
    left join
    (
        select o.fk_openingtypeid, count(o.position) as cnt
        from tblopening o inner join tblopeningcity oc on o.city = oc.openingcityid
        where
            o.position = "Flex Officer" and
            o.closed = no and 
            oc.openingcity in ("Livermore", "Pleasanton")
        group by o.fk_openingtypeid
    ) t
    on ot.id = t.fk_openingtypeid

附录: 根据Chux的建议,我通过将scanf最大字符串长度设置为29(小于char [30]缓冲区大小1)来修改代码,以减轻潜在的缓冲区溢出。

这是更详细的说明:

SonarSource: "scanf()" and "fscanf()" format strings should specify a field width for the "%s" string placeholder

答案 1 :(得分:0)

您必须回答的第一个问题是:文件对于人们或在其他平台上可读的重要性如何?

如果不是那么重要,那么我建议使用fwrite()fread()进行序列化。对于每个记录,这更容易编码,并且-只要您的结构都具有相同的大小-允许O(1)访问文件中的任何记录。

如果您愿意将它们存储为单独的行,则从文件中读取行的最佳方法是使用fgets()

伪代码如下:

typedef struct flight {
  int flightNum;
  char desination[30];
  char departDay[15];
} flight;

typedef struct flightSet {
  flight *flights;
  size_t n; /* number of flights */
  size_t nAlloc; /* number of flights you have space for */
} flightSet;

#define FLIGHTSET_INIT_SIZE 16
#define MAX_LINE_LENGTH 128
#define FILENAME "file.txt"

// Create a new flightSet, calling it F
// Allocate FLIGHTSET_INIT_ALLOC number of flight structures for F->flights
// Set F->n to 0
// Set F->nAlloc to FLIGHTSET_INIT_ALLOC

/* Set up other variables */
size_t i = 0;                       // iterator */
char buffer[MAX_LINE_LENGTH];   // for reading with fgets() */
flights *temp;                  // for realloc()ing when we have more flights to read
                            // after reaching nAlloc flights
char *endptr;                   // for using strtol() to get a number from buffer
FILE *fp;                       // for reading from the file

// Open FILENAME with fp for reading

//MAIN LOOP
  // If i == F->nAlloc, use realloc() to double the allocation of F->flights
  // If successful, double F->nAlloc

  if (fgets(buffer, MAX_LINE_LENGTH, fp) == NULL) {
      // End of file
      // Use break to get out of the main loop
  }

  F->flights[i]->flightNum = (int)strtol(buffer, &endptr, 10);
  if (endptr == buffer) {
    // The first invalid character that can't be converted to a number is at the very beginning
    // of the buffer, so this is not a valid numerical character and your data file is corrupt
    // Print out an error message
    break; 
  }

  if (fgets(buffer, MAX_LINE_LENGTH, fp) == NULL) {
      // End of file when expecting new line; file format error
      // Use break to get out of the main loop
  } else {
     F->flights[i]->destination = strdup(buffer);  // If your system has strdup()
     // Check for memory allocation
  }

  if (fgets(buffer, MAX_LINE_LENGTH, fp) == NULL) {
      // End of file when expecting new line; file format error
      // Use break to get out of the main loop
  } else {
     F->flights[i]->departDay = strdup(buffer);  // If your system has strdup()
     // Check for memory allocation
  }

  // If you've gotten here so far without errors, great!
  //    Increment F->n to reflect the number of successful records we have in F.
  //    Increment i, the loop iterator

//Final cleanup.  Should include closing the file, and freeing any allocated
//memory that didn't end up in a valid record.