increment index pointer to point to next record

I have a program that takes in a .dat file containing 10 records with the following format:

acctNum, firstName, lastName, balance, lastPayment

the program opens the file with the records, sorts them in DESCENDING order of balance and writes the data to an index file.

I am trying to display the contents of the file for testing purposes but I am not sure how to make the program look at the next contact in the array.

can anyone suggest any ideas?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
  #define _CRT_SECURE_NO_WARNINGS

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

#define MAX_ARGS 3
#define APP_NAME "Week09Demo"
#define MAX_CONTACTS 10
typedef enum { ACCT_NUM, FIRST, LAST, BAL, LPAY } IndexKey;

struct clientData
{
	int acctNum;
	char lastName[15];
	char firstName[10];
	double balance;
	double lastPayAmt;
};

typedef union
{
	int		num;
	char	first[30];
	char	last[30];
	double	bal;
	double	lpay;
} KeyType;

typedef struct
{
	KeyType		key;
	long		filePos;
} IndexRecord;

typedef struct
{
	IndexKey	idxKey;
	char		appName[20];
	int			recCount;
} IndexHeader;


//struct clientData arrayOfContacts[10];
typedef struct clientData ClientData;
struct clientData clientDataArray[MAX_CONTACTS];
long fileSize(FILE *input);
int descending(const void *left, const void *right);

int main()
{
	// create clientData with default data
	ClientData	client = { 0, "", "", 0.0, 0.0 };
	FILE		*fpIndexBal;
	FILE		*tester; // file pointer
	IndexKey	indexKey;
	IndexHeader	indexHeader;
	IndexRecord	*indexRecords;
	IndexRecord idxTemp;

	int		indexRecordCount;
	long	filePos;
	int		readCount;
	int		writeCount;
	int		dataRecordCount;
	int		i = 0; // incrementer
	int		numOfContacts = 0;

	indexKey = BAL;
	/*
	// if there isnt 3 args, then exit program
	if (argc != MAX_ARGS) {
		printf("Incorrect number of arguments entered.");
		exit(EXIT_SUCCESS);
	}
	*/
	// fopen opens the file; exits if file cannot be opened
	if ((tester = fopen("accounts.dat", "rb")) == NULL) {
		printf("File could not be opened.\n");
	}

	// open index file for writing
	if ((fpIndexBal = fopen("accounts.idx", "wb")) == NULL)
	{
		printf("ERROR - can not open/create index file.\n");
		return 1;
	}

	dataRecordCount = fileSize(tester) / sizeof(ClientData);
	printf("Data record count: %d", dataRecordCount);

	indexRecords = (IndexRecord *)calloc(dataRecordCount, sizeof(IndexRecord));

	// populate index header record
	indexHeader.idxKey = indexKey;
	strcpy(indexHeader.appName, APP_NAME);
	indexHeader.recCount = dataRecordCount;

	rewind(tester);
	filePos = ftell(tester);
	indexRecordCount = 0;

	// Read first data record
	readCount = fread(&client, sizeof(ClientData), 1, tester);

	// Process all data records
	while (!feof(tester) && (readCount == 1))
	{
		// populate index record from data record
		indexRecords[indexRecordCount].key.bal = client.balance;
		indexRecords[indexRecordCount].filePos = filePos;

		// added a record - increment to next element
		indexRecordCount++;

		// store file pos before next read advances it
		filePos = ftell(tester);

		// read next record
		readCount = fread(&client, sizeof(ClientData), 1, tester);
		
	}

	// Sort array of index records in memory
	//  based on return value of compare function
	qsort(indexRecords, indexRecordCount, sizeof(IndexRecord), descending);

	printf("Index Header Size: %d\nIndex Record Size: %d\n\n"
		, sizeof(IndexHeader), sizeof(IndexRecord));

	printf("Creating Index File\n");

	// write Index Header to file
	writeCount = fwrite(&indexHeader, sizeof(IndexHeader), 1, fpIndexBal);

	// Write Index Records to file
	writeCount = fwrite(indexRecords, sizeof(IndexRecord), indexRecordCount, fpIndexBal);

	printf("%d Records Processed\n", writeCount);

	printf("\nFileSize: %d\n\n", fileSize(fpIndexBal));

	// release this memory and set it free
	free(indexRecords);

	// prints column headers
	printf("%-15s%-15s%-15s%-15s%-15s\n"
		, "Account #"
		, "First Name"
		, "Last Name"
		, "Balance"
		, "Last Payment");


	for (i = 0; i < MAX_CONTACTS; i++) {
		// if file pointer is not empty, read content
		if (fpIndexBal != NULL) {
			fread(&client, sizeof(ClientData), 1, fpIndexBal);

		}
		// prints data from file // THIS IS THE PROBLEM HERE
		printf("%-15d%-15s%-15s%7.2lf%15.2lf\n"
			, client.acctNum
			, client.firstName
			, client.lastName
			, client.balance
			, client.lastPayAmt);
		
	}
	// close files and go home
	fclose(tester);
	fclose(fpIndexBal);
	_getch();
	return 0;
}

