unions and files

This is a discussion on unions and files within the C Programming forums, part of the General Programming Boards category; Hi, I'm trying to debug a C program that I have written and getting nowhere fast. It involves reading from ...

  1. #1
    Unregistered
    Guest

    Lightbulb unions and files

    Hi,

    I'm trying to debug a C program that I have written and getting nowhere fast.

    It involves reading from a file, validating the data and writing this back to another file.

    To write it back I'm using a union of 3 structures( as it can be one of 3 types of record). However, the program runs ofr around 20 records and then crashes with a windows, you have accessed memory error. So I've looked for an array that isn't big enough etc but everything looks ok.

    Wondered if it might have something to do with the union, as I initialise the longest structure in it on each pass, so as not to carry over any data to the next record.

    Here's the main function of the program.

    Thanks

    Andy.


    void quantity(void);
    void error(int i);
    void valid(void);
    void valid_part_number(void);
    char Pause(void);
    void read(void);
    void valid_cust_name(void);
    void valid_address(void);
    void cust_balance(void);
    void cust_credit(void);



    FILE *fp_ptr,
    *prn_ptr,
    *valid_ptr;

    struct ir_rec { /* Insert/replace record */
    char type, /* record type */
    cust_code[5], /* customer code */
    part_no[6], /* part number */
    quantity[20]; /* issue/ received quantity */
    };

    struct del_rec { /* deletion record */
    char type,
    cust_code[5];
    };

    struct create_rec { /* creation record */
    char type,
    cust_code[5],
    cust_name[20], /* cust name */
    cust_address[60], /* address */
    cust_balance[9], /* balance */
    cust_credit_limit[7]; /* credit limit */
    }dummy;


    union records {
    struct ir_rec ir;
    struct del_rec del;
    struct create_rec create;
    };

    union records transaction; /* transaction is union name */

    char big[150],
    *trans_ptr,
    record[5];

    int *big_ptr,
    delta = 0,
    lines = 0;


    void main()
    {


    char ch;
    struct create_rec dummy = {'\0',
    "\0",
    "\0",
    "\0",
    "\0",
    "\0" };


    /* open file for input */

    if(( fp_ptr = fopen("A\:TEST.txt","r")) == NULL)
    {
    printf("\n Error in opening input file\n");

    exit(1);
    /* can't open or find file, exit to OS */

    }


    /* open printer file */

    /* if(( prn_ptr = fopen("A:\PRN1.dat","wb")) == NULL)
    {
    printf("\nError opening printer for output\n");
    Pause();
    exit(1); */
    /* printer unavailable, exit to OS */


    /* open file for output */

    if(( valid_ptr = fopen("A:\VALIDATED.dat","wb+")) == NULL)

    {
    printf("\nError creating output file\n");
    exit(1);
    /* unable to create/write to output file */
    }

    /* print headings */

    fprintf(prn_ptr, "FILE ERROR REPORT\n");


    lines = 2;

    /* read in from file */
    printf("file read");
    Pause();

    while(!feof(fp_ptr))
    {

    transaction.create = dummy;

    fscanf(fp_ptr, "%[^\n]", big);
    ch = fgetc(fp_ptr); /* increments file pointer to skip newline character */
    /* printf("\n %s", big);
    Pause(); */
    ch = toupper(*big);
    printf("\n%c first chararcter", ch);
    /* if(ch ==' ')
    {
    error(5);
    } */

    switch(ch)
    {
    case 'I': valid();
    valid_part_number();
    quantity();

    break;
    case 'R': valid();
    valid_part_number();
    quantity();

    break;
    case 'D': valid_part_number();
    break;
    case 'C': valid_cust_name();
    valid_address();
    cust_balance();
    cust_credit();
    break;

    default: error(3);
    }
    /* write validated record to file */




    fwrite(&transaction, sizeof(transaction.create), 1, valid_ptr);



    }


    fcloseall();

  2. #2
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,484
    None of the code you post has any memory allocation in it, so its hard to say what you're doing wrong.

    Post all the code, preferably using the board's handy attachment facility.

    But there are some things to note.
    1. What's the purpose of the struct create_rec ... dummy; variable?

    2. void main() - main returns an int.

    3. "A\:TEST.txt" is a broken filename - try "A:\\TEST.txt"

    4. fwrite(&transaction, sizeof(transaction.create), 1, valid_ptr);
    You should only use sizeof(transaction), just in case the create member is no longer the largest member.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  3. #3
    Registered User
    Join Date
    Sep 2001
    Posts
    4

    code for union

    Hi,

    Here's the code.

    1) the dummy variable is used to zeroise the transaction union before writing the next record to it (as each structure in the union is a different length I didn't know whether there would be any carryover from a previous record).

    Thanks for the other tips, I'll have a play with it see if I can make any sense of where its wrong.

    Cheers

    Andy.
    Attached Files Attached Files

  4. #4
    and the hat of wrongness Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    32,484
    Well here's one mistake

    Code:
       /* next 4 chars are customer code and 5th is check digit */
       printf("\n %s big", big);
       strncpy(transaction.ir.cust_code, (big+1),5);
       
    
       /* check that all characters are digits */
    
       strcpy(ch,transaction.ir.cust_code);
    The strcpy to ch is going to overflow, EVEN if transaction.ir.cust_code is immediately followed by a \0 (and there's no guarantee of that).

    Here's a tip
    Instead of writing
      cust_code[5]
    write
      #define CUST_CODE_LEN 5
      cust_code[CUST_CODE_LEN]

    Then in the rest of the code you can use CUST_CODE_LEN instead of 5, and have something which is more readable.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.
    I support http://www.ukip.org/ as the first necessary step to a free Europe.

  5. #5
    Registered User
    Join Date
    Sep 2001
    Posts
    4
    Hi Salem,

    I've changed all the strcpy's to strncpy and put in the amount of characters that I want to copy across (as per the #define) and it works..

    many thanks, I was beginning to tear my hair out

    Cheers

    Andy.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Parse a program for functions, variables
    By Enu in forum C Programming
    Replies: 2
    Last Post: 02-15-2006, 10:08 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21