3

I am having trouble with this code, and I'm not sure what I'm doing wrong

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

typedef struct flight_struct{
    char flightNum[7];
    char originAirport[5];
    char destAirport [5];
    int timestamp;
    struct flight_struct *next;
} flightRec;

int main(){
struct flight_struct *head; // unchanging first node.
struct flight_struct *tail; //the conductor.
struct flight_struct *p; // first new struct
FILE* binFile = fopen("acars.bin","r");
FILE* DataOut;

    p =(struct flight_struct*) malloc(sizeof(*p) + 1); //malloc the first struct\

    fread(p,sizeof(*p),1,binFile);  //read the file into it.

    head = p; //make head point to that struct
    tail = p; //make tail point to that struct

//  fclose(binFile);

    while (feof(binFile) == 0){
    flight_struct *temp = (struct flight_struct*) malloc(1*sizeof(*temp) + 1); //malloc a new struct
    fread(temp,sizeof(*temp),1,binFile); //read the next struct from acars.bin into the structure you malloc'ed
    temp -> next = NULL; // add that struct to your linked list using the next memeber of the struct
    tail -> next = temp; // set tail to point to the element you just added
    tail = tail -> next;
    } //while not eof on acars file

    tail = head;

    while(tail -> next != 0 ){  
        int t;
        t = tail -> timestamp;
        time_t tim = t;
        printf("%s, %s, %s, %s\n\n",tail -> flightNum,tail -> originAirport,tail -> destAirport,asctime(gmtime(&tim)));
        tail = tail -> next;
    } //starting at head traverse the list printing the leemnts of each strucure
}

Now, what I am getting as a result is What i'm getting

What I should be getting is What I should be getting

Honestly I don't know what I'm doing wrong, and help would be nice. That being said, I can't use arrays so a linked list is the only way to do it.

Damien
  • 1,161
  • 2
  • 19
  • 31
  • 2
    Your flight_struct struct is probably being padded out in memory by the compiler in a way that doesn't match the format of your file. You need to read each field one at a time and copy it into the struct instead of reading the whole struct at once. – samgak Apr 30 '15 at 02:41
  • Do you have any idea how to do that from a .txt or .bin file? – Bryan Justo Apr 30 '15 at 02:43
  • I agree with @samgak - never read and write directly into a struct because your code and data-files won't be portable between machines. – Dai Apr 30 '15 at 02:44
  • Any hints on how to start doing that? I have been trying to work with this code for about two days and I am completely out of ideas... – Bryan Justo Apr 30 '15 at 02:46
  • `int timestamp;` in no way matches `Fri Jan 10 23:33:00 2014` – smac89 Apr 30 '15 at 03:03
  • @Smac89 Well I can promise you i didn't write that myself, and the .bin doesn't have any readable dates in there. timestamp is getting the PIOSX time and changing it using the time_t function in the time.h header – Bryan Justo Apr 30 '15 at 03:05
  • This basic code is very similar to that in [Linked list print error using time functions](http://stackoverflow.com/questions/29933773/). It has a few of the problems fixed; it is still suffering from [`while (!feof(file))` is always wrong](http://stackoverflow.com/questions/5431941) and consequentially mishandles I/O errors by ignoring the return value from `fread()`. I've not scrutinized what else is an issue. (The questions are nominally posed by different people.) – Jonathan Leffler Apr 30 '15 at 03:12
  • You've not shown how you create the data file, or what the data file looks like. There are all sorts of ways it could be wrong, but relatively few in which it is right. Have you done a hex dump of the data file? Have you checked the size of the structure against the size of the entries in your program? Have you checked for endian-ness problems with the `int` used for storing time values — which will more or less work OK in 32-bit systems but likely won't work OK in 64-bit systems. – Jonathan Leffler Apr 30 '15 at 03:16
  • 2
    Having `struct flight_struct *next;` in the structure you read from forces that amount of data to be read from the file into the pointer (which you then overwrite). I seriously doubt that "next" is part of the information in the datafile, so by reading it that way you are messing up the alignment of how you read the file, not to mention the issue with internal structure padding doing the same thing. Use separate freads to read each element, checking the return value (to make sure 1 thing was read each time) and the !feof() does not work the way you think it does. – JohnH Apr 30 '15 at 03:37

3 Answers3

2

You shouldn't have a pointers in your file.

Because order of elements in file automagically sets the order in your list (obviously). I doubt that file contains a pointers to sctructure and it's okay (pointers can be different in different architectures, ta-da).

What to do?

Given data structure:

struct flight_struct {
  char flightNum[7];
  char originAirport[5];
  char destAirport [5];
  int timestamp;
}

Implement the list struct:

struct list {
  flight_struct* data;
  list* next;
  list* prev; //if you want bi-directional list
}

And load from file just the data structure into list struct.

Writing pointers into binary file is wrong and may cause a lot of problems. Did you create file with objects by yourself or it is from other source?

Dawid Pura
  • 991
  • 9
  • 32
1

Here is a solution that seems to work:

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

typedef struct flight_struct{
    char flightNum[7],originAirport[5], destAirport [5];
    size_t timestamp;
    struct flight_struct *next;
} flightRec;


int readFlight(FILE* file, flightRec *fr);

int main() {
    FILE *f = fopen("input.txt", "r");
    if (f != NULL) {
        while (feof(f) == 0) {
            flightRec fr;
            if (readFlight(f, &fr) == 0) {

                printf("%s, %s, %s, %s\n", fr.flightNum, fr.originAirport,
                        fr.destAirport, ctime((time_t*)(&fr.timestamp)));
            }
            else {
                fprintf(stderr, "Couldn't read the file information");
                break;
            }
        }
    }

    fclose(f);
    return 0;
}

int readFlight(FILE* file, flightRec *fr) {
    struct tm tstr;
    char *buffer = NULL, time[40];
    size_t len = 0;
    getline(&buffer, &len, file);

    int v = sscanf(buffer, "%6s%*[^ ]%4s%*[^ ]%4s%*[^a-zA-Z]%[^\n\r]", fr->flightNum, fr->originAirport,
                                                fr->destAirport, time);
    free(buffer);
    if (v == 4) {
        strptime(time, "%a %b %d %T %Y", &tstr);
        tstr.tm_isdst = -1;
        fr->timestamp = (size_t)mktime(&tstr);
        return 0;
    }
    return -1;
}

Input file:

XE4608, KIAH, KRSW, Mon Oct 21 15:25:00 2013
XE4232, KSDH, KASW, Sat Mar 29 16:38:00 2014
XE3453, MASH, KRSW, Wed Jan 01 19:10:00 2014
ZF4608, SAAH, KRSW, Tue Mar 25 18:49:00 2014

Output:

XE4608, KIAH, KRSW, Mon Oct 21 15:25:00 2013

XE4232, KSDH, KASW, Sat Mar 29 16:38:00 2014

XE3453, MASH, KRSW, Wed Jan  1 19:10:00 2014

ZF4608, SAAH, KRSW, Tue Mar 25 18:49:00 2014

Made a change to the struct so that timestamp is size_t type rather than int.

smac89
  • 39,374
  • 15
  • 132
  • 179
0

Are you sure that the file contains the full struct? Even with the space for the pointers?

And isn't your linking off? Shouldn't this be:

temp-> next = null;
if ( tail == null )
{
    head = temp;
    tail = temp;
}
else
{ 
   tail-> next = temp;
   tail = temp;
}
Mario The Spoon
  • 4,799
  • 1
  • 24
  • 36