3.6.1 Lists Stored in Dynamic Memory

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.

#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;

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.

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)

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.

>Comment

#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);

}

>Comment

#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();

>Comment

int done;

initialize(&stocks);

recordpointer = stocks;

done = FALSE;

while(!done&&anotherrecord(recordpointer))

{

>Comment

addrecord(&stocks,recordpointer,&done);

recordpointer = next(recordpointer);

}

>Comment

recordpointer=stocks;

while(anotherrecord(recordpointer))

{

>Comment

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())

{

>Comment

setinfo(recordpointer,pointer);

setlink(recordpointer,avail());

predecessor = recordpointer;

}

else if(*plistname != recordpointer)

{

>Comment

setlink(predecessor,setnull());

*pdone = TRUE;

}

else

{

>Comment

*plistname = setnull();

*pdone = TRUE;

}

}