Sorting a Union

This is a discussion on Sorting a Union within the C Programming forums, part of the General Programming Boards category; Hi, I'm trying to write a program to read in a file (over a 100 records, each being a union ...

  1. #1
    andy
    Guest

    Angry Sorting a Union

    Hi,

    I'm trying to write a program to read in a file (over a 100 records, each being a union of 3 structures), sort them, print them out and write the sorted data to the another file.

    It does read them in and sort them and this seems to work, but cant seem to access the block of memory to print them out.

    I have a pointer to the union transaction records *s and s is the start of the block of memory for the file read.

    I declared a pointer to s after the sort and then tried to print out eg transaction.ir.type etc and then increment the pointer but I don't get anything output.

    help!!

    Andy.

    Here's the code (I know its a bit messy)

    #include <stdio.h>
    #include <ctype.h>
    #include <conio.h>
    #include <stdlib.h>
    #include <string.h>


    #define LINES_PER_PAGE 60

    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,
    *sorted_ptr,
    *valid_ptr;

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

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

    struct create_rec { /* creation record */
    char type,
    cust_code[6],
    cust_name[21], /* cust name */
    cust_address[61], /* address */
    cust_balance[10], /* balance */
    cust_credit_limit[8]; /* credit limit */
    }dummy;


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

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

    int intcmp(const void *v1, const void *v2);



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

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


    void main()
    {
    /*CHANGED THIS BIT FROM A CHARACTER POINTER TO A UNION POINTER*/

    /*CHANGED IT AGAIN IT SHOULD BE A POINTER OF UNION RECORDS TYPE*/
    union records *s;

    int size_of_file,
    i,
    r,
    d,
    c,
    diff_cust,
    loop;

    char *ptr,
    prev_cust[6];



    /* struct create_rec dummy = {'\0',
    "\0",
    "\0",
    "\0",
    "\0",
    "\0" }; */

    i=r=d=c=0;

    /* open file for output */

    if(( sorted_ptr = fopen("A:\SORTED.dat","wb")) == NULL)

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

    if(( valid_ptr = fopen("A:\ZENCVF.DAT","rb")) == NULL)

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

    /* calculate size of file */
    /* find end of input file */

    if(fseek(valid_ptr, sizeof(transaction), SEEK_END)!=0 )
    {
    printf("\nSeek Error.");
    exit(1);
    }


    size_of_file = (ftell(valid_ptr) / sizeof(transaction));

    s=(union records *) malloc (size_of_file);
    rewind(valid_ptr);


    /* write union to memory */
    /* while(!feof(valid_ptr)) */




    /*REMOVED AMPERSAND FROM IN FRONT OF S*/
    fread(s, sizeof(transaction)* size_of_file, 1, valid_ptr);


    Pause();


    /* end of file */
    printf("\n finished reading in file ");
    Pause();
    printf("\n %s s",s); /* doesn't work displays nothing*/

    /* printf("\n did rewind too %s", s);
    Pause();*/

    /* read all data into s now time to sort */

    /* sort into ascending order */

    printf("\n rec number %d", size_of_file);
    /* size_of_file is really number of records */

    qsort(s, size_of_file, sizeof(transaction), intcmp);
    printf("\n finished sort %d", sizeof(transaction));
    printf("\n s after sort %s",s);
    Pause();
    ptr = &s;







    /*THE POINTER IS NOT POINTING TO A FILE BUT TO A DYNAMIC ARRAY,POINTER NOT BEING INCREMENTED TO NEXT RECORD ANYWAY.
    PERHAPS NEED TO LOOP THRU' THE ARRAY*/
    printf("\n I'm in the stats function");


    Pause();

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

    {


    printf("\n ptr %p", ptr); /* don't work */
    /* prints out <null>???*/

    switch(*ptr)
    {
    case 'I': i=i+1;
    break;
    case 'R': r=r+1;
    break;
    case 'D': d=d+1;
    break;
    case 'C': c=c+1;
    break;
    }
    printf("\n i%d %d %d %d", i,r,d,c);
    printf("\n 1%c 2%s ", transaction.ir.type, transaction.ir.cust_code);
    Pause();
    (*ptr)++ ;


    }
    if( strcmp( transaction.ir.cust_code, prev_cust) != 0)
    {
    diff_cust +=1;
    }

    strcpy( prev_cust, transaction.ir.cust_code);

    Pause();
    /* end of file */


    Pause();
    /*rewind(valid_ptr);*/



    printf("\ got to before while for fwrite");



    fwrite(s, sizeof(transaction)* size_of_file,1, sorted_ptr);





    printf("\n wrote to file");


    fclose(sorted_ptr);
    fclose(valid_ptr);
    fclose(fp_ptr);
    fclose(prn_ptr);

    }

    int intcmp(const void *v1, const void *v2)
    /* the sort bit */
    {



    /*return ((*(char *)v1) - (*(char *)v2));*/
    /*CHANGED THIS BIT TO USE THE UNION TYPE NAME (records) INSTEAD OF THE DEFINED NAME (transaction)*/
    return (strcmp(((union records *)v1)->ir.cust_code,((union records *)v2)->ir.cust_code));

    }



    char Pause(void)
    {
    char c;
    printf("\nPress Enter to continue.");
    while((c=getchar()) != '\n')
    {
    return c;
    }
    return(1);
    }

  2. #2
    Registered User
    Join Date
    Nov 2001
    Posts
    18
    Dear Andy

    Assuming you have read the records in from the file, placed them into malloc allocated memory, then sorted them and repositioned the pointer to the beginning of malloc memory, you should proceed as follows, further assuming your pointer to malloc is called move_ptr

    Put your self into a loop of the number of records, then test the first record like so

    if(move_ptr->create.type == 'C')
    {
    fprintf(PTR_PTN," %c %s %s %s %s %s\n",
    move_ptr->create.type, move_ptr->create.code,
    move_ptr->create.name, move_ptr->create.address,
    move_ptr->create.bal, move_ptr->create.limit);
    }
    else

    What is useful to know it the first line
    ?if(move_ptr->cust.type == 'C')?
    can be used to test each and every record, since they all have the same field in the same position in each of the structures.
    Although you are naming the structure ?create? you could be saying any of the structures in the union. The coding is in effect saying ?Is the first field (which is always ?type? in all of the three structures) a C. If it is a C then I will access the fields via the structure for C.

    After each record in malloc has been accessed the pointer needs to be incremented so that you move to the beginning of the next union in malloc.

    I have dealt with this question on previous occasions and am experienced with the group of four programmes that it relates to. You can contact me off board if you wish (stephanos@writeme.com)


    Stephanos

  3. #3
    Registered User
    Join Date
    Sep 2001
    Posts
    4
    Thanks Stephanos,
    I made 'S' the start of the malloc area, so if I make

    move_ptr = s;

    then that should reposition it so I can then loop through the records.

    I hadn't thought of using the move_ptr -> etc, not too familiar with structures and unions.

    So its not just me who got stuck with these 4 programs then? (Well I'm only up to the second one).

    Many Thanks,

    Andy.

    P.S. You may be hearing from me again..

  4. #4
    Sayeh
    Guest
    It seems as if you are trying to treat the structure/union as a string... you can't. A struct/union is a physical aggragate variable in RAM.

    Also, although it will work (using 'switch(*ptr)'-- I'm not sure you really understand what this is doing...

    If I say a = *ptr; Sure, it will get the first byte out of that location, but normally, you don't access a structure this way, unless you're peeking at a nested structure (which you aren't doing). You should be saying:

    switch(ptr->type)

    enjoy

  5. #5
    Registered User
    Join Date
    Sep 2001
    Posts
    4
    I've just tried changing the 'switch' line but I get an error from the compiler. (pointer required on left side of arrow (*-> or ->*))

    But I was trying to treat it like you said( was guessing).

    Thanks

    Andy.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. sizeof union question
    By noops in forum C Programming
    Replies: 13
    Last Post: 06-06-2008, 12:56 PM
  2. Replies: 16
    Last Post: 10-29-2006, 05:04 AM
  3. "generic" union or something
    By Raven Arkadon in forum C++ Programming
    Replies: 2
    Last Post: 12-05-2005, 09:55 PM
  4. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 07:39 AM
  5. sorting union of structures with q sort
    By colw in forum C Programming
    Replies: 6
    Last Post: 04-09-2002, 10:51 AM

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