打印时间戳时程序崩溃。我相信错误位于函数void flightRec_PrflightRecData(flightRecRead * thisFlight)中,它旨在做三件事:
错误是tb!= NULL并显示指定asctime的其他信息。
我做了什么来解决问题:
感谢任何帮助。
#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;
}
答案 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
在中断(或以其他方式发送信号)之前不会终止。