Listing 7 This code provides a solution that avoids the trade-off between the limited usability of a single-purpose function and the complexity of a multi-purpose function.

//arts.c ...ref CUJ April 1992 page 108, the Q&A column
//by Ken Pugh

//select the file to be created
//
#define       FILE_FORMAT         "ARTS1.FF"
//
//nothing else in this file needs to change!

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

//create structure
#define ff(name,size)   char name[size+NUL_TERMINATED];
struct rec{
#include FILE_FORMAT
};

//initialize sizes array
#define ff(name,size) size + NUL_TERMINATED,
static int field sizes[] = {
#include FILE_FORMAT
};

#define FIELDCOUNT  (sizeof(field_sizes)/sizeof(int))

#define TRUE 1
#define FALSE 0

//build custom print function
#define ff(name, size) printf("%*s: %.*s\n", 20, #name,
size+NUL_TERMINATED, record->name );
void art_print(struct rec* record)
{
printf("\n\n");
#include FILE_FORMAT
printf("\n\nPress key...");
getch();
}

//set arbitrary limit to record creation
#define RECS 5
//
//generate some data
void createfile(void)
{
int r, f;
char buf[100];
FILE *fp = fopen(FILENAME,"w");
if(!fp){
 printf("Open failed\n");
 exit(1);
 }
for(r=0; r<RECS; r++){
 for(f=0; f<FIELDCOUNT; f++){
   memset(buf,'A'+f+r,field_sizes[f]);
   if(NUL_TERMINATED)
     buf[field_sizes[f]-1] = 0;
   fwrite(&buf, sizeof(char), field_sizes[f], fp);
   }
 }
fclose(fp);
}

void stats(void){
printf("\n\nStats for file '%s':\n\n", FILENAME);
printf("\tStructure size %d\n", sizeof(struct rec) );
printf("\tThere are %d fields\n", FIELDCOUNT);
printf("\tThe fields are %snul-terminated\n",
 (NUL_TERMINATED?"":"not " ));
}

void main(void){
struct rec record;
FILE *fp;

createfile();
stats();
fp = fopen(FILENAME,"r");
if(fp){
 while(fread(&record, sizeof(record),1, fp))
   art_print(&record);
 fclose(fp);
 }
}

/* End of File */