2016-01-14 56 views
2

该程序基本上创建了所有信息的航班列表(由来自ListaVoli.bin的fread()函数读取)。 该列表主要由节点组成,每个节点包含一个航班。从二进制文件中读取fread()的意外行为

#include <stdio.h> 
#include <stdlib.h> 

#define FILE_NAME "/Users/Matt/Downloads/ListaVoli.bin" 

struct flight { 
    int flightCode; 
    char destination[3]; 
    int scheduledDepHour; 
    int scheduledDepMinute; 
    int realDepHour; 
    int realDepMinute; 
    int passengers; 
}; 

struct node { 
    struct flight volo; 
    struct node *next; 
}; 

struct node *addToList(struct node *list, struct flight voloIn) { 
    struct node *newNode; 
    newNode = malloc(sizeof(struct node)); 

    if (newNode == NULL) { 
     printf("Error: malloc failed\n"); 
     exit(EXIT_FAILURE); 
    } 

    newNode -> volo = voloIn; 
    newNode -> next = list; 
    return newNode; 
} 

void printList(struct node *list) { 
    for (; list != NULL; list = list -> next) { 
     printf("Code:%d\nDestination:%s\nDeparture:%d-%d\nReal:%d-%d\nPassengers:%d\n\n\n", 
     list -> volo.flightCode, 
     list -> volo.destination, 
     list -> volo.scheduledDepHour, 
     list -> volo.scheduledDepMinute, 
     list -> volo.realDepHour, 
     list -> volo.realDepMinute, 
     list -> volo.passengers 
     ); 
    } 
} 

void decolla(struct node *list, int flightCode, int realDepHour, int realDepMinute) { 
    for (; list != NULL; list = list -> next) { 
     if (flightCode == (list -> volo.flightCode)) { /* 
      printf("Inserisci ora di partenza per il volo %d: ", flightCode); 
      scanf("%d", &(list -> volo.realDepHour)); 
      printf("Inserisci minuto di partenza: "); 
      scanf("%d", &(list -> volo.realDepMinute)); */ 
      list -> volo.realDepHour = realDepHour; 
      list -> volo.realDepMinute = realDepMinute; 
     } 
    } 
} 

void delay(struct node *list) { 
    for (; list != NULL; list = list -> next) { 
     if ((list -> volo.realDepHour) - (list -> volo.scheduledDepHour) == 0) { 
      if ((list -> volo.realDepMinute) - (list -> volo.scheduledDepMinute) > 5 && (list -> volo.realDepMinute) - (list -> volo.scheduledDepMinute) < 30) { 
      printf("Il volo %d ha più di 5 minuti di ritardo\n", list -> volo.flightCode); 
      continue; 
      } 
      if ((list -> volo.realDepMinute) - (list -> volo.scheduledDepMinute) > 30) { 
       printf("Il volo %d ha più di 30 minuti di ritardo\n", list -> volo.flightCode); 
       continue; 
      } 
     } else 
      printf("Il volo %d ha più di 30 minuti di ritardo\n", list -> volo.flightCode); 
    } 
} 

void passengersCount(struct node *list) { 
    for (; list != NULL; list = list -> next) { 
     if (list -> volo.passengers > 200) { 
      printf("Il volo %d ha più di 200 passeggeri\n", list -> volo.flightCode); 
      continue; 
     } 
    } 
} 

int main() { 
    FILE *fp; 
    struct node *first = NULL; 
    struct flight volo; 

    /* Apro il file e controllo che sia stato aperto correttamente */ 
    if ((fp = fopen(FILE_NAME, "rb")) == NULL) { 
     printf("Can't open %s\n", FILE_NAME); 
     exit(EXIT_FAILURE); 
    } 

    for (int i = 0; i < 4; i++) { 
     fread(&volo, sizeof(int), 7, fp); 
     first = addToList(first, volo); 
    } 

    decolla(first, 3497, 11, 30); 
    decolla(first, 2193, 11, 53); 
    decolla(first, 4284, 11, 07); 
    decolla(first, 5536, 12, 26); 
    printList(first); 
    delay(first); 
    passengersCount(first); 

    /* Controllo che il file sia chiuso correttamente */ 
    if (fclose(fp) == EOF) { 
     printf("File not closed properly!"); 
     exit(EXIT_FAILURE); 
    } 
    return 0; 
} 

代码编译正确,所以不用担心整个代码,只关注main()函数和两个结构体。 我有一个关于在main()函数FREAD()函数的两个问题:

  1. 为什么,如果我把的sizeof(int)的第二个参数,该flight.destination值正确分配?不应该char [3]变量比sizeof(int)大吗?
  2. 为什么,如果我把sizeof(struct flight)作为第二个参数(这将是最好的选择),我会得到分段错误:11?
+0

如果其余代码无关紧要,则不应该发布它。这就是[mcve]中第一部分的想法。 – Olaf

+0

您需要使用代码才能更好地理解程序。我刚刚说过,问题不是关于整个程序,而是main()函数中的fread()函数。 – Matt95

+0

没问题,但是从二进制文件读取很复杂,而且一个位可能会产生很大的问题。正如你所说,int是4个字节,char [3]是3个字节,那么fread()应该读取比它应该更多的字节?那为什么我得到正确的输出(一个3字符的字符串)? – Matt95

回答

2

三个字符的数组是三个字节。一个int通常(至少在现代32位和64位平台上)4个字节。它的工作原理是读取sizeof(int),因为编译器添加了填充

但“正确”(或至少是平常)的方式来读取结构将是你的情况下,使用sizeof(volo)读取整个结构为一个单元,即:

fread(&volo, sizeof(volo), 1, fp); 

如果你得到其他因为这个错误,你正在做点什么否则错了。

+0

其实更好(和corrcet)的方式是正确地(de)以元素为序列化它。 – Olaf

+0

为什么你写了1作为第三个参数而不是7我像?我的解决方案不正确? – Matt95

+0

似乎是因为7导致了段错误:11错误 – Matt95