|
|
|
The following code fragments show how a singly linked list can be
constructed and manipulated. The list consists of instances of an example
class, CItem, which form items on a stack implemented as a singly
linked list using the iSlink data member as the link object. In
this example, a CItem object can contain an item of text
implemented as an HBufC.
The class is declared as:
class CItem : public CBase
{
public :
static CItem* NewL(const TDesC& aText);
static CItem* NewLC(const TDesC& aText);
CItem();
virtual ~CItem();
const HBufC* GetText();
public :
static const TInt iOffset;
private :
void ConstructL(const TDesC& aText);
private :
TSglQueLink iSlink;
HBufC* iText;
friend class CStack;
};The CItem member functions are implemented as:
const TInt CItem::iOffset = _FOFF(CItem,iSlink);CItem* CItem::NewLC(const TDesC& aText)
{
CItem* self = new (ELeave) CItem();
CleanupStack::PushL(self);
self->ConstructL(aText);
return self;
}CItem* CItem::NewL(const TDesC& aText)
{
CItem* self = CItem::NewLC(aText);
CleanupStack::Pop();
return self;
}void CItem::ConstructL(const TDesC& aText)
{
iText = aText.AllocL();
}CItem::CItem()
{}CItem::~CItem()
{
delete iText;
}const HBufC* CItem::GetText()
{
return (iText);
}As part of the construction process, a CItem constructs
an HBufC of the correct length and copies the content of the
descriptor parameter into it.
The stack is implemented by an instance of the example class
CStack. This maintains the stack by adding CItem
objects onto the end of the list and removing them from the end of the list.
When removing them from the end of the list, a pointer to the removed
CItem object is returned.
In this example, the list header, iStack, and the
iterator, iStackIter, are declared as data members of the class
and are constructed when the CStack object is constructed. A C++
constructor must be supplied so that iStackIter can be
constructed. (TSglQueIter has no default constructor).
AddToStack() takes a CItem object and adds
it to the end of the singly linked list.
RemoveFromStack() takes the CItem object at
the end of the singly linked list, removes it from the list and returns a
pointer to it.
The CStack class is declared as:
class CStack : public CBase
{
public :
static CStack* NewL();
static CStack* NewLC();
CStack();
void Construct();
virtual ~CStack();
CItem* RemoveFromStack();
void AddToStack(CItem& anItem);
private :
TSglQue<CItem> iStack;
TSglQueIter<CItem> iStackIter;
};The CStack member functions are implemented as:
CStack* CStack::NewLC()
{
CStack* self = CStack::NewL();
CleanupStack::PushL(self);
return self;
}CStack* CStack::NewL()
{
CStack* self = new (ELeave) CStack;
return self;
}CStack::CStack()
: iStack(CItem::iOffset),iStackIter(iStack)
{}
The C++ constructor is needed so that the list header
(iStack) and the list iterator (iStackIter) can be
properly constructed.
Before destroying a CStack object, the list is
destroyed. This is achieved using the iterator (iStackIter). The
iterator pointer is set to point to each element in turn, removing that element
from the list before destroying it.
Once the iterator has reached the end of the list, the
operator++ returns NULL.
The destruction process is safe if the list is empty; the statement
iStackIter.SetToFirst() is harmless, the operator++
returns NULL and execution of the body of the while
loop never happens.
CStack::~CStack()
{
CItem* item;
iStackIter.SetToFirst();
while ((item = iStackIter++) != NULL)
{
iStack.Remove(*item);
delete item;
};
}
Adding an element to the stack simply involves adding the
CItem object to the end of the list.
void CStack::AddToStack(CItem& anItem)
{
iStack.AddLast(anItem);
}
The RemoveFromStack() function returns
NULL, if the list is empty, otherwise it just uses the
Last() member function to return a pointer to the last element in
the list before removing it.
CItem* CStack::RemoveFromStack()
{
CItem* lastitem;
if (iStack.IsEmpty())
return NULL;
lastitem = iStack.Last();
iStack.Remove(*lastitem);
return (lastitem);
}
Executing the code results in a singly linked list of
CItem objects each containing a pointer to an HBufC
descriptor each of which, in turn, contains the text “8”,
“89”, and so on through to “89ABCDEF”:
{
CStack* stack;
CItem* item;
TBuf<16> buffer;
TRAPD(leavecode,stack = CStack::NewL());
if (leavecode != KErrNone)
{
// Cannot create stack
return;
} for (TUint jj = 8; jj < 16; jj++)
{
buffer.AppendNumUC(jj,EHex);
TRAPD(leavecode,item = CItem::NewL(buffer));
if (leavecode != KErrNone)
{
// Cannot create item
delete stack;
return;
}
stack->AddToStack(*item);
}as the following shows:
The following code removes each CItem element from the
list, starting with the last and working through to the first until the list is
empty.
while ((item = stack->RemoveFromStack()) != NULL)
{
// item->GetText());can be used to access the text.
delete item;
}; delete stack;Note that unlike doubly linked lists, elements can only be added to the start or the end of a singly linked list. Elements cannot be added to the middle of the list.