Thread: reading several structs

  1. #1
    Registered User breed's Avatar
    Join Date
    Oct 2001
    Posts
    91

    Exclamation reading several structs

    Can some one help me with a querie, i have three structures listed below and i need to access them then run several validation tests, i'm going to use

    while(fscanf( some_fp, "%c %s %s %d",I_R_RECORD.rec_type, I_R_RECORD.cust_code, I_R_RECORD.part_num, I_R_RECORD.quantity) !=EOF)

    to read the structure/s. Th question being can i access them all within one while(fscanf()), or do i have to fscanf() the three structures seperately

    typedef struct {
    char rec_type;
    char cust_code[5];
    char part_num[6];
    int quantity[4];
    }I_R_RECORD;

    typedef struct {
    char rec_type;
    char cust_code[5];
    }DELETE_RECORD;

    typedef struct {
    char rec_type;
    char cust_code[5];
    char cust_name[20];
    char cust_addr[60];
    float cust_bal;
    int credit_lmit;
    }CREATION_RECORD;

    explinations and examples will help a great deal

    Thank in advs

    breed

  2. #2
    Just one more wrong move. -KEN-'s Avatar
    Join Date
    Aug 2001
    Posts
    3,227
    The best way to read in structures is with fread(), here's some sample code:

    Code:
    struct RECORD{
          ....
    }I_R_RECORD;
    ....
    while(fread((void *)I_R_RECORD, sizeof(struct RECORD), 1, fp)==1)
          printf("%c\n%s\n%s\n%d",I_R_RECORD.rec_type, I_R_RECORD.cust_code, I_R_RECORD.part_num, I_R_RECORD.quantity);
    And you'd have to use 2 other while loops to read the rest of your structires.

    Basically, the function fread() takes a void pointer to the struct you want to put the info into, the size of the structure, the number to read in, and the file pointer
    Last edited by -KEN-; 01-05-2002 at 09:35 AM.

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > Th question being can i access them all within one while(fscanf()), or do i have to fscanf() the three structures seperately
    If this is a text file, the best thing is to read a line into a buffer using fgets, then use sscanf (one or more times) to decide what the line actually means

    Code:
    char buff[BUFSIZ];
    while ( fgets( buff, BUFSIZ, fp ) != NULL ) {
      // test for each record type
      // using sscanf
      // or something else - as you see fit
    }

  4. #4
    Registered User breed's Avatar
    Join Date
    Oct 2001
    Posts
    91

    Thumbs up

    Thanks for the fast reply guy's i'll try both ways out see which i have the least probs with, although i'm not that familiar with using BUFFSIZE i should really try to use it (perhaps it will all become clearer in the mornin ;-) )
    Before you judge a man, walk a mile in his
    shoes. After that, who cares.. He's a mile away and you've got
    his shoes.
    ************William Connoly

  5. #5
    Unregistered
    Guest
    Two things confuse me KEN and Salem.

    First, KEN.
    Your code said this
    while(fread((void *)I_R_RECORD, sizeof(struct RECORD), 1, fp)==1)
    Since fread takes a void pointer and void pointer is the generic pointer that supposedly accepts any pointer without needing a cast then why do you use (void *) to cast your structure? Also, since fread takes the number of items why not have something like this instead?
    if(fread(I_R_RECORD, sizeof struct RECORD, ITEM_NUM, fp)<ITEM_NUM)
    {
    /*error code*/
    }
    You avoid using a loop that way and still read three structures in.

    And now for Salem.
    I understand what you meant by using fgets and sscanf, but since the data is wrapped in a structure wouldn't it be easier just to read it in with fread? If not, why? I know that fread is supposed to read binary data and using it on a text file is taboo among programmers, but since most data files are structured to not have overlapping data you can just read the number of bytes into the proper area of a struct and be done with it in a single line. This would make the code shorter and simpler. I also imagine that fread is called eventually inside fgets or any other text input function, so can't I just get rid of the middlemen and call it myself? Once again, if I can't please explain why.

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Like I said
    > If this is a text file

    fgets for text files
    fread for binary files

    The rest is pretty much up to you

  7. #7
    Unregistered
    Guest
    I understand that one is for text and one is for binary, but why should they be used exclusively for either text or binary? Since a lot of people seem to use fread to input data into a structure even if that data is text I'd like to know why this is okay if fread is meant to ONLY read binary data.

  8. #8
    Registered User breed's Avatar
    Join Date
    Oct 2001
    Posts
    91
    Perhaps i should have been a bit more elaborate!
    the prog that i'm working on is supposed to read from a .dat file, and on this file (which is text) there are three types of records
    a receipt record, deletion record and a creation record, each record has data made up of the above structures.
    any idea's on how to read the dat file, each record has a record type i.e:'r' (receipt has 4 feilds) 'd' (delete has 2 feilds) 'c' (create has 5 feilds)

    how would i determine what type of record is being read at any time of the reading proccess cos each record has a different amount of feilds, can i get around this by adding a \n char after ver rec.
    we are told to create our own test data!
    but this still dose'nt get me off the hook with the rec size

    help plz!
    Before you judge a man, walk a mile in his
    shoes. After that, who cares.. He's a mile away and you've got
    his shoes.
    ************William Connoly

  9. #9
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Here's how the reading of the text file might look

    Code:
    #include <stdio.h>
    
    // what db.txt might look like
    // c 1111 Flintstone Bedrock 1234.56 10000
    // c 2222 Dracula Transylvania 135 6789
    // r 1111 1234 42
    // r 2222 1234 99
    // d 2222
    
    typedef struct {
        char rec_type;
        char cust_code[5];
        char part_num[6];
        int quantity[4];
    }I_R_RECORD;
    
    typedef struct {
        char rec_type;
        char cust_code[5];
    }DELETE_RECORD;
    
    typedef struct {
        char rec_type;
        char cust_code[5];
        char cust_name[20];
        char cust_addr[60];
        float cust_bal;
        int credit_lmit;
    }CREATION_RECORD;
    
    int main ( ) {
        char            buff[BUFSIZ];
        FILE            *fp;
        I_R_RECORD      ir_rec;
        DELETE_RECORD   del_rec;
        CREATION_RECORD cr_rec;
        int             nfields;
    
        fp = fopen ( "db.txt", "r" );
        while ( fgets( buff, BUFSIZ, fp ) != NULL ) {
            switch ( buff[0] ) { // ie the 'c' 'r' or 'd'
            case 'c':
                break;
            case 'r':
                break;
            case 'd':
                nfields = sscanf( buff, "%c %s", &del_rec.rec_type, del_rec.cust_code );
                if ( nfields != 2 ) {
                    // error
                }
                break;
            default:
                break;
            }
        }
        fclose( fp );
        return 0;
    }

  10. #10
    Registered User
    Join Date
    Aug 2001
    Posts
    247
    Hi, Zenith paints again.

    read the file as text using a union

    Code:
    typedef struct { 
    char rec_type; 
    char cust_code[5]; 
    char part_num[6]; 
    int quantity[4]; 
    }I_R_RECORD; 
    
    typedef struct { 
    char rec_type; 
    char cust_code[5]; 
    }DELETE_RECORD; 
    
    typedef struct { 
    char rec_type; 
    char cust_code[5]; 
    char cust_name[20]; 
    char cust_addr[60]; 
    float cust_bal; 
    int credit_lmit; 
    }CREATION_RECORD; 
    
    typedef union {
         I_R_RECORD Iss_Ret;
         DELETE_RECORD Deletion;
         CREATION_RECORD Create;
         } ALL_RECS;
    use one loop to read the records and carry out the validation according to the record type. 
    
    while(type = fgetc(fp)!= EOF)
    {
           switch(type) {
      /*your cases to read the remainder of the record
         and validate records remember to cater for \n char */
      /* this is best done character at a time */
      } /*end switch*/
    } /*end while*/
    Last edited by bigtamscot; 01-06-2002 at 02:32 PM.

  11. #11
    Registered User breed's Avatar
    Join Date
    Oct 2001
    Posts
    91
    using the above structures along with the following functions, can you check wether i have called the function in the switch correctly(syntax) if i haven't can you let me know why.

    void rpt(struct I_R_RECORD *buff);
    void del(struct DELETION_RECORD *buff);
    void crt(struct CREATION_RECORD *buff);

    //function definitions?


    void main()
    {
    char buff[BUFFERSIZE];
    int f_num;


    while( fgets(buff, BUFFERSIZE, test_rec_fp) !=NULL)
    {
    switch(buff[0])
    {
    case 'I' :
    case 'R' : f_num = sscanf(buff, "%c %s %s %d", &I_R_RECORD.rec_type,&I_R_RECORD.cust_code, &I_R_RECORD.part_num, &I_R_RECORD.quantity);
    if(f_num != 4)
    error_rep(buff, error(5));// i have a seperate error function which reports the type of error
    else
    rcp(buff); // is this a correct function call?
    break;
    case 'D' : f_num = sscanf(buff, "%c %s", %DELETE_RECORD.type_code, &DELETE_RECORD.cust_code);
    if(f_num != 2)
    error_rep(buff, error(5));
    else
    del(buff);
    break;
    case 'C' : f_num =sscanf(buff, "%c %s %s %s %f %d", &CREATION_RECORD.type_code, &CREATION_RECORD.cust_code, &CREATION_RECORD.cust_name,&CREATION_RECORD.cust_a ddr,&CREATION_RECORD.cust_bal,&CREATION_RECORD.cre dit_limit);
    if(f_num != 6)
    error_rep(buff, error(5));
    else
    crt(buff);
    break;
    default :;

    }
    }

    TIA for help
    Before you judge a man, walk a mile in his
    shoes. After that, who cares.. He's a mile away and you've got
    his shoes.
    ************William Connoly

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. reading file word by word
    By 98holb in forum C Programming
    Replies: 2
    Last Post: 01-25-2006, 05:49 PM
  2. Replies: 5
    Last Post: 10-02-2005, 12:15 AM
  3. reading float from file
    By arjunajay in forum C++ Programming
    Replies: 10
    Last Post: 07-30-2005, 11:01 PM
  4. Reading from file into structs..
    By dankas in forum C Programming
    Replies: 14
    Last Post: 10-16-2002, 10:33 PM
  5. reading from structs in a binary file
    By Unregistered in forum C Programming
    Replies: 4
    Last Post: 12-21-2001, 10:52 AM