@LB I shall study the newer language idioms more. Problem is, the language (pre c++11) was
already so capable that one seems to rarely need other tools (though I admit that not knowing of the tools may influence this perception).
For fun (That's what we're here for right?) I thought I'd try creating a list with nodes in which a reference to the next node is used rather than a pointer. I got it to work! The key was creating a self referential node 1st for use as the list tail, then push_back() on this tail node.
Note the rather questionable ctor for the refNode class which creates self-referential nodes.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
|
struct refNode
{
int data;
refNode& rNext;
refNode(int Data): data(Data), rNext(*this) {}// self referential node to be used as list tail
refNode(int Data, refNode& rRN ): data(Data), rNext(rRN) {}// "normal" ctor. reference is to next node inj list
};
// 2 functions for creating and displaying a refList
refNode& createList( std::istream& is, int& size );
void printList( refNode& rRN );
int main()
{
std::ifstream fin("test.txt");
if( !fin )// exception handling at its finest!!
{
cout << "bad istream \n";
return 1;
}
int listSize = 0;
refNode& rList = createList( fin, listSize );
printList( rList );
cout << endl;
return 0;
}
refNode& createList( std::istream& is, int& size )
{
int temp;
refNode* pPrev = 0;// sorry about the pointer! I ouldn't think of how to avoid using one here.
if( is >> temp )
{
// refNode tail( temp );// oops. What was I thinking?
// pPrev = &tail;
pPrev = new refNode( temp );// correct!
size = 1;
while( is >> temp )
{
pPrev = new refNode( temp, *pPrev );
++size;
}
}
if( !pPrev ) cerr << "null ptr returning from createList() \n";// More fine exception handling (Let it crash, it will tell us why)
return *pPrev;
}
void printList( refNode& rRN )
{
refNode* pCurr = &rRN;// WARNING! pointer in use!
while( pCurr != &(pCurr->rNext) )// require that node is not referencing self
{
cout << pCurr->data << " ";
pCurr = &(pCurr->rNext);// point to next refNode
}
cout << " tail = " <<pCurr->data;
}
|
When I supply a test.txt with contents = 10 21 33 45
I get this output:
Indicating it works as expected.
I'm having trouble getting a destroyList() to work right at the moment though...
EDIT: Found the problem! Lines 38, 39 are very wrong (local refNode as list tail)!
New line 40 corrects this.
This destroyList() appears to work:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
int destroyList( refNode& rRN )
{
refNode* pCurr = &rRN;
int count = 1;// CANNOT be 0
while( pCurr != &(pCurr->rNext) )// require that node is not referencing self
{
cerr << pCurr->data << " ";
refNode* pTemp = pCurr;// will be deleting this refNode
pCurr = &(pCurr->rNext);// point to next refNode
delete pTemp;
++count;
}
// the last, self referential one
cerr << pCurr->data << " ";
delete pCurr;// this one was counted initially
return count;
}
|
Calling this adds the following to the program output:
45 33 21 10 releasing 4 refNodes from list |
EDIT2: A push_front() function is easy enough. Assuming a 1st node already exists:
1 2 3 4 5
|
refNode& push_front( refNode& rHead, int Data, int& size )
{
++size;
return *(new refNode( Data, rHead ) );
}
|
However, the list in the main() can't be added to. That would require re assigning rList. So, once again I resort to pointers:
1 2 3 4 5 6 7 8 9 10 11
|
int listSize = 0;
refNode* pList = &createList( fin, listSize );
printList( *pList ); cout << endl;// 45 33 21 10
// add one more refNode to the list
pList = &push_front( *pList, 99, listSize );// this line is why a pointer is needed.
printList( *pList ); cout << endl;// 99 45 33 21 10
cout << "releasing " << destroyList( *pList ) << " refNodes from list \n";
|
Output now is:
45 33 21 tail = 10
99 45 33 21 tail = 10
99 45 33 21 10 releasing 5 refNodes from list |
OK. I promise to stop now.
errr... except to note that sizeof( refNode ) = 4 + sizeof( int ), so rNext is costing 4 bytes.