The simplest implementation is to store all list records in the dynamic memory. The declarations required are illustrated below for the example of the stock portfolio. For storage in dynamic memory, the records of a list are defined as usual, and an additional field is added to contain the link field pointer. Since it will point to a successor record stored in dynamic memory, it must be defined as a pointer. In this case, the null value for a pointer is always given by the value , with having the value 0. Variables of type listpointer will contain pointers to records of type stockrecord.
The following complete program reads in and creates a list of stockrecords as in Example 3.5 and, in addition, prints out the information fields of the list records. Both the creation and printing portion of the code are appropriately modified versions of traverse. The initialize and process functions of Example 3.5 are used in the creation portion, but process has been given the name addrecord. The program treats the list as a data abstraction. The data abstraction list, with its allowed operations?/FONT>next, setlink, setinfo, avail, anotherrecord, getnextrecord, and printrecord, appear together in the program.
Typical input to the program is shown in Table 3.2.
The program that follows reads in the records of a list, creates the list, and prints the records in the list.
#define MAXSIZE 5
#define NULL 0
#define SENTINEL -1
typedef struct
{
int month;
int day;
int year;
}date;
typedef struct
{
char name[MAXSIZE];
int shares;
float value;
date datebought;
}infofield;
typedef struct listrecord
{
infofield info;
struct listrecord *link;
}stockrecord,*listpointer;
Table 3.2 Sample Input
Explanation Actual Input
--------------------------------------------------------------------------
Record 1 Number of shares 100
Stock name abc
Price of a share 56.25
Month day year of purchase 1 23 1978
Record 2 Number of shares 50
Stock name wxyz
Price of a share 5.50
Month day year of purchase 11 4 1986
.
.
.
Terminal record Sentinel (where next number of shares would -1
otherwise appear)
#define MAXSIZE 5
#define NULL 0
#define SENTINEL -1
typedef struct
{
int month;
int day;
int year;
}date;
typedef struct
{
char name[MAXSIZE];
int share;
float value;
date datebought;
}infofield;
typedef struct listrecord
{
infofield info;
struct listrecord *link;
}stockrecord,*listpointer;
listpointer next(pointer)
/* Returns a copy of the
link field in the record
pointed to by pointer
*/
listpointer pointer;
{
return(pointer->link);
}
listpointer setnull()
/* Returns a null pointer */
{
return(NULL);
}
setlink(pointer1,pointer2)
/* Sets the link field of the
record pointed to by pointer1
to the contents of pointer2
*/
listpointer pointer1,pointer2;
{
pointer1->link = pointer2;
}
setinfo(pointer1,pointer2)
/* Sets the infofield of the record
pointed to by pointer1 to the
infofield of the record
pointed to by pointer2
*/
listpointer pointer1,pointer2;
{
int i;
for(i=0;i<MAXSIZE;i++)
pointer1->info.name[i] = pointer2->
info.name[i];
pointer1->info.shares = pointer2->
info.shares;
pointer1->info.value = pointer2->info.value;
pointer1->info.datebought.month = pointer2->
info.datebought.month;
pointer1->info.datebought.day = pointer2->
info.datebought.day;
pointer1->info.datebought.year = pointer2->
info.datebought.year;
}
listpointer avail()
/* Returns a pointer to storage
allocated for a record of type
stockrecord
*/
{
listpointer malloc();
return(malloc(sizeof(stockrecord)));
}
anotherrecord(recordpointer)
/* Returns true if there is
another record
*/
listpointer recordpointer;
{
listpointer setnull();
return(recordpointer != setnull());
}
listpointer getnextrecord()
/* Inputs the data for the new
record and returns a pointer
to a record containing the data
in its infofield, or, if there
are no new records,returns
a null pointer
*/
{
listpoiner setnull();
static stockrecord nextrecord;
printf("Enter number of shares\n");
scanf("%d",&(nextrecord.info.shares));
if(nextrecord.info.shares != SENTINEL)
{
printf(" Enter the stock name - less than
%d characters\n",MAXSIZE);
scanf("%s",nextrecord.info.name);
printf(" Enter the price of one share of
the stock\n");
scanf("%f",&(nextrecord.info.value));
printf(" Enter the month day year of the
stock purchase\n");
scanf("%d %d %d",&(nextrecord.info.
datebought.month),
&(nextrecord.info.datebought.day),
&(nextrecord.info.datebought.year));
return(&nextrecord);
}
else
return(setnull());
}
printrecord(recordpointer)
/* Prints the contents of the infofield
of the record pointed to by recordpointer
*/
listpointer recordpointer;
{
printf(" The stock is %s\n",
recordpointer->info.name);
printf(" The number of shares is %d\n",
recordpointer->info.shares);
printf(" The value of a share is %f\n",
recordpointer->info.value);
printf(" The date of purchase is %d %d %d\n\n",
recordpointer->info.datebought.month,
recordpointer->info.datebought.day,
recordpointer->info.datebought.year);
}
#include <stdio.h>
#define TRUE 1
#define FALSE 0
main()
/* Inputs a series of stockrecords,
creates a list of the records, and
prints the contents of each list
record's infofield
*/
{
listpointer stocks,recordpointer,next();
int done;
initialize(&stocks);
recordpointer = stocks;
done = FALSE;
while(!done&&anotherrecord(recordpointer))
{
addrecord(&stocks,recordpointer,&done);
recordpointer = next(recordpointer);
}
recordpointer=stocks;
while(anotherrecord(recordpointer))
{
printrecord(recordpointer);
recordpointer = next(recordpointer);
}
}
initialize(plistname)
/* Allocates storage for the first record
and sets listname to point to it
*/
listpointer *plistname;
{
listpointer avail();
*plistname = avail();
}
addrecord(plistname,recordpointer,pdone)
/* Fills in the current record's data, and allocates
storage for the next record and adds it to the
list. If there is no data for the current record
it sets the link field of the last list record
to null, or the list head to null, and done to
true.
*/
listpointer *plistname,recordpointer;
int *pdone;
{
static listpointer predecessor;
listpointer setnull(),avail(),getnextrecord(),
pointer;
pointer =getnextrecord();
if(pointer != setnull())
{
setinfo(recordpointer,pointer);
setlink(recordpointer,avail());
predecessor = recordpointer;
}
else if(*plistname != recordpointer)
{
setlink(predecessor,setnull());
*pdone = TRUE;
}
else
{
*plistname = setnull();
*pdone = TRUE;
}
}