long fileSize(FILE *input)
{
	long orgPos;
	long startPos;
	long endPos;

	orgPos = ftell(input);          // save orig file position
	rewind(input);
	startPos = ftell(input);
	fseek(input, 0, SEEK_END);
	endPos = ftell(input);
	fseek(input, orgPos, SEEK_SET); // restore orig position

	return(endPos - startPos);
}

int descending(const void *left, const void *right)
{
	int retVal = 0;
	int *pLeft = (int*)left;
	int *pRight = (int*)right;

	if (*pLeft > *pRight)
	{
		retVal = 1;
	}
	else if (*pLeft < *pRight)
	{
		retVal = -1;
	}
	// printf("desc called\n");
	return retVal * -1; // -1 for descending
}
I don't see why you need MAX_CONTACTS, as the program only holds one data record at a time in memory.

If you fail to open the index file, you fail to close the data file.

Use the sorted index to seek/read/print each data record.
The last part looks a bit like the index file and the data file are mixed up.

Here fpIndexBal is the index file, but the fread is attempting to read client data which is in the other file (tester).
 
    fread(&client, sizeof(ClientData), 1, fpIndexBal);


What I think needs to happen is this.
After creating the index file, close the index file.

Then start all over again, open the index file for reading.
Read the index header record.

Then use a loop to read each index record from the file.
For each index record read, reposition the data file prior to reading.
1
2
        // reposition data file.
        fseek(tester, idxTemp.filePos, SEEK_SET);  

Then read the ClientData.
Print the details.
Last edited on
thank you guys for your help, I fixed everything and it works now:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
#define _CRT_SECURE_NO_WARNINGS

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

#define MAX_ARGS 3
#define APP_NAME "Assignment08Part1"
#define MAX_CONTACTS 10
typedef enum { ACCT_NUM, FIRST, LAST, BAL, LPAY } IndexKey;

struct clientData
{
	int acctNum;
	char lastName[15];
	char firstName[10];
	double balance;
	double lastPayAmt;
};

typedef union
{
	int		num;
	char	first[30];
	char	last[30];
	double	bal;
	double	lpay;
} KeyType;

typedef struct
{
	KeyType		key;
	long		filePos;
} IndexRecord;

typedef struct
{
	IndexKey	idxKey;
	char		appName[20];
	int			recCount;
} IndexHeader;


//struct clientData arrayOfContacts[10];
typedef struct clientData ClientData;
struct clientData clientDataArray[MAX_CONTACTS];
long fileSize(FILE *input);
int descending(const void *left, const void *right);

