/* mallocex.c:
 * stores height chart using dynamic memory allocation and displays it
 * Richard Kay		 Last Changed 10 Oct 2008 */

#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h> /* includes prototype for malloc() */

#define HDATA "heights.txt"

typedef struct {
	 char name[30];	/* persons name */
	 float height;  /* persons height */
} HRECORD; /* height record data type */

int countrecs(FILE*); /* counts records in file */
void storedata(FILE *fp,HRECORD harray[],int rows); /* stores in dynamic array */
void displaydata(HRECORD harray[],int rows); /* displays data in array */

int main(void){
	 int numrecs;
	 char nam[30],buff[BUFSIZ];
	 float high;
	 FILE *in;
	 HRECORD *hrecsp; /* will point to start of dynamic anonymous array */
	 numrecs=countrecs(in); /* count number of records in input file */
	 printf("there are %d records in the %s file\n",numrecs,HDATA);

	/* Assign a pointer hrecsp to the start of a block of memory 
	* taken from the memory heap.
	* The pointer is to be used to access	a variable size 
	* height records array. malloc() takes a parameter for the size 
	* of a block of memory to be allocated and returns a void pointer 
	* to the start of this block. This void pointer is then cast to a 
	* pointer of the appropriate type for storing the data.	malloc() 
	* returns NULL if 0 bytes of memory are requested or sufficient 
	* memory to meet the request is unavailable */

	 if((hrecsp=(HRECORD*)malloc(sizeof(HRECORD)*numrecs)) == NULL){
		 fprintf(stderr,"insufficient memory available or no height data\n");
		 return 1; /* exit program now */
	 }
	 storedata(in,hrecsp,numrecs); /* store data in dynamic array */
	 displaydata(hrecsp,numrecs);	/* display data in dynamic array */

	 free(hrecsp); /* free the memory allocated */
	 getch();
	 return 0;
} /* end of main() */

int countrecs(FILE *fp){ 
	/* counts number of records in file but doesn't store them */
	int rows=0;
	char buff[BUFSIZ]; /* standard buffer size is defined in stdio.h */
	fp=fopen(HDATA,"rt");
	while(fgets(buff,BUFSIZ,fp) != NULL) /* what if record longer than buff ? */
	rows++;	 /* incremented for each row in file */
	fclose(fp); /* close it so when we read data we start from beginning again */
	return rows;
}

void storedata(FILE *fp,HRECORD harray[],int rows){
	/* stores data in dynamically allocated array */
	int i;
	char buff[BUFSIZ],nam[30];
	float high;
	fp=fopen(HDATA,"rt"); /* open heights data file again in read mode */
	/* read data into harray */
	for(i=0;i<rows;i++){
		fgets(buff,BUFSIZ,fp);	/* read next record from file */
		sscanf(buff,"%s%f",nam,&high); /* read name and height from buffer */
		strcpy((harray+i)->name,nam); /* assign element i of array member name */
		(harray+i)->height=high; /* assign element i of array member height */
	}
	fclose(fp);
} /* end of storedata() */

void displaydata(HRECORD harray[],int rows){
	/* displays data in dynamically allocated array */
	int i;
	for(i=0;i<rows;i++){
		if(i%20==0){ /* throw a set of headings if needed */
			if(i>0){ /* pause and clear screen unless first page */
				printf("press a key to continue\n");
				getch();
				clrscr();
			}
			printf("name\t\theight\n"); 
				/* Print headings. Note us of \t tabs to*/
			printf("====\t\t======\n"); /* line up columns */
		}
		/* display data for height record				 */
		printf("%s\t\t%f\n",(harray+i)->name,(harray+i)->height);
	 } /* end for */
} /* end of displaydata() */