使用时间函数的链接列表打印错误

时间:2015-04-29 03:25:38

标签: c visual-studio-2013 time printing linked-list

打印时间戳时程序崩溃。我相信错误位于函数void flightRec_PrflightRecData(flightRecRead * thisFlight)中,它旨在做三件事:

  1. 声明时间结构飞行时间,飞行时间为POSIX格式。
  2. Localtime将POSIX时间转换为人类可读的时间。
  3. 第四个说明符使用asctime打印转换时间,该时间以Www Mmm dd hh:mm:ss yyyy格式打印。
  4. 错误是tb!= NULL并显示指定asctime的其他信息。

    我做了什么来解决问题:

    1. 检查时间标题
    2. 检查指针和地址
    3. 关闭弃用
    4. 检查格式说明符
    5. 感谢任何帮助。

      #include <stdio.h>
      #include <stdlib.h>
      #include <string.h>
      #include <time.h>
      
      
      typedef struct flightRec_struct { // declare a struct to match the format of the binary data
          char FlightNum[7];
          char OriginAirportCode[5];
          char DestAirportCode[5];
          int  timestamp;
      } flightRec;
      
      typedef struct flightRecRead_struct { // declare a struct to match the format of your linked list
          char FlightNum[7];
          char OriginAirportCode[5];
          char DestAirportCode[5];
          int  timestamp;
          struct flightRec* nextFlight_ptr;
      } flightRecRead;
      
      
      
      // Print dataVal
      void flightRec_PrflightRecData(flightRecRead* thisFlight) {
          struct tm *flightTime;
          flightTime = localtime(&thisFlight->timestamp);
          printf("%s \t %s \t %s \t %s\n", thisFlight->FlightNum, thisFlight->OriginAirportCode,
              thisFlight->DestAirportCode, asctime(flightTime));
          return;
      }
      
      // Grab location pointed by nextFlight_ptr
      flightRecRead* flightRec_GetNext(flightRecRead* thisFlight) {
          return thisFlight->nextFlight_ptr;
      }
      
      int main(void) {
          flightRec firstStruct;
          flightRecRead* headObj = NULL;
          flightRecRead* currObj = NULL;
          flightRecRead* tailObj = NULL;
          struct tm *flightTime;
          int i = 0;                               //loop index
      
      
          FILE* inFile = NULL;
          inFile = fopen("acars.bin", "rb");
          if (inFile == NULL) {
              printf("Could not open file acars.bin.\n");
              return -1;
          }
      
          if (!feof(inFile)) {
              fread(&firstStruct, sizeof(flightRec), 1, inFile); // 2. read the file into that struct
      
              headObj = (flightRecRead*)malloc(sizeof(flightRecRead)); // 3. make head point to that struct
              strcpy(headObj->FlightNum, firstStruct.FlightNum);
              strcpy(headObj->OriginAirportCode, firstStruct.OriginAirportCode);
              strcpy(headObj->DestAirportCode, firstStruct.DestAirportCode);
              headObj->timestamp = firstStruct.timestamp;
      
              tailObj = (flightRecRead*)malloc(sizeof(flightRecRead));  // 4. make tail point to that struct
              strcpy(tailObj->FlightNum, firstStruct.FlightNum);
              strcpy(tailObj->OriginAirportCode, firstStruct.OriginAirportCode);
              strcpy(tailObj->DestAirportCode, firstStruct.DestAirportCode);
              tailObj->timestamp = firstStruct.timestamp;
              headObj->nextFlight_ptr = tailObj;
              tailObj->nextFlight_ptr = NULL;
          }
      
          while (!feof(inFile)) {                       // 5. while not end-of-file on the acars file:
              fread(&firstStruct, sizeof(flightRec), 1, inFile); // 6. malloc a new struct
              currObj = (flightRecRead*)malloc(sizeof(flightRecRead));
              strcpy(currObj->FlightNum, firstStruct.FlightNum);
              strcpy(currObj->OriginAirportCode, firstStruct.OriginAirportCode);
              strcpy(currObj->DestAirportCode, firstStruct.DestAirportCode);
              currObj->timestamp = firstStruct.timestamp;
              currObj->nextFlight_ptr = NULL;
      
              tailObj->nextFlight_ptr = currObj;
              tailObj = currObj;
          }
      
      
          currObj = headObj;                           // Print the list
          printf("FlightNum \t OriginAirportCode \t DestAirportCode \t Time \t \n");
          while (currObj != NULL) {
              flightRec_PrflightRecData(currObj);
              currObj = flightRec_GetNext(currObj);
          }
      
          system("pause"); //return 0;
      }
      

1 个答案:

答案 0 :(得分:1)

当我使用GCC 5.1.0在64位Mac上编译代码时,它会给我一些错误。但是,其中一些是我使用的非常严格的编译选项的结果:

$ gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
>     -Wold-style-definition -Werror timecrash.c -o timecrash
timecrash.c:25:6: error: no previous prototype for ‘flightRec_PrflightRecData’ [-Werror=missing-prototypes]
 void flightRec_PrflightRecData(flightRecRead* thisFlight) {
      ^
timecrash.c: In function ‘flightRec_PrflightRecData’:
timecrash.c:27:28: error: passing argument 1 of ‘localtime’ from incompatible pointer type [-Werror=incompatible-pointer-types]
     flightTime = localtime(&thisFlight->timestamp);
                            ^
In file included from timecrash.c:4:0:
/usr/include/time.h:112:12: note: expected ‘const time_t * {aka const long int *}’ but argument is of type ‘int *’
 struct tm *localtime(const time_t *);
            ^
timecrash.c: At top level:
timecrash.c:34:16: error: no previous prototype for ‘flightRec_GetNext’ [-Werror=missing-prototypes]
 flightRecRead* flightRec_GetNext(flightRecRead* thisFlight) {
                ^
timecrash.c: In function ‘flightRec_GetNext’:
timecrash.c:35:12: error: return from incompatible pointer type [-Werror=incompatible-pointer-types]
     return thisFlight->nextFlight_ptr;
            ^
timecrash.c: In function ‘main’:
timecrash.c:68:33: error: assignment from incompatible pointer type [-Werror=incompatible-pointer-types]
         headObj->nextFlight_ptr = tailObj;
                                 ^
timecrash.c:81:33: error: assignment from incompatible pointer type [-Werror=incompatible-pointer-types]
         tailObj->nextFlight_ptr = currObj;
                                 ^
timecrash.c:44:9: error: unused variable ‘i’ [-Werror=unused-variable]
     int i = 0;                               //loop index
         ^
timecrash.c:43:16: error: unused variable ‘flightTime’ [-Werror=unused-variable]
     struct tm *flightTime;
                ^
cc1: all warnings being treated as errors
$

'未使用的变量'和'没有以前的原型'错误(除了我使用-Werror强制所有警告都被视为错误之外的警告)。

但滥用int作为time_t的代理可能也是一个问题。如果您编译32位平台,它可能不是一个问题。

其他“不兼容的指针类型”警告也令人担忧。实际上,您的第二个结构定义是不正确的。你有:

typedef struct flightRec_struct {
    char FlightNum[7];
    char OriginAirportCode[5];
    char DestAirportCode[5];
    int  timestamp;
} flightRec;

typedef struct flightRecRead_struct {
    char FlightNum[7];
    char OriginAirportCode[5];
    char DestAirportCode[5];
    int  timestamp;
    struct flightRec* nextFlight_ptr;
} flightRecRead;

struct flightRec *是指向不完整类型的指针。它不是struct flightRec_struct也不是flightRec(也不是struct flightRecRead_struct也不是flightRecRead)。实际上,您需要它是struct flightRecRead_struct *或者您需要预先声明类型并使用flightRecRead *

typedef struct flightRecRead_struct flightRecRead;
struct flightRecRead_struct {
    char FlightNum[7];
    char OriginAirportCode[5];
    char DestAirportCode[5];
    int  timestamp;
    flightRecRead *nextFlight_ptr;
};

您可以使用以下方法简化代码的分配部分:

struct flightRecRead_struct
{
    flightRec      flight;
    flightRecRead *nextFlight_ptr;
};

然后,您可以在一行中分配整个flightRec结构,而不必写出多个strcpy()操作等。

对此,如果您需要使用time_t且与int的大小不同,并且二进制格式在外部修复,那么您可能需要在之后进行成员方式复制所有

您应该了解原因while (!feof(file)) is always wrong

半固定代码:timecrash.c

此代码或多或少对我有用。

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

typedef struct flightRec_struct
{
    char FlightNum[7];
    char OriginAirportCode[5];
    char DestAirportCode[5];
    time_t timestamp;
} flightRec;

typedef struct flightRecRead_struct flightRecRead;
struct flightRecRead_struct
{
    char FlightNum[7];
    char OriginAirportCode[5];
    char DestAirportCode[5];
    time_t timestamp;
    flightRecRead *nextFlight_ptr;
};

static
void flightRec_PrflightRecData(flightRecRead *thisFlight)
{
    struct tm *flightTime = localtime(&thisFlight->timestamp);
    printf("timestamp = 0x%.8lX\n", (long)thisFlight->timestamp);
    assert(flightTime != 0);
    printf("%s \t %s \t %s \t %s\n", thisFlight->FlightNum, thisFlight->OriginAirportCode,
           thisFlight->DestAirportCode, asctime(flightTime));
}

static
flightRecRead *flightRec_GetNext(flightRecRead *thisFlight)
{
    return thisFlight->nextFlight_ptr;
}

int main(void)
{
    flightRec firstStruct;
    flightRecRead *headObj = NULL;
    flightRecRead *currObj = NULL;
    flightRecRead *tailObj = NULL;
    const char filename[] = "acars.bin";
    int recnum = 0;
    FILE *inFile = fopen(filename, "rb");

    if (inFile == NULL)
    {
        fprintf(stderr, "Could not open file %s.\n", filename);
        return -1;
    }

    if (fread(&firstStruct, sizeof(flightRec), 1, inFile) == 1)
    {
        printf("Record %d\n", ++recnum);
        headObj = (flightRecRead *)malloc(sizeof(flightRecRead));
        strcpy(headObj->FlightNum, firstStruct.FlightNum);
        strcpy(headObj->OriginAirportCode, firstStruct.OriginAirportCode);
        strcpy(headObj->DestAirportCode, firstStruct.DestAirportCode);
        headObj->timestamp = firstStruct.timestamp;
        flightRec_PrflightRecData(headObj);

        tailObj = (flightRecRead *)malloc(sizeof(flightRecRead));
        strcpy(tailObj->FlightNum, firstStruct.FlightNum);
        strcpy(tailObj->OriginAirportCode, firstStruct.OriginAirportCode);
        strcpy(tailObj->DestAirportCode, firstStruct.DestAirportCode);
        tailObj->timestamp = firstStruct.timestamp;
        flightRec_PrflightRecData(tailObj);

        headObj->nextFlight_ptr = tailObj;
        tailObj->nextFlight_ptr = NULL;
    }

    while (fread(&firstStruct, sizeof(flightRec), 1, inFile) == 1)
    {
        printf("Record %d\n", ++recnum);
        currObj = (flightRecRead *)malloc(sizeof(flightRecRead));
        strcpy(currObj->FlightNum, firstStruct.FlightNum);
        strcpy(currObj->OriginAirportCode, firstStruct.OriginAirportCode);
        strcpy(currObj->DestAirportCode, firstStruct.DestAirportCode);
        currObj->timestamp = firstStruct.timestamp;
        currObj->nextFlight_ptr = NULL;
        flightRec_PrflightRecData(currObj);

        tailObj->nextFlight_ptr = currObj;
        tailObj = currObj;
    }
    printf("Finished reading\n");

    currObj = headObj;
    printf("FlightNum \t OriginAirportCode \t DestAirportCode \t Time \t \n");
    recnum = 0;
    while (currObj != NULL)
    {
        printf("Record %d\n", ++recnum);
        flightRec_PrflightRecData(currObj);
        currObj = flightRec_GetNext(currObj);
    }

    fclose(inFile);

    system("pause");
}

样品运行

数据生成假设time_t是一个64位类型,在8字节边界上对齐(在它之前有7个空填充字节),并且以小端格式化(如在英特尔上)。

$ printf "BA7231\0LHR\0\0LGW\0\0\0\0\0\0\0\0\0\xA2\x93\x84\x75\0\0\0\0" > acars.bin
$ printf "UA9240\0LAX\0\0AMS\0\0\0\0\0\0\0\0\0\x72\x93\x84\x75\0\0\0\0" >> acars.bin
$ odx acars.bin
0x0000: 42 41 37 32 33 31 00 4C 48 52 00 00 4C 47 57 00   BA7231.LHR..LGW.
0x0010: 00 00 00 00 00 00 00 00 A2 93 84 75 00 00 00 00   ...........u....
0x0020: 55 41 39 32 34 30 00 4C 41 58 00 00 41 4D 53 00   UA9240.LAX..AMS.
0x0030: 00 00 00 00 00 00 00 00 72 93 84 75 00 00 00 00   ........r..u....
0x0040:
$ ./timecrash
Record 1
timestamp = 0x758493A2
BA7231   LHR     LGW     Wed Jun 23 10:00:18 2032

timestamp = 0x758493A2
BA7231   LHR     LGW     Wed Jun 23 10:00:18 2032

Record 2
timestamp = 0x75849372
UA9240   LAX     AMS     Wed Jun 23 09:59:30 2032

Finished reading
FlightNum    OriginAirportCode   DestAirportCode     Time    
Record 1
timestamp = 0x758493A2
BA7231   LHR     LGW     Wed Jun 23 10:00:18 2032

Record 2
timestamp = 0x758493A2
BA7231   LHR     LGW     Wed Jun 23 10:00:18 2032

Record 3
timestamp = 0x75849372
UA9240   LAX     AMS     Wed Jun 23 09:59:30 2032

^C
$

中断是必要的,因为Mac OS X上的pause在中断(或以其他方式发送信号)之前不会终止。