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

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

  1. 声明时间结构的飞行时间,飞行时间是POSIX格式。
  2. Localtime将POSIX时间转换为人类可读的时间。
  3. 第四个说明符使用asctime打印转换时间,该时间以Www Mmm dd hh:mm:ss yyyy格式打印。

错误是tb!= NULL并显示指定asctime的其他信息。

我做了什么来排除故障:

  1. 检查时间标题
  2. 检查指针和地址
  3. 关闭了弃用
  4. 检查格式说明符

任何帮助表示赞赏。

#include  #include  #include  #include  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; } 

当我使用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 $ 

‘unused variables’和’no previous prototype’错误(除了我使用-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 ,如果你需要使用time_t并且它与int大小不同并且二进制格式在外部是固定的,那么你可能需要进行成员方式的复制。

你应该知道为什么while (!feof(file))总是错的 。


半固定代码: timecrash.c

这段代码或多或少对我有用。

 #include  #include  #include  #include  #include  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是在8字节边界上对齐的64位类型(在它之前为7个空填充字节),并且以little-endian格式化(如在Intel上)。

 $ 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在中断(或以其他方式发送信号)之前不会终止。