int main(int argc, char *argv)
{
	// create clientData with default data
	ClientData	client = { 0, "", "", 0.0, 0.0 };
	ClientData	client2 = { 0, "", "", 0.0, 0.0 };
	FILE		*fpIndexBal;
	FILE		*tester; // file pointer
	IndexKey	indexKey;
	IndexHeader	indexHeader;
	IndexRecord	*indexRecords;
	IndexRecord idxTemp;
	IndexHeader idxHeader;

	int		indexRecordCount;
	long	filePos;
	int		readCount;
	int		writeCount;
	int		dataRecordCount;
	int		i = 0; // incrementer
	int		numOfContacts = 0;
	int		b = 0;
	int		recCount;

	indexKey = BAL;
	
	// if there isnt 3 args, then exit program
	if (argc != MAX_ARGS) {
		printf("Incorrect number of arguments entered.");
		exit(EXIT_SUCCESS);
	}
	
	// fopen opens the file; exits if file cannot be opened
	if ((tester = fopen("accounts.dat", "rb")) == NULL) {
		printf("File could not be opened.\n");
	}

	// open index file for writing
	if ((fpIndexBal = fopen("accounts.idx", "wb")) == NULL)
	{
		printf("ERROR - can not open/create index file.\n");
		return 1;
	}

	dataRecordCount = fileSize(tester) / sizeof(ClientData);
	printf("Data record count: %d", dataRecordCount);

	indexRecords = (IndexRecord *)calloc(dataRecordCount, sizeof(IndexRecord));

	// populate index header record
	indexHeader.idxKey = indexKey;
	strcpy(indexHeader.appName, APP_NAME);
	indexHeader.recCount = dataRecordCount;

	rewind(tester);
	filePos = ftell(tester);
	indexRecordCount = 0;

	// Read first data record
	readCount = fread(&client, sizeof(ClientData), 1, tester);

	// Process all data records
	while (!feof(tester) && (readCount == 1))
	{
		// populate index record from data record
		indexRecords[indexRecordCount].key.bal = client.balance;
		indexRecords[indexRecordCount].filePos = filePos;

		// added a record - increment to next element
		indexRecordCount++;

		// store file pos before next read advances it
		filePos = ftell(tester);

		// read next record
		readCount = fread(&client, sizeof(ClientData), 1, tester);
		
	}

	// Sort array of index records in memory
	//  based on return value of compare function
	qsort(indexRecords, indexRecordCount, sizeof(IndexRecord), descending);

	printf("Index Header Size: %d\nIndex Record Size: %d\n\n"
		, sizeof(IndexHeader), sizeof(IndexRecord));

	printf("Creating Index File\n");

	// write Index Header to file
	writeCount = fwrite(&indexHeader, sizeof(IndexHeader), 1, fpIndexBal);

	// Write Index Records to file
	writeCount = fwrite(indexRecords, sizeof(IndexRecord), indexRecordCount, fpIndexBal);

	printf("%d Records Processed\n", writeCount);

	printf("\nFileSize: %d\n\n", fileSize(fpIndexBal));

	// release this memory and set it free
	free(indexRecords);

	// close files
	//fclose(tester);
	fclose(fpIndexBal);


	// ------------------test reading index-------------------------


	// open index file for READING
	if ((fpIndexBal = fopen("accounts.idx", "rb")) == NULL)
	{
		printf("ERROR - can not open/create index file.\n");
		return 1;
	}

	// prints column headers
	printf("%-15s%-15s%-15s%-15s%-15s\n"
		, "Account #"
		, "First Name"
		, "Last Name"
		, "Balance"
		, "Last Payment");

	//rewind(fpIndexBal);
	recCount = fileSize(tester) / sizeof(ClientData);
	// read header record in index file
	readCount = fread(&idxHeader, sizeof(IndexHeader), 1, fpIndexBal);
	// read first index record
	readCount = fread(&idxTemp, sizeof(IndexRecord), 1, fpIndexBal);
	
	// continue processing all index records
	while ((!feof(fpIndexBal)) && (readCount == 1))
	{
		// seek record in data file based on file position
		//  stored in previously read index record
		if (fseek(tester, idxTemp.filePos, SEEK_SET) != 0)
		{
			printf("Seek Error\n");
			fclose(tester);
			fclose(fpIndexBal);
			return 1;
		}

		// read data record and output
		fread(&client2, sizeof(ClientData), 1, tester);

			printf("%-15d%-15s%-15s%-10.2lf%15.2lf\n"
				, client2.acctNum
				, client2.firstName
				, client2.lastName
				, client2.balance
				, client2.lastPayAmt);

			// read next index record
			readCount = fread(&idxTemp, sizeof(IndexRecord), 1, fpIndexBal);
			// reposition data file.
			fseek(tester, idxTemp.filePos, SEEK_CUR);
	}

	//open index file
	_getch();
	return 0;
}

long fileSize(FILE *input)
{
	long orgPos;
	long startPos;
	long endPos;

	orgPos = ftell(input);          // save orig file position
	rewind(input);
	startPos = ftell(input);
	fseek(input, 0, SEEK_END);
	endPos = ftell(input);
	fseek(input, orgPos, SEEK_SET); // restore orig position

	return(endPos - startPos);
}

int descending(const void *left, const void *right)
{
	int retVal = 0;
	IndexRecord *index1 = (IndexRecord*)left;
	IndexRecord *index2 = (IndexRecord*)right;

	if ((index1->key.bal) > (index2->key.bal))
	{
		retVal = 1;
	}
	else if ((index1->key.bal) < (index2->key.bal))
	{
		retVal = -1;
	}
	// printf("desc called\n");
	return retVal * -1; // -1 for descending
}
Last edited on
Topic archived. No new replies allowed.