alex said:
I've written this structure and allowed the user to initialise the
members in an array of this structure. I also want the program to
print to the screen whats in this array after its been initialised.
I've written the program below, but it doesn't do the last thing
properly...any ideas?
.... snip code ...
The following (incomplete) program may help. It separates
discrete actions, such as getting a record, storing a record,
printing a record. To use it you need ggets() - see the
annotation comment. You can now practice getting a number out of
a string, and finding out where it ends, both for floats and
integers. To do this I advise writing further functions getint
and getfloat. Make sure they detect errors. The standard
functions strtol and strtod will do all the hard work. The place
to insert those functions is ahead of getrecord. Note how #define
is used to set critical constants in one place.
If you use gcc the compilation and linking is done by:
gcc -c ldstruct.c
gcc -o ldstruct ldstruct.o ggets.o
assuming you have already compiled ggets (see comments) with:
gcc -c ggets.c
The main thing I am trying to put across is the breakup of
programs into small, easily definable, simple subroutines. You
should be able to see the whole routine in one editor screenful,
and it should be simple enough so you can easily see it does the
job. If it gets too long it is time to split it up into further
simple subroutines. In C, a subroutine is implemented by writing
a function. Using descriptive names helps readability.
------- File ldstruct.c --------
/* demo program to load, verify, print an array of struct */
/* Note how functions do one simple thing each */
/* Public domain, by C.B. Falconer */
#include <stdio.h>
#include <string.h> /* strcpy strlen */
#include <stdlib.h> /* free */
/* this, and ggets.c, is available at:
<
http://cbfalconer.home.att.net/download/ggets.zip> */
#include "ggets.h" /* simplifies i/o. Don't use gets() */
#define MAXNAME 20
/* Declare a four member structure type */
struct PayRecord {
int number;
char name[MAXNAME];
float rate;
int hours;
};
#define MAXSTRUCTS 10
/* persistent data */
static int usedslots; /* zeroed */
static struct PayRecord payroll[MAXSTRUCTS];
/* ---------------- */
/* Incomplete. Use strtol and strtod, then check length of
remaining line < MAXNAME after removing leading blanks.
return 1 for any failure. */
/* returns 0 for success, 1 for error, EOF for end of input */
static int getrecord(struct PayRecord *record)
{
char *ln, *nm;
int err;
if (err = ggets(&ln))
return EOF; /* no data or no memory */
else {
/* parse the fields into *record */
nm = ln;
record->number = 0; /* dummies for testing */
record->rate = 0.0;
record->hours = 40;
/* remove leading blanks */
while (' ' == *nm) nm++;
/* remainder of string is the name */
if (MAXNAME <= strlen(nm)) err = 1;
else {
strcpy(record->name, nm);
err = 0;
}
free(ln);
return err;
};
} /* getrecord */
/* ---------------- */
/* stuff record into the indexth slot of payroll */
static void saverecord(struct PayRecord record, int index)
{
payroll[index] = record;
} /* saverecord */
/* ---------------- */
/* dump a readable version of the record to f */
static void putrecord(struct PayRecord *record, FILE *f)
{
fprintf(f, "%d, %s, %f, %d\n",
record->number,
record->name,
record->rate,
record->hours);
} /* putrecord */
/* ---------------- */
/* The auxiliary functions getrecord, saverecord, and putrecord
do all the nitty gritty. main simply organizes them */
int main(void)
{
struct PayRecord current;
int i;
int inputerror;
puts("Enter lines in the following format. ^Z or ^D ends\n"
"(with at least one blank separating fields)\n"
" number rate hours name\n"
"EX: 2 12.50 40 Joe Q. Shmoo");
/* This organization, with a string entry last, */
/* makes parsing the fields fairly easy. */
/* puts() appends a final /n */
/* load until max or EOF signalled */
/* We test for max first to avoid overflows */
while ((usedslots < MAXSTRUCTS) &&
(EOF != (inputerror = getrecord(¤t)))) {
if (inputerror) fprintf(stderr, "Input error\n");
else {
saverecord(current, usedslots);
usedslots++;
}
}
printf("%d items entered.\n\n", usedslots);
/* dump the lot */
/* since we use stdout we don't need to open/close files */
if (0 == usedslots) printf("Storage empty\n");
else
for (i = 0; i < usedslots; i++) {
putrecord(&payroll
, stdout);
}
/* signal success, no file close needed */
return 0;
} /* main ldstruc */