Thread: Structures and Unions(arrrr)

  1. #1
    Registered User
    Join Date
    Feb 2002
    Posts
    3

    Unhappy Structures and Unions(arrrr)

    Bascially i have 3 structures here and need to read in from a file the first record stored in zentd which is unval_ptr.
    When i run this program there are no syntax errors (which is good).
    But nothin is being read from zentd i have no idea if i've gone about this the right way or not, or why it isnt reading the file!!

    Any help would be much appreciated

    #include<stdio.h>
    #include<stdlib.h>
    #include<conio.h>
    #include<string.h>
    #include<ctype.h>
    #include<time.h>
    #define LINES_PER_PAGE 60
    #define MODULUS 11
    #define REC_SIZE sizeof(valid_ptr)
    #define SIZE sizeof(union customer)


    /*define structures*/

    struct I_R_details {
    char record_type;
    char cust_code[7];
    char part_num[7];
    int quantity;
    };

    struct deletion_details {
    char record_type;
    char cust_code[7];
    };

    struct creation_details {
    char record_type;
    char cust_code[6];
    char cust_name[21];
    char cust_addr[61];
    float cust_bal;
    long credit_limit;
    };



    /*declare the functions that are to be used*/

    void error(int i);
    void print_headings(void);
    int validation1(char *test_ptr);
    int field_val(char *str_ptr);
    int validation2(char *test1_ptr);
    int save_rec(FILE *valid);
    float bal_check(int chk);
    int quant_check(int check);
    int credit_val(int credit);

    /* global variables*/

    FILE *unval_ptr, *valid_ptr, *out_prn; /*file pointers*/
    int lines = 0, cust_code;
    int weights[] = { 6, 5, 4, 3, 2,};
    struct tm *todays_date;
    time_t calendar_time;

    void main()
    {

    union customer {
    struct I_R_details first;
    struct deletion_details second;
    struct creation_details third;
    }unval;



    int chk_digit = 0, valid1 = 0, fine = 0, valid = 0;




    /* try and open the files ready to use*/
    if( (unval_ptr = fopen("zentd.dat" , "rt" )) == NULL)
    {
    fprintf(stderr, "\n Error in opening file GD03TD ");
    exit(1);
    }

    if( ( valid_ptr = fopen("GD03VF" , "rt+" )) == NULL)
    {
    fprintf(stderr, "\n Error in creating GD03VF ");
    exit(1);
    }

    if ( ( out_prn = fopen("prn", "wt")) == NULL)
    {
    fprintf(stderr, "\nError in opening printer ");
    exit(1);
    }


    /*call function to print error headings*/
    print_headings();

    /*read records from file*/

    while(fread(&unval, SIZE, 1, unval_ptr) == 1)

  2. #2
    Registered User
    Join Date
    Aug 2001
    Posts
    247
    welcome to the compu community.....you are trying to read a text file with binary fread.......and use zenctd instead of zentd.
    hoping to be certified (programming in c)
    here's the news - I'm officially certified.

  3. #3
    Sayeh
    Guest
    First, you need to typedef your structures correctly, and then put your union up under your typedefs--

    Code:
    /*****
     *
     *  TYPEDEFS
     *
     *****/
    
    typedef struct
       { 
       char   record_type; 
       char   cust_code[7]; 
       char   part_num[7]; 
       int      quantity; 
       }I_R_details; 
    
    typedef struct
       { 
       char   record_type; 
       char   cust_code[7]; 
       }deletion_details; 
    
    typedef struct
       { 
       char   record_type; 
       char   cust_code[6]; 
       char   cust_name[21]; 
       char   cust_addr[61]; 
       float   cust_bal; 
       long   credit_limit; 
       }creation_details; 
    
    typedef union customer 
       { 
       I_R_details          first; 
       deletion_details  second; 
       creation_details   third; 
       }unval;

    Then, take a look at your actual read command-- from what I glanced at in your code, I can't see that you've asked it to read in anything--

    Code:
    while(fread(&unval, SIZE, 1, unval_ptr) == 1)
    ]

    fread() requires 4 things to be passed to it:

    1) The address of a buffer to read data into

    'unval' isn't a variable, it is a TYPE of variable. Just as 'char' is not a variable it is a TYPE of variable.

    2) The size of the element to be read

    'SIZE' isn't defined anywhere that I see. It is supposed to be coded as something like 'element_size = sizeof(unval);'. If 'SIZE' is currently zero, that would explain why you're not getting any input.

    3) The Number of Elements to read

    4) The file pointer.

    Furthermore, if you know how many elements to read, then you don't need to use the while() statement. All you have to do is have a buffer larger enough for all of them and then access them as an array.

    You should also zero the file pointers (any pointer for that matter) prior to using them.

    Note that you should also use binary mode when reading/writing this data.

    For Example:

    Code:
    /*****
     *
     *  TYPEDEFS
     *
     *****/
    
    typedef struct
       { 
       char   record_type; 
       char   cust_code[7]; 
       char   part_num[7]; 
       int      quantity; 
       }I_R_details; 
    
    typedef struct
       { 
       char   record_type; 
       char   cust_code[7]; 
       }deletion_details; 
    
    typedef struct
       { 
       char   record_type; 
       char   cust_code[6]; 
       char   cust_name[21]; 
       char   cust_addr[61]; 
       float   cust_bal; 
       long   credit_limit; 
       }creation_details; 
    
    typedef union
       { 
       I_R_details          first; 
       deletion_details  second; 
       creation_details   third; 
       }unval; 
    
    
      . . .
    
    
    int main(void)
       {
       size_t   bufSize;
       FILE      *myFileP;
       unval    *bufferP;
       size_t   elemSize;
    
       elemSize = sizeof(unval);
       myFileP = 0L;
       bufSize = (elemSize * 10);                  /* we have 10 entries to read */
       bufferP = 0L;
    
       bufferP = (unval*)malloc(bufSize);      /* allocate buffer to hold all 10 */
       if(!bufferP)
          {
          printf(stderr,"\n Error in allocating input buffer");
          exit(1);
          };
    
       myFileP = fopen("zentd.dat","r+b");
       if(!myFileP)
          { 
          printf(stderr, "\n Error in opening file GD03TD "); 
          exit(1);
          };
    
       fread(bufferP,elemSize,10,myFileP);
    
       . . .
    
       /* after you've read it, you can then access it */
    
       }
    Since the first 2 fields of every structure are the same, I would re-typedef the structures and union as follows:

    Code:
    typedef struct
       { 
       char   part_num[7]; 
       int      quantity; 
       }I_R_details; 
    
    typedef struct
       {
       char   cust_name[21]; 
       char   cust_addr[61]; 
       float   cust_bal; 
       long   credit_limit; 
       }creation_details; 
    
    typedef struct
       { 
       char      record_type; 
       char      cust_code[7]; 
       union
          {
          I_R_detail            irInfo;
          creation_details   cInfo;
          };
       }customer;
    enjoy.

  4. #4
    Registered User
    Join Date
    Feb 2002
    Posts
    3
    Ok i get that but what if i dont actually know the size of the file?

    After all that when i have to validate all the info thats in the file have have done the following:
    not quite sure how to go about validate each different field

    if(unval.I_R_details.record_type == 'I' )

    {
    validation1(unval.first.cust_code);
    {
    if (chk_digit == 'X')
    {
    error(1);
    fprintf(out_prn, "%c%6s%6s%d",
    unval.first.record_type,
    unval.first.cust_code,
    unval.first.part_num,
    unval.first.quantity);
    }
    else
    {
    save_rec(valid_ptr);
    }
    }
    }
    else
    {
    if(unval.first.record_type == 'R' )

    {
    validation1(unval.first.cust_code);
    {
    if (chk_digit == 'X')
    {
    error(1);
    fprintf(out_prn, "%c%6s%6s%d",
    unval.first.record_type,
    unval.first.cust_code,
    unval.first.part_num,
    unval.first.quantity);
    }
    else
    {
    save_rec(valid_ptr);
    }
    }
    }

    else
    {
    if(unval.second.record_type == 'D')
    {
    validation1(unval.second.cust_code);
    if (chk_digit == 'X')
    {
    error(1);
    fprintf(out_prn, "%c%6s",
    unval.second.record_type,
    unval.second.cust_code);
    }
    else
    {
    save_rec(valid_ptr);
    }
    }
    }


    {
    if(unval.third.record_type == 'C')
    {
    validation1(unval.third.cust_code);
    {
    if (chk_digit == 'X')
    {
    error(1);
    fprintf(out_prn, "%c%6s%20s%60s%9fd%7ld",
    unval.third.record_type,
    unval.third.cust_code,
    unval.third.cust_name,
    unval.third.cust_addr,
    unval.third.cust_bal,
    unval.third.credit_limit);
    }
    else
    {
    save_rec(valid_ptr);
    }
    }
    }
    else
    {
    error(7);
    fprintf(out_prn, "%c", unval.first.record_type);
    }
    }
    quant_check(unval.first.quantity);
    {
    if(valid == 1)
    {
    error(3);
    fprintf(out_prn, "%c%6s%6s%d",
    unval.first.record_type,
    unval.first.cust_code,
    unval.first.part_num,
    unval.first.quantity);
    }
    else
    {
    save_rec(valid_ptr);
    }

    }
    validation2(unval.first.part_num);
    if (chk_digit == 'X')
    {
    error(1);
    fprintf(out_prn, "%c%6s%6s%d",
    unval.first.record_type,
    unval.first.cust_code,
    unval.first.part_num,
    unval.first.quantity);
    }
    else
    {
    save_rec(valid_ptr);
    }
    field_val(unval.third.cust_addr);
    {
    if(valid1 == 1)
    {
    error(4);
    fprintf(out_prn, "%c%6s%20s%60s%9fd%7ld",
    unval.third.record_type,
    unval.third.cust_code,
    unval.third.cust_name,
    unval.third.cust_addr,
    unval.third.cust_bal,
    unval.third.credit_limit);

    }
    else
    {
    save_rec(valid_ptr);
    }
    }
    }

    bal_check(unval.third.cust_bal);
    {
    if(fine == 1)
    {
    error(5);
    fprintf(out_prn, "%c%6s%20s%60s%9fd%7ld",
    unval.third.record_type,
    unval.third.cust_code,
    unval.third.cust_name,
    unval.third.cust_addr,
    unval.third.cust_bal,
    unval.third.credit_limit);
    }
    else
    {
    save_rec(valid_ptr);
    }
    }

    credit_val(unval.third.credit_limit);
    {
    if(valid1 == 1)
    {
    error(6);
    fprintf(out_prn, "%c%6s%20s%60s%9fd%7ld",
    unval.third.record_type,
    unval.third.cust_code,
    unval.third.cust_name,
    unval.third.cust_addr,
    unval.third.cust_bal,
    unval.third.credit_limit);

    }
    else
    {
    save_rec(valid_ptr);
    }
    }


    if( lines <= LINES_PER_PAGE)
    {
    print_headings();
    lines = 4;
    }
    }

    /*close all files*/

    fclose(unval_ptr);
    fclose(valid_ptr);
    fclose(out_prn);
    }


    /*function declarations*/


    void print_headings(void)
    {
    /*output the error headings to the printer*/
    static int page;

    page++;

    fprintf(out_prn, " GMD RETAILS \t\tPAGE %3d\n",
    asctime(todays_date) ,page);
    fprintf(out_prn, " CUSTOMER ERRORS REPORT\n");

    fprintf(out_prn, " Rec Type\tCust Code\tQuantity\tCust Name\t\t\tBalance\t"
    " Credit Limit\tError Code\n");

    lines = 5;

    fprintf(out_prn, " EXPLANATION OF ERROR CODES \n");
    fprintf(out_prn, " A - Customer Code Error \n");
    fprintf(out_prn, " B - Part Num Error \n");
    fprintf(out_prn, " C - Quantity Error \n");
    fprintf(out_prn, " D - Address Error \n");
    fprintf(out_prn, " E - Balance Error \n");
    fprintf(out_prn, " F - Credit Limit Error \n");
    fprintf(out_prn, " G - Record Type Error \n");


    }

    int field_val(char *str_ptr)
    {
    int valid1 = 0;
    while(*str_ptr)
    { /*test to make sure there is ';' in the spaces*/
    /*of the address*/
    *str_ptr = (*str_ptr == ' ') ? ';' : *str_ptr;
    str_ptr++;
    valid1 = 1;
    }
    return valid1;
    }




    int validation1(char *test_ptr)
    {
    /*check to make sure code is ok*/

    char chk_digit;
    int loop, rem = 0, total = 0, check_num = 0, value = 0;

    for(loop = 0; loop < 5; loop++)

    /*convert character digit to int value*/
    {
    value = test_ptr[loop] - '0';
    total += value * weights[loop];
    }

    rem = total % MODULUS;
    check_num = MODULUS - rem;

    /*convert int value into char digit*/

    if( check_num < 10)
    chk_digit = check_num + '0';
    else
    if(check_num == 10)
    chk_digit = '0';
    else
    chk_digit = 'X';



    return(chk_digit);

    }

    int quant_check(int check)
    {

    int loop, valid = 1;
    for(loop = 0; loop <= 4; loop++)
    {
    if(loop >= 0 && loop <= 4)
    {
    if(!isdigit(check))
    valid = 0;
    check++;
    }
    }
    return (valid);

    }


    int validation2(char *test1_ptr)
    {

    char chk_digit;
    int loop, rem, total = 0, check_num, value;

    for(loop = 0; loop < 6; loop++)

    /*convert character digit to int value*/
    {
    value = test1_ptr[loop] - '0';
    total += value * weights[loop];
    }

    rem = total % MODULUS;
    check_num = MODULUS - rem;

    /*convert int value into char digit*/
    if( check_num < 10)
    chk_digit = check_num + '0';
    else
    if(check_num == 10)
    chk_digit = '0';
    else
    chk_digit = 'X';


    return(chk_digit);
    }

    float bal_check(int chk)
    {

    int loop, fine = 1;
    for(loop = 0; loop <= 9; loop++)
    {
    if(loop >= 0 && loop <= 9)
    {
    if(!isdigit(chk))
    fine = 0;
    chk++;
    }
    }
    return (fine);

    }

    int credit_val(int credit)
    {
    int loop, fine = 1;
    for(loop = 0; loop <= 9; loop++)
    {
    if(loop >= 0 && loop <= 9)
    {
    if(!isdigit(credit))
    fine = 0;
    credit++;
    }
    }
    return (fine);

    }

    void error(int i)

    {

    char *e[] = {"\n (A)",
    "(B)",
    "(C)",
    "(D)",
    "(E)",
    "(F)"
    "(G)\n\n" };

    fprintf(out_prn, "\a%c", e[i]);

    }
    int save_rec(FILE *valid)
    {
    /*write valid record to file*/
    fwrite(valid, REC_SIZE,1,valid_ptr);

    return 1;
    }
    Last edited by Plastic_Road; 02-27-2002 at 11:28 AM.

  5. #5
    Sayeh
    Guest
    Well, you should know the format of the file, right?

    If all it is is structures that you've created, then get the size of the file and divide it by the size of your structure-- that tells you how many elements are in the file.

    If you want to verify the file, add a long onto the start of the file-- have your records immediately following it.

    Put a 32-bit crc in that long when the file is saved, which is a crc for all the data in all the records at once. Then, when you go to load the records, just read the first 32-bits of the file (a 'long') and then run a crc on the rest of the data in the file-- if the crc at the start of the file, and the one you calculate don't match-- the data's corrupt.. Otherwise, it's good.

    It's easier to do things in bulk; more effecient and faster, too.

    enjoy.

Popular pages Recent additions subscribe to a feed