Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations strongm on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

qsort and unions

Status
Not open for further replies.

AndyDoyle

Programmer
Jan 31, 2003
5
US
I have a binary file that contains vaious length records that are held in structures.
Here is a sample of the file :-
I10014 010006 0002 I10006 010006 0001 I10006 049301 0009 I10022 012807 0008 I10049 012106 0099 I10065 054402 0100 C10081 COVER SYSTEMS LTD ALBOY RD;KINVER;SOUTH STAFFS; ; 000234500 0010000 I10103 020109 0507 I13005 030309 0007 I14001 013404 0044 I20001 022403 0202 I22225 016004 0032 I11703 035408 0090 I11703 054402 0300 R1986X 012106 0200 I19984 010103 0085 I1518X 012505 0002 I1518X 014001 0002 D31003
I19186 013307 0090 I19321 021504 0088 I10006 035009 0009 I19321 03530X 0092 I19321 041408 0077 I13323 05200X 0250 I1454X 011002 0066 I1454X 014206 9999 D11525 I10189 010405 0010

And here are the structures in which the records are held:-

struct IRRecord{
char RecordType;
char CustCode[6];
char PartNo[7];
char Qty[5];
};

struct DRecord{
char RecordType;
char CustCode[6];
};

struct CRecord{
char RecordType;
char CustCode[6];
char CustName[21];
char CustAddress[61];
char CustBal[10];
char CreditLimit[8];
};

I need to sort the file into customer code order! I am using malloc and qsort.

Firstly, I declare my union:-

union Recs{
struct IRRecord IRStr;
struct DRecord DStr;
struct CRecord CStr;
}Allrecs;

Then some code here......
Then...

total_recs = ftell(d_ptr) / sizeof(union Recs);
fseek(d_ptr,0l,SEEK_SET);

printf("%d",total_recs);

/*Allocate portion of memory that is to be used in sort*/
if ((memptr = (union Recs*)malloc(sizeof(union Recs)* (int)total_recs))==NULL)
fprintf(stdout,"Cannot allocate buffer");

memptr2 = memptr;

/*Read file into memory*/
if (fread(memptr,sizeof(union Recs),(int)total_recs,d_ptr)!= (int)total_recs)
fprintf(stdout,"\nCannot read file");

/*reset pointer to start of allocated file*/
memptr = memptr2;

/*now sort file*/
qsort(memptr,(int)total_recs,sizeof(union Recs),compare);

/*reset pointer again*/
memptr = memptr2;

/*now read back to file - sorted*/
if (fwrite(memptr,sizeof (union Recs),(int)total_recs,s_ptr)!=(int)total_recs)
fprintf(stdout,"\nError writing to sorted data file");

/*reset pointer again*/
memptr = memptr2;

/*Now produce printout with totals on*/

fclose(prn_ptr);
fclose(d_ptr);
fclose(s_ptr);
free(memptr);

This is my qsort function...

int compare(const void *a,const void *b)
{
return strcmp(((union Recs *)a)->CStr.CustCode,((union Recs *)b)->CStr.CustCode);
}

Can anyone see where the problem is as its not quite right?

If you need more info let me know!
Cheers.
 
1) Since you are writing variable length records to the disk, the number of records is not
Code:
total_recs = ftell(d_ptr) / sizeof(union Recs);
It is between ftell(d_ptr)/sizeof(struct CRecord) and ftell(d_ptr)/sizeof(struct DRecord). Better to use CRecord since it is the smaller of the two.

2) Since the records are variable length, they cannot be read in 1 fread. You have to read them individually and assign them accordingly and compute the new value of total_recs before passing it into qsort.

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top