Thread: Data Structures Debugging

  1. #1
    Registered User
    Join Date
    Apr 2004
    Posts
    173

    Data Structures Debugging

    Ok, the basic task for this program is to read input from a file that has a specific layout within the file. I read these into variables and do an sorted insertion into a singly linked list based on the value of time. The problem here is that I have lots of:

    'invalid type argument of ->'
    'deferencing pointer to incomplete type'

    Most notably in the print_list function and sorted_insert function. Any pointers to why this is occuring would definitely be welcomed

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <assert.h>
    #include <time.h>
    #include <ctype.h>
    
    #define MAX_TIMESTR 1024
    
    /* Function Prototypes */
    char *timestamp(time_t);
    void sorted_insert(struct node** headRef, time_t, *char, int, double, int, int);
    
    /* Debug Function Prototypes - Remove once Release */
    void print_list(struct node* root)
    {
            struct node* current = root;
            while (current != NULL){
                printf("%s %s/%d %s\n",timestamp(current->data->time),
                current->data->location, current->data->device_id,
                (char)(current->data->msg));
                
                current = current->next;
            }
    }
            
    
    /* Data Structures */
    struct message {
        time_t time;
        char location[24];
        int device_id;
        double frequency;
        int burst_size;
        int msg_len;
        int *msg;
    };    
    
    struct node {
        struct node* next;
        struct message data;
    };
    
    
    
    int main(int argc, char **argv)
    {
        int i = 1, a = 0;
        time_t data_time;
        char data_location[24];
        int data_deviceid, burst_size, msg_len;
        double data_frequency;
        int *data_message;
        struct node *empty = NULL;
        
        /* Check for arguments if argc == 1 display usage */
        if (argc == 1){
            printf("usage: codebreak messagefile\n");
            printf("where: messagefile contains intercepts in the correct binary \
            format\n");
            return 0;
        }
        
        /* Open a File for reading */
        FILE *fp = fopen(argv[i],"r");
        
        /* Place Data into Variables ready for insertion into SLL */
        while ((a = fseek(fp,1,SEEK_CUR)) > 0){
            fseek(fp,0,SEEK_CUR);
            fscanf("%d %s %d %ld %d %d",&data_time,data_location,data_deviceid,
                    &data_frequency, &burst_size, &msg_len);
            fseek(fp,1,SEEK_CUR);
            data_message = malloc(msg_len*sizeof(int));
            fgets(data_message,msg_len,fp);
            sorted_insert(empty, data_time, data_location, data_deviceid,
            data_frequency, burst_size, msg_len, data_message);
        }
        
        print_list(empty);
    
        return 0;
    }        
    
    
    
    
    void sorted_insert(struct node** headRef, time_t data_time, char data_location[],
        int data_deviceid, double data_frequency, int burst_size, int msg_len,
        int data_msg[])
    {
        struct node** currentRef = headRef;
        struct node* new = (struct node*)malloc(sizeof(struct node));
        /* Traverse until right node for insertion */
        while(*currentRef != NULL && ((int)(data_time) < (int)((*currentRef)->data->time)))
            currentRef = &((*currentRef)->next;
        
        /* Insert data and re-link structures */
        new->next = *currentRef;
        *currentRef = new;
        new->data->time = data_time;
        for (int i = 0; i < 24; i++){
            new->data->location[i] = data_location[i];
        }
        new->data->device_id = data_deviceid;
        new->data->frequency = data_frequency;
        new->data->burst_size = burst_size;
        new->data->msg_len = msg_len;
        new->data->msg = malloc(sizeof(msg_len * sizeof(int)));
        
        for (int i = 0; i < msglen; i++){
            new->data->msg[i] = data_msg[i];
        }
    }    
    
    char *timestamp(time_t tval)
    {
        static char t_buff[MAX_TIMESTR];
        t_buff[MAX_TIMESTR-1] = '\0';
        strftime(t_buff, MAX_TIMESTR-1, "%Y-%m-%d",gmtime(&tval));
        return t_buff;
    }

  2. #2
    Im a Capricorn vsriharsha's Avatar
    Join Date
    Feb 2002
    Posts
    192
    Point No 1:
    You are using the structure "struct node *......." prior to its declaration....

    Add the definition of the structure node immediately after your #define...
    and that problem will be solved.
    Help everyone you can

  3. #3
    Im a Capricorn vsriharsha's Avatar
    Join Date
    Feb 2002
    Posts
    192
    Then there is a problem in your fscanf function... You need to pass the address of variables ( check out the third variable)...

    -Harsha.
    Help everyone you can

  4. #4
    ~viaxd() viaxd's Avatar
    Join Date
    Aug 2003
    Posts
    246
    Code:
    void print_list(struct node* root)
    {
            struct node* current = root;
            while (current != NULL){
                printf("%s %s/%d %s\n",timestamp(current->data->time),
                current->data->location, current->data->device_id,
                (char)(current->data->msg));
                
                current = current->next;
            }
    }
    in struct node, next is a pointer, data is not, so you can't use -> with it.
    try smt like: current->data.time, this goes for all other members of struct data.
    :wq

  5. #5
    Registered User
    Join Date
    Apr 2004
    Posts
    173
    Ya thanks for the hints - bah haven't actually written much C code getting rusty.. even wrote *char instead of char *

    Also, for the int* msg in the message structure can't I use:
    (current->data->msg) for it?
    I'm getting errors on dat, not sure why though.
    Last edited by 0rion; 08-27-2004 at 06:33 AM.

  6. #6
    ~viaxd() viaxd's Avatar
    Join Date
    Aug 2003
    Posts
    246
    since, data is not a pointer, you can't.
    :wq

  7. #7
    Registered User
    Join Date
    Apr 2004
    Posts
    173
    Hmm I pretty much cleaned up most of the code - now the functionality is a problem now. I previously did a smaller version playing around with text files with fseek() and fgets() for some reason, now it doesn't seem to even go in the while() loop in the main() function.


    Updated Code:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <assert.h>
    #include <time.h>
    #include <ctype.h>
    
    #define MAX_TIMESTR 1024
    
           
    /* Data Structures */
    struct message {
        time_t time;
        char location[24];
        int device_id;
        double frequency;
        int burst_size;
        int msg_len;
        int *msg;
    };    
    
    struct node {
        struct node* next;
        struct message data;
    };
    
    /* Function Prototypes */
    char *timestamp(time_t);
    void sorted_insert(struct node** headRef, time_t, char *, int, double, int, int, int[]);
    
    /* Debug Function Prototypes - Remove once Release */
    void print_list(struct node* root)
    {
            struct node* current = root;
            while (current != NULL){
                printf("%s %s/%d %s\n",timestamp((current->data).time),
                (current->data).location, (current->data).device_id,
                (current->data.msg));
                
                current = current->next;
            }
    }
    
    
    
    int main(int argc, char **argv)
    {
        int i = 1, a = 1;
        time_t data_time;
        char data_location[24];
        int data_deviceid, burst_size, msg_len;
        double data_frequency;
        int *data_message;
        struct node *empty = NULL;
        
        /* Check for arguments if argc == 1 display usage */
        if (argc == 1){
            printf("usage: codebreak messagefile\n");
            printf("where: messagefile contains intercepts in the correct binary format\n");
            return 0;
        }
        
        /* Open a File for reading */
        FILE *fp = fopen(argv[i],"r");
        
        /* Place Data into Variables ready for insertion into SLL */
        while ((a = fseek(fp,1,SEEK_CUR)) > 0){
            fseek(fp,0,SEEK_CUR);
            fscanf("%d %s %d %ld %d %d",&data_time,data_location,data_deviceid,
                    &data_frequency, &burst_size, &msg_len);
            fseek(fp,1,SEEK_CUR);
            data_message = malloc(msg_len*sizeof(int));
            fgets(data_message,msg_len,fp);
            /* Debug */
            printf("%d %s %d %ld %d %d",data_time,data_location,data_deviceid,
                    data_frequency,burst_size,msg_len);
                    
            sorted_insert(&empty, data_time, data_location, data_deviceid,
            data_frequency, burst_size, msg_len, data_message);
        }
        
        print_list(empty);
    
        return 0;
    }        
    
    
    void sorted_insert(struct node** headRef, time_t data_time, char data_location[],
        int data_deviceid, double data_frequency, int burst_size, int msg_len,
        int data_msg[])
    {
        int j;
        struct node** currentRef = headRef;
        struct node* new = (struct node*)malloc(sizeof(struct node));
        /* Traverse until right node for insertion */
        while(*currentRef != NULL && ((int)(data_time) < (int)((*currentRef)->data.time)))
            currentRef = &((*currentRef)->next);
        
        /* Insert data and re-link structures */
        new->next = *currentRef;
        *currentRef = new;
        new->data.time = data_time;
        for (j = 0; j < 24; j++){
            new->data.location[j] = data_location[j];
        }
        new->data.device_id = data_deviceid;
        new->data.frequency = data_frequency;
        new->data.burst_size = burst_size;
        new->data.msg_len = msg_len;
        new->data.msg = malloc(sizeof(msg_len * sizeof(int)));
        
        for (j = 0; j < msg_len; j++){
            new->data.msg[j] = data_msg[j];
        }
    }    
    
    char *timestamp(time_t tval)
    {
        static char t_buff[MAX_TIMESTR];
        t_buff[MAX_TIMESTR-1] = '\0';
        strftime(t_buff, MAX_TIMESTR-1, "%Y-%m-%d",gmtime(&tval));
        return t_buff;
    }
    Is there anyway to obtain the correct structure of the file and put them into their respective variables.
    It's meant to have something similar to:

    <int/time_t> <char[24]> <int> <double> <int> <int> <int[]>

    Where the last one can be any length depending on the message. The first 6 variables act like 'message headers' and provide information about how to output the message etc. I looked into the option of using getline() but I can't think of a correct way of implementing it to suit this scenario.

    Any suggestions?

  8. #8
    Registered User
    Join Date
    Apr 2004
    Posts
    173
    Ok it kinda works properly but my while() loop still doesn't work. How would I know when it reaches the EOF using fseek() and without messing up the currrent cursor thing. Unless you can determine it another way?

    I was thinking of counting the number of lines in the program and writing a condition on it but that most likely will not work since the messages they can type is dependent on msg_len and dat changes for each line etc.

    Any ideas?

  9. #9
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Quote Originally Posted by 0rion
    Ok it kinda works properly but my while() loop still doesn't work. How would I know when it reaches the EOF using fseek() and without messing up the currrent cursor thing. Unless you can determine it another way?
    How about checking the return value of fseek, and checking errno to see what the error is? Consider looking at the man page.

    [edit]
    You might also consider using ftell and do a bit of basic math to figure out just how big your file is before you start playing with it, and keep a counter of how far along you've move. That way you'll know when you've reached the end.
    [/edit]

    [edit2]
    Wait just a minute. This is a text file? You shouldn't really use fseek on text files. Well, at least not if they're more than a single line. There is a problem fseeking text files due to the way newline and carriage return are handled. Basicly, you don't want to use fseek at all on text files. (Yeah, the man pages for fopen say under a unix enviornment, there is no differance between binary and text, but as a portability hold over, don't fseek text files.)

    Basicly, if this is a text file, and all your information is stored on a line-by-line basis, you should really be reading the whole line, with something like fgets, processing it, and moving on.
    [/edit2]

    Quzah.
    Last edited by quzah; 08-27-2004 at 03:30 PM.
    Hope is the first step on the road to disappointment.

  10. #10
    Registered User
    Join Date
    Jun 2004
    Posts
    277
    This you can solve by your self.

    junk.c:69: warning: passing arg 1 of `fscanf' from incompatible pointer type
    junk.c:69: warning: passing arg 2 of `fscanf' from incompatible pointer type
    junk.c:72: warning: passing arg 1 of `fgets' from incompatible pointer type
    junk.c:75: warning: int format, time_t arg (arg 2)
    junk.c:75: warning: long int format, double arg (arg 5)

  11. #11
    Registered User
    Join Date
    Apr 2004
    Posts
    173
    Hmm seems the program only works for 1 line - I get unexpected output that is pretty much half of whats in the contents of the file and some blank fields if the file is more than 2 lines. I guess this maybe what you were talking about Quzah. Looks like I'll have to play around with fgets then. I'll post back on how that goes, thanks

  12. #12
    Registered User
    Join Date
    Apr 2004
    Posts
    173
    Just a small side question, why do I need to have fgets(___,msg_len+2,___) to read something of msg_len? Is it because it reads '\0' and the '\n' characters?

    Can't seem to figure it out - its really just a minor question since I'm curious - so if it does store the '\n' character it doesn't get printed right since the '\0' terminates before the '\n' character if I use something like: printf("%s",____).

  13. #13
    Im a Capricorn vsriharsha's Avatar
    Join Date
    Feb 2002
    Posts
    192

    Lightbulb

    Quote Originally Posted by 0rion
    Just a small side question, why do I need to have fgets(___,msg_len+2,___) to read something of msg_len? Is it because it reads '\0' and the '\n' characters?

    Can't seem to figure it out - its really just a minor question since I'm curious - so if it does store the '\n' character it doesn't get printed right since the '\0' terminates before the '\n' character if I use something like: printf("%s",____).
    This is what the MAN page in linux says:
    Quote Originally Posted by MAN_PAGE
    char *fgets(char *s, int size, FILE *stream);
    fgets() reads in at most one less than size characters from stream and
    stores them into the buffer pointed to by s. Reading stops after an
    EOF or a newline. If a newline is read, it is stored into the buffer.
    A ’\0’ is stored after the last character in the buffer.
    Help everyone you can

  14. #14
    Registered User
    Join Date
    Apr 2004
    Posts
    173
    This seems to work better - but still needs more work but I'm not willing to go just yet since I obtain a segementation fault even after correct printage. So it definitely goes towards my print_list() function but for some reason I get a segmentation fault afterwards. I've checked my print_list() code and that seems correct.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <assert.h>
    #include <time.h>
    #include <ctype.h>
    
    #define MAX_TIMESTR 1024
    
           
    /* Data Structures */
    struct message {
        time_t time;
        char location[24];
        int device_id;
        double frequency;
        int burst_size;
        int msg_len;
        int *msg;
    };    
    
    struct node {
        struct node* next;
        struct message data;
    };
    
    /* Function Prototypes */
    char *timestamp(time_t);
    void sorted_insert(struct node** headRef, time_t, char *, int, double, int, int, int[]);
    void print_list(struct node* root);
    
    
    
    
    int main(int argc, char **argv)
    {
        int i = 1, a = 0;
        time_t data_time;
        char data_location[24];
        int data_deviceid, burst_size, msg_len;
        double data_frequency;
        int *data_message = malloc(sizeof(int));
        struct node *empty = NULL;
    
        
        /* Check for arguments if argc == 1 display usage */
        if (argc == 1){
            printf("usage: codebreak messagefile\n");
            printf("where: messagefile contains intercepts in the correct binary format\n");
            return 0;
        }
        
        /* Open a File for reading */
        FILE *fp = fopen(argv[i],"r");
    
        /* while() loop needs major fix */
        /* Place Data into Variables ready for insertion into SLL */
    
    do {	
            fscanf(fp,"%d %s %d %f %d %d",&data_time,data_location,&data_deviceid,
                    &data_frequency, &burst_size, &msg_len);
    	data_message = realloc(data_message,(msg_len+1)*sizeof(int));
            fgets(data_message,msg_len+2,fp);
           /* 
            printf("%s",data_message);
            printf("%d | %s | %d | %f | %d | %d ",data_time,data_location,data_deviceid,
                    data_frequency,burst_size,msg_len);     
    	*/
            sorted_insert(&empty, data_time, data_location, data_deviceid,
            data_frequency, burst_size, msg_len, data_message);
    	i++;
    }   while(i != 3); 
            
            
        print_list(empty);
    
        return 0;
    }        
    
    
    void sorted_insert(struct node** headRef, time_t data_time, char data_location[],
        int data_deviceid, double data_frequency, int burst_size, int msg_len,
        int data_msg[])
    {
        int j;
        struct node** currentRef = headRef;
        struct node* new = (struct node*)malloc(sizeof(struct node));
        /* Traverse until right node for insertion */
        while(*currentRef != NULL && ((int)(data_time) < (int)((*currentRef)->data.time)))
            currentRef = &((*currentRef)->next);
        
        /* Insert data and re-link structures */
        new->next = *currentRef;
        *currentRef = new;
        new->data.time = data_time;
        for (j = 0; j < 24; j++){
            new->data.location[j] = data_location[j];
        }
        new->data.device_id = data_deviceid;
        new->data.frequency = data_frequency;
        new->data.burst_size = burst_size;
        new->data.msg_len = msg_len;
        new->data.msg = malloc(sizeof(msg_len * sizeof(int)));
        
        for (j = 0; j < msg_len; j++){
            new->data.msg[j] = data_msg[j];
        }
    }    
    
    char *timestamp(time_t tval)
    {
        static char t_buff[MAX_TIMESTR];
        t_buff[MAX_TIMESTR-1] = '\0';
        strftime(t_buff, MAX_TIMESTR-1, "%Y-%m-%d",gmtime(&tval));
        return t_buff;
    }    
    
    void print_list(struct node* root)
    {
            if (root == NULL){
                printf("Nothing to print! Empty list!\n");
                return;
            }    
            struct node* current = root;
            while (current != NULL){
                printf("%s %s/%d %s\n",timestamp((current->data).time),
                (current->data).location, (current->data).device_id,
                (current->data.msg));
                
                current = current->next;
            }
    }
    A sample input would be:
    7500000000 World 15 500000 15 10 HelloWorld
    60000000 Middle 60 700000 15 20 Say What? Middle?

    A sample output would be:
    2038-01-19 World/15 HelloWorld
    1971-11-26 Middle/60 Say What? Middle?

    Segmentation Fault

    I also tried reading 3 text lines and letting the while loop in the main() run 1 extra time - this got unexpected results as well. Could it be due to my usage of malloc() and realloc()?

    <<<Update:>>>
    After changing the realloc() code from the size_t argument to be from msg_len+1 to (msg_len+1)*sizeof(int) - the segementation fault disappears and now another problem pops up (aargh!) as demonstrated below:

    A sample input would be:
    7500000000 World 15 500000 15 10 HelloWorld
    60000000 Middle 60 700000 15 20 Say What? Middle?

    A sample output would be:
    2038-01-19 World/15 HelloWorld
    2038-01-19 World/15 HelloWorld
    Last edited by 0rion; 08-28-2004 at 01:13 AM.

  15. #15
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    You're using an integer array as the buffer for fgets(). This seems...a bit odd.
    If you understand what you're doing, you're not learning anything.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. What's a good generalized data structures book?
    By indigo0086 in forum A Brief History of Cprogramming.com
    Replies: 12
    Last Post: 11-16-2006, 01:01 PM
  2. i need advice about data structures
    By sawer in forum C Programming
    Replies: 2
    Last Post: 04-22-2006, 03:40 AM
  3. Any Good Data Structures Books?
    By YevGenius in forum C++ Programming
    Replies: 3
    Last Post: 05-26-2004, 07:49 AM
  4. array of structures, data from file
    By nomi in forum C Programming
    Replies: 5
    Last Post: 01-11-2004, 01:42 PM
  5. Array Data Structures
    By Unregistered in forum C Programming
    Replies: 2
    Last Post: 03-27-2002, 06:52 PM