Google Answers Logo
View Question
 
Q: C++ Correction ( Answered 5 out of 5 stars,   1 Comment )
Question  
Subject: C++ Correction
Category: Computers > Programming
Asked by: martim07-ga
List Price: $40.00
Posted: 08 Mar 2003 10:53 PST
Expires: 07 Apr 2003 11:53 PDT
Question ID: 173530
This is a C++ problem that I have tried to complete, but there are
many areas that I'm not comfortable with. Please troubleshoot the
functions. I will be as detailed as possible.
 
The goal is to implement and test a class called List that uses a
linked list toolkit to create and manipulate a linked list. The
definitions are listed below. I will also show the linked list toolkit
that the implementation file must link to as well as what I have come
up with for the function implementations.

// FILE: list3.h  //DEFINITIONS FOR FUNCTIONS TO BE IMPLEMENTED
// CLASS PROVIDED: List (a container class for a List of value_types,
// where each List may have a designated value_type called the current
value_type)
//
// TYPEDEF for the List class:
//   typedef ____ value_type
//     List::value_type is the data type of the value_types in the
List. It may be any of
//     the C++ built-in types (int, char, etc.), or a class with a
default
//     constructor, an assignment operator, and a copy constructor.
//
// CONSTRUCTOR for the List class:
//   List( )
//     Postcondition: The List has been initialized as an empty List.
//
// MODIFICATION MEMBER FUNCTIONS for the List class:
//   void start( )
//     Postcondition: The first Item on the List becomes the current
Item
//     (but if the List is empty, then there is no current Item).
//
//   void advance( )
//     Precondition: is_Item returns true.
//     Postcondition: If the current Item was already the last Item on
the
//     List, then there is no longer any current Item. Otherwise, the
new
//     current Item is the Item immediately after the original current
Item.
//
//   void insert(const value_type& entry)
//     Postcondition: A new copy of entry has been inserted in the
List before
//     the current Item. If there was no current Item, then the new
entry has
//     been inserted at the front of the List. In either case, the
newly
//     inserted Item is now the current Item of the List.
//
//   void attach(const value_type& entry)
//     Postcondition: A new copy of entry has been inserted in the
List after
//     the current Item. If there was no current Item, then the new
entry has
//     been attached to the end of the List. In either case, the newly
//     inserted Item is now the current Item of the List.
//
//   void remove_current( )
//     Precondition: is_Item returns true.
//     Postcondition: The current Item has been removed from the List,
and the
//     Item after this (if there is one) is now the new current Item.
//
// CONSTANT MEMBER FUNCTIONS for the List class:
//   size_t size( ) const
//     Postcondition: The return value is the number of Item on the
List.
//
//   bool is_Item( ) const
//     Postcondition: A true return value indicates that there is a
valid
//     "current" Item that may be retrieved by activating the current
//     member function (listed below). A false return value indicates
that
//     there is no valid current Item.
//
//   value_type current( ) const
//     Precondition: is_Item( ) returns true.
//     Postcondition: The Item returned is the current Item on the
List.
//
// VALUE SEMANTICS for the List class:
//    Assignments and the copy constructor may be used with List
objects.
//
// DYNAMIC MEMORY USAGE by the List:
//   If there is insufficient dynamic memory, then the following
functions call
//   new_handler: The constructors, insert, attach, and the
//   assignment operator.

#ifndef LIST3_H
#define LIST3_H
#include <stdlib.h>  // Provides size_t
#include "link1.h"   // Provides linked list toolkit


    class List
    {
    public:
        // TYPEDEF
        typedef node::value_type value_type;
        // CONSTRUCTORS and DESTRUCTOR
        List( );
        List(const List& source);
        ~List( );
        // MODIFICATION MEMBER FUNCTIONS
        void start( );
        void advance( );
        void insert(const value_type& entry);
        void attach(const value_type& entry);
        void remove_current( );
        void operator =(const List& source);
        // CONSTANT MEMBER FUNCTIONS
        size_t size( ) const { return many_nodes; }
	bool is_Item( ) const { return (cursor != NULL); }
        value_type current( ) const;
    private:   
    	             node *head_ptr;
		node *tail_ptr;
		size_t many_nodes;
		node *cursor;
		node *precursor;
      };

#endif





//THIS IS WHAT NEEDS TO BE IMPLEMENTED. I’M HAVING SOME “ISSUES” WITH
//THESE.
/* FILE: list3.cpp
   IMPLEMENTS: List class(see list3.h for documentation)
   INVARIANT for the List class:
   1. The items in the list are stored in a linked list.
   2. The head pointer of the list is stored in the member variable
head_ptr.
   3. The tail pointer of the list is stored in the member variable
tail_ptr.
   4. The current item of the linked list is stored in the member
variable cursor.
   5. The item before the current item of the linked list is stored in
the member variable precursor.
   6. The total number of items in the list is stored in the member
variable many_nodes.
*/

#include <cassert>    // Provides assert
#include <cstdlib>    // Provides NULL and size_t
#include "list3.h"
#include "link1.cpp"       //LINKED LIST TOOLKIT


//Constructors and destructor

List::List()
{
	head_ptr=NULL;
	tail_ptr=NULL;
	many_nodes=0;
	cursor=NULL;
	precursor=NULL;
}

List::List(const List& source)  //Copy constructor  
{
     if(source.cursor==NULL)
	 {
		 list_copy(source.head_ptr, head_ptr, tail_ptr);
		 precursor=NULL;
		 cursor=NULL;
	 }
	 if(source.cursor==source.head_ptr)
	 {
		 list_copy(source.head_ptr, head_ptr, tail_ptr);
		 precursor=NULL;
		 cursor=head_ptr;
	 }
	 //I’M NOT SURE HOW TO USE THE PIECE FUNCTION AT THIS POINT

}

List::~List()     //Destructor
{
	list_clear(head_ptr);
	many_nodes=0;
}


//Modification member functions

void List::start()
{
	cursor=head_ptr;
	precursor=head_ptr;
	tail_ptr=head_ptr;
}

void List::advance()
{
	assert(is_Item());
	if(head_ptr==NULL)
		cursor=head_ptr;

	cursor=cursor->link();
	precursor=precursor->link();
}

void List::insert(const value_type& entry)
{
	precursor=cursor;
	cursor=cursor->link();
	precursor->link()=cursor;
	if(cursor->link()==NULL)
		tail_ptr=cursor;



	list_insert(precursor, entry);
}

void List::attach(const value_type& entry)  
{
    precursor=cursor;
	cursor=cursor->link();
	precursor->link()=cursor;
	if(cursor->link()==NULL)
		tail_ptr=cursor;
	if(head_ptr==NULL)
		cursor->link()=tail_ptr;

	list_insert(cursor->link(), entry);  
}

void List::remove_current()
{
	assert(is_Item());
	if(cursor==head_ptr)
	{
		list_head_remove(head_ptr);
		tail_ptr=NULL;
	}
	else if(cursor!=head_ptr && cursor!=NULL)
	{
		list_remove(cursor);
		cursor=cursor->link();
		precursor=precursor->link();
	}
	else if(cursor==NULL)
	{
		size_t i=0;
		cursor=precursor;
		i=list_length(head_ptr);
		//list_remove(i);
	}
}

void List::operator =(const List& source)     
{

		
     if(source.cursor==NULL)
	 {
		 list_copy(source.head_ptr, head_ptr, tail_ptr);
		 precursor=NULL;
		 cursor=NULL;
	 }
	 if(source.cursor==source.head_ptr)
	 {
		 list_copy(source.head_ptr, head_ptr, tail_ptr);
		 precursor=NULL;
		 cursor=head_ptr;
	 }
	 //NOT SURE HOW TO USE PIECE FUNCTION HERE
}


//Constant member functions

List::value_type List::current() const
{
	assert(is_Item());
    return cursor->data();
}


I will provide the .h and .cpp files for the linked list toolkit that
is used in conjunction with the implementation of the new class:

H
// PROVIDES: A toolkit of 10 functions for manipulating linked lists.
Each
// node of the list contains a piece of data and a pointer to the next
node.
// The type of the data is defined as node::value_type in a typedef
statement.
// The complete type definitions used by the toolkit are:
//
//
//  TYPEDEF for node class: 
//  value_type  may be any of the C++ built-in types (int, char,
etc.), or a class with a default
//  constructor, an assignment operator, and a test for equality (x ==
y).
//  CONSTRUCTOR for node class:
//	node(const value_type& init_data, node* init_link)
//	Post: The node contains the specified data and link. NOTE: The
default value of the data is
//	provided by default constructor of value_type, the default value of
init_link is NULL
//
//	NOTE: Some of the functions have a return value that is a pointer
to a node. Each of these
//	functions comes in two versions: a non-constant version (where the
return value is node*) and
//	a const version (where the return valuse is const node*)
//
//	MEMBER FUNCTIONS:
// void set_data(const value_type&  new_data)
// post: The node now contains the specified new data

// void set_link(node* new_link)
// post: The node now contains the specified new link
//
//	value_type data() const;
//	post: The return value is the data frem this node

// const node* link() const
//
//	node* link()
//	post: The return value is the link from this node


// FUNCTIONS in the linked list toolkit:
//   size_t list_length(const node* head_ptr)
//     Precondition: head_ptr is the head pointer of a linked list.
//     Postcondition: The value returned is the number of nodes in the
linked
//     list.
//
//   void list_head_insert(node*& head_ptr, const node::value_type&
entry)
//     Precondition: head_ptr is the head pointer of a linked list.
//     Postcondition: A new node containing the given entry has been
added at
//     the head of the linked list; head_ptr now points to the head of
the new,
//     longer linked list.
//
//   void list_insert(node* previous_ptr, const node::value_type&
entry)
//     Precondition: previous_ptr points to a node in a linked list.
//     Postcondition: A new node containing the given entry has been
added
//     after the node that previous_ptr points to.
//
//   const node* list_search(const node* head_ptr, const
node::value_type& target)
//	 node* list_search(node* head_ptr, const node::value_type& target)
//     Precondition: head_ptr is the head pointer of a linked list.
//     Postcondition: The pointer returned points to the first node
containing
//     the specified target in its data member. If there is no such
node, the
//     null pointer is returned. The list itself is unaltered.
//
//   const node* list_locate(const node* head_ptr, size_t position)
//	 const node* list_locate(const node* head_ptr, size_t position)
//     Precondition: head_ptr is the head pointer of a linked list,
and
//     position > 0.
//     Postcondition: The pointer returned points to the node at the
specified
//     position in the list. (The head node is position 1, the next
node is
//     position 2, and so on). If there is no such position, then the
null
//     pointer is returned. 
//
//   void list_head_remove(node*& head_ptr) 
//     Precondition: head_ptr is the head pointer of a linked list,
with at
//     least one node.
//     Postcondition: The head node has been removed and returned to
the heap;
//     head_ptr is now the head pointer of the new, shorter linked
list.
//
//   void list_remove(node* previous_ptr) 
//     Precondition: previous_ptr points to a node in a linked list,
and this
//     is not the tail node of the list.
//     Postcondition: The node after previous_ptr has been removed
from the
//     linked list.
//
//   void list_clear(node*& head_ptr) 
//     Precondition: head_ptr is the head pointer of a linked list.
//     Postcondition: All nodes of the list have been returned to the
heap,
//     and the head_ptr is now NULL.
//
//   void list_copy(const node* source_ptr, node*& head_ptr, node*&
tail_ptr)
//     Precondition: source_ptr is the head pointer of a linked list.
//     Postcondition: head_ptr and tail_ptr are the head and tail
pointers for
//     a new list that contains the same items as the list pointed to
by
//
//   void list_piece(
//     const node* start_ptr, const node* end_ptr, Node*& head_ptr,
Node*& tail_ptr)
//     Precondition: start_ptr and end_ptr are pointers to nodes on
the same
//     linked list, with the start_ptr node at or before the end_ptr
node.
//     Postcondition: head_ptr and tail_ptr are the head and tail
pointers for
//     a new linked list that contains the items from start_ptr to
end_ptr.
//     The original list is unaltered.

//  
// DYNAMIC MEMORY usage by the toolkit: 
//   If there is insufficient dynamic memory, then the following
functions call
//   new_handler before any changes are made to the list that head_ptr
points
//   to : list_head_insert, list_insert, list_copy, list_piece,
list_insert_at,
//   list_copy_segment.

#ifndef LINK1_H  
#define LINK1_H
#include <cstdlib> // Provides size_t

class node{ 
public:
	//TYPEDEF:
	typedef double value_type;

	node(const value_type& init_data = value_type(), node*
init_link=NULL);

//	MEMBER FUNCTIONS:

	void set_data(const value_type&  new_data);

	void set_link(node* new_link);

	value_type data() const;
	const node* link() const;
	node* link();

private:
	value_type data_field;
	node* link_field;



};	

// FUNCTIONS in the linked list toolkit:
	size_t list_length(const node* head_ptr);

	void list_head_insert(node*& head_ptr, const node::value_type& entry)
;

	void list_insert(node* previous_ptr, const node::value_type& entry);
    const node* list_search(const node* head_ptr, const
node::value_type& target) ;
	node* list_search(node* head_ptr, const node::value_type& target); 
    node* list_locate(node* head_ptr, size_t position);
	const node* list_locate(const node* head_ptr, size_t position);
    void list_head_remove(node*& head_ptr) ;
    void list_remove(node* previous_ptr) ;
    void list_clear(node*& head_ptr); 

    void list_copy(const node* source_ptr, node*& head_ptr, node*&
tail_ptr) ;
    void list_piece(
    const node* start_ptr, const node* end_ptr, node*& head_ptr,
node*& tail_ptr) ;

#endif


CPP

#include <cassert>    // Provides assert
#include <cstdlib>    // Provides NULL and size_t
#include "link1.h"


node::node(const value_type& init_data, node* init_link)
{
	data_field = init_data;
	link_field = init_link;
}

void node::set_data(const value_type& new_data)
{
	data_field = new_data;
}

void node::set_link(node* new_link)
{
	link_field = new_link;
}

node::value_type node::data() const
{
	return data_field;
}

const node* node::link() const 
{
	return link_field;
}

node* node::link()
{
	return link_field;
}
size_t list_length(node* head_ptr)
// Library facilities used: stdlib.h
{
    node *cursor;
    size_t answer;

    answer = 0;
    for (cursor = head_ptr; cursor != NULL; cursor = cursor->link)
        answer++;

    return answer;
}

void list_head_insert(node*& head_ptr, const node::value_type& entry)
{
    head_ptr = new node (entry, head_ptr);
}

void list_insert(node* previous_ptr, const node::value_type& entry) 
{
    node* insert_ptr;
	insert_ptr = new node;
	insert_ptr->set_data(entry);
	insert_ptr->set_link(previous_ptr->link());
	previous_ptr->set_link(insert_ptr);
}

node* list_search(node* head_ptr, const node::value_type& target) 
// Library facilities used: stdlib.h
{
    node *cursor;
   
    for (cursor = head_ptr; cursor != NULL; cursor = cursor->link())
        if (target == cursor->data())
            return cursor;
    return NULL;
}

node* list_locate(node* head_ptr, size_t position) 
// Library facilities used: assert.h, stdlib.h
{
    node *cursor;
    size_t i;
    
    assert (0 < position);
    cursor = head_ptr;
    for (i = 1; (i < position) && (cursor != NULL); i++)
        cursor = cursor->link();
    return cursor;
}

const node* list_locate(const node* head_ptr, size_t position) 
// Library facilities used: assert.h, stdlib.h
{
    const node *cursor;
    size_t i;
    
    assert (0 < position);
    cursor = head_ptr;
    for (i = 1; (i < position) && (cursor != NULL); i++)
        cursor = cursor->link();
    return cursor;
}

void list_head_remove(node*& head_ptr)
{
    node *remove_ptr;

    remove_ptr = head_ptr;
    head_ptr = head_ptr->link();
    delete remove_ptr;
}

void list_remove(node* previous_ptr)
{
    node *remove_ptr;

    remove_ptr = previous_ptr->link();
    previous_ptr->set_link(remove_ptr->link());
    delete remove_ptr;
}

void list_clear(node*& head_ptr)
// Library facilities used: stdlib.h
{
    while (head_ptr != NULL)
        list_head_remove(head_ptr);
}

void list_copy(node* source_ptr, node*& head_ptr, node*& tail_ptr) 
// Library facilities used: stdlib.h
{
    head_ptr = NULL;
    tail_ptr = NULL;

    // Handle the case of the empty list
    if (source_ptr == NULL)
        return;
    
    // Make the head node for the newly created list, and put data in
it
    list_head_insert(head_ptr, source_ptr->data());
    tail_ptr = head_ptr;
    
    // Copy the rest of the nodes one at a time, adding at the tail of
new list
    source_ptr = source_ptr->link();
	while(source_ptr !=NULL)
	{
		list_insert(tail_ptr, source_ptr->data());
		tail_ptr = tail_ptr->link();
		source_ptr = source_ptr->link();
	}
}

void list_piece(const node* start_ptr, const node* end_ptr, node*&
head_ptr, node*& tail_ptr)
// Library facilities used: stdlib.h
{
    head_ptr = NULL;
    tail_ptr = NULL;

    // Handle the case of the empty list
    if (start_ptr == NULL)
        return;
    
    // Make the head node for the newly created list, and put data in
it
    list_head_insert(head_ptr, start_ptr->data());
    tail_ptr = head_ptr;
    if (start_ptr == end_ptr)
        return;
    
    // Copy the rest of the nodes one at a time, adding at the tail of
new list
    for (start_ptr = start_ptr->link(); start_ptr != NULL; start_ptr =
start_ptr->link())
    {
        list_insert(tail_ptr, start_ptr->data());
        tail_ptr = tail_ptr->link();
        if (start_ptr == end_ptr) 
            return;
    }
}
Thanks. Feel free to follow up with any questions. Please give
reasoning behind major ideas. I want to understand the corrections.

Request for Question Clarification by maniac-ga on 08 Mar 2003 13:07 PST
Hello Martim07,

Just a few comments / clarifications as I get started with this.
Please confirm if possible.

[1] in link1.cpp, line 44 (in list_length), there appears to be a typo
- this should read
    for (cursor = head_ptr; cursor != NULL; cursor = cursor->link()) 
        answer++; 
(added parenthensis to cursor->link)

[2] After some cleanup due to the line wrapping, I get a few
compilation errors in list3.cpp.

g++    -c -o list3.o list3.cpp
list3.cpp: In member function `void List::insert(const double&)':
list3.cpp:84: non-lvalue in assignment
list3.cpp: In member function `void List::attach(const double&)':
list3.cpp:97: non-lvalue in assignment
list3.cpp:101: non-lvalue in assignment

These are all cases where you use cursor->link() (or precursor->link()
on the left hand side of an assignment. I assume this is part of what
you need fixed - please confirm.

[3] You have comments related to using "Piece"; I assume this refers
to list_piece.

[4] I assume you want to confirm these all work, do you need a test
program or do you already have one?

  --Maniac

Clarification of Question by martim07-ga on 09 Mar 2003 08:36 PST
For questions 1 through 3, everything you said is correct. For
question 4, I do have a test program.

Request for Question Clarification by maniac-ga on 09 Mar 2003 12:27 PST
Hello Martim07,

Just a quick progress report.

On the list_piece question - I am assuming the code should look
like...

  else 
    {
      list_piece(source.cursor, source.tail_ptr, head_ptr, tail_ptr);
      precursor = NULL;
      cursor = head_ptr;
    }

where you start at the current cursor position & proceed to the tail
of the list. This code fragment (or very similar) is applied to all
three locations.

In start, precursor should be NULL (and cursor should be head_ptr) to
indicate there are no entries prior to the current entry. This is used
later to trigger calls to node::list_head_* routines.

In advance, the assertion is true implies that the head pointer is not
NULL. Change the if to check if precursor is NULL & handle the two
possible conditions.

Both insert and attach can be simplified quite a bit.
list_insert(precursor, entry) handles most of the work; there is book
keeping required for [1] empty list, [2] insert at start / attach at
end.

The same kind of comment applies for remove_current.

A question on the assignment operator - do you want to copy just the
portion from current -> tail or the whole list (including the current
cursor / precursor position)?  The header file does not specify which
should be done.

I also read the comment made to your question. The implementation of
node (in link1.h and link1.cpp) could be made a template [with some
effort]. I am assuming you don't want link1 changed for this work.
Please confirm.

I am going through test cases right now & making some fixes - I expect
to be done later today.
  --Maniac
Answer  
Subject: Re: C++ Correction
Answered By: maniac-ga on 09 Mar 2003 13:47 PST
Rated:5 out of 5 stars
 
Hello Martim07,

I guess I got done faster than I expected. I will post the revised
version of list3.cpp, the testing program I used, a simple Makefile,
and the results of the tests. Note that I did not try the copy
constructor nor assignment (since they were not listed as "functions
to be implemented" in the header file.

list3.cpp

//THIS IS WHAT NEEDS TO BE IMPLEMENTED. I?M HAVING SOME ?ISSUES? WITH
//THESE.
/* FILE: list3.cpp 
   IMPLEMENTS: List class(see list3.h for documentation) 
   INVARIANT for the List class: 
   1. The items in the list are stored in a linked list. 
   2. The head pointer of the list is stored in the member variable
head_ptr.
   3. The tail pointer of the list is stored in the member variable
tail_ptr.
   4. The current item of the linked list is stored in the member
variable cursor.
   5. The item before the current item of the linked list is stored in
the member variable precursor.
   6. The total number of items in the list is stored in the member
variable many_nodes.
*/ 
 
#include <cassert>    // Provides assert 
#include <cstdlib>    // Provides NULL and size_t 
#include "list3.h" 
#include "link1.cpp"       //LINKED LIST TOOLKIT 
 
 
//Constructors and destructor 
 
List::List() 
{ 
  head_ptr=NULL; 
  tail_ptr=NULL; 
  many_nodes=0; 
  cursor=NULL; 
  precursor=NULL; 
} 

List::List(const List& source)  //Copy constructor   
{ 
  if(source.cursor==NULL) 
    { 
      list_copy(source.head_ptr, head_ptr, tail_ptr); 
      precursor=NULL; 
      cursor=NULL; 
    } 
  else if(source.cursor==source.head_ptr) 
    { 
      list_copy(source.head_ptr, head_ptr, tail_ptr); 
      precursor=NULL; 
      cursor=head_ptr; 
    }
  else 
    {
      list_piece(source.cursor, source.tail_ptr, head_ptr, tail_ptr);
      precursor = NULL;
      cursor = head_ptr;
    }
} 
 
List::~List()     //Destructor 
{ 
  list_clear(head_ptr); 
  many_nodes=0; 
} 
 
 
//Modification member functions 
 
void List::start() 
{ 
  cursor=head_ptr; 
  precursor=NULL; 
} 
 
void List::advance() 
{ 
  assert(is_Item()); 
  precursor=cursor;
  cursor=cursor->link();
} 
 
void List::insert(const value_type& entry) 
{ 
  if (cursor == NULL)
    { // by rule, add to start of list
      list_head_insert(head_ptr, entry);
      cursor = head_ptr;
      precursor = NULL;
    }
  else if (precursor == NULL)
    { // at start of list, insert at head
      list_head_insert(head_ptr, entry);
      cursor = head_ptr;
    }
  else
    { // insert into middle of list
      list_insert(precursor, entry);
      cursor = precursor->link();
    }
  if (tail_ptr == NULL)
    tail_ptr = head_ptr; // was empty list, set tail_ptr too.
  many_nodes++;
} 
 
void List::attach(const value_type& entry)   
{ 
  if (cursor == NULL)
    { 
      if (precursor == NULL)
	{  // list was empty, now one element
	  list_head_insert(head_ptr, entry);
	  cursor = head_ptr;
	  tail_ptr = head_ptr;
	}
      else
	{ // no current entry, add to end
	  precursor = tail_ptr;
	  list_insert(tail_ptr, entry);
	  cursor = precursor->link();
	  tail_ptr = cursor;
	}
      
    }
  else
    { // add after current entry, may be at end
      precursor = cursor;
      list_insert(cursor, entry);
      if (precursor == tail_ptr)
	{ // it was the end of list, update tail
	  tail_ptr = precursor->link();
	}
      cursor = precursor->link();
    }
  many_nodes++;
} 
 
void List::remove_current() 
{ 
  assert(is_Item()); 
  if(cursor==head_ptr) 
    { 
      list_head_remove(head_ptr);
      if (head_ptr == NULL)
	{ // list is now empty, make it so
	  tail_ptr = NULL;
	  cursor = NULL;
	  precursor = NULL;
	}
      else if (precursor == NULL)
	{ // removed from head
	  cursor = head_ptr;
	}
      else // removed from middle, update cursor
	  cursor = precursor->link();
    } 
  else
    { 
      list_remove(precursor); 
      cursor=precursor->link();
      if (cursor == NULL)
	tail_ptr = precursor; // removed last item
    } 
  many_nodes--;
} 
 
void List::operator =(const List& source)      
{ 
  if(source.cursor==NULL) 
    { 
      list_copy(source.head_ptr, head_ptr, tail_ptr); 
      precursor=NULL; 
      cursor=NULL; 
    } 
  else if(source.cursor==source.head_ptr) 
    { 
      list_copy(source.head_ptr, head_ptr, tail_ptr); 
      precursor=NULL; 
      cursor=head_ptr; 
    } 
  else
    {
      list_piece(source.cursor, source.tail_ptr, head_ptr, tail_ptr);
      precursor = NULL;
      cursor = head_ptr;
    }
} 
 
 
//Constant member functions 
 
List::value_type List::current() const 
{ 
  assert(is_Item()); 
  return cursor->data(); 
} 
 
 To explain the changes...

The copy constructor and assignment operator - added else (to if
clause) and added code using list_piece. As I noted in the request for
clarification - it copies the list from the current cursor to end of
list.

The start function - removed assignment to tail_ptr (not needed).

The advance function - set precursor to cursor & advances cursor.

The insert function - there are three cases to handle:
 - insert when cursor is NULL
 - insert when precursor is NULL (insert at head)
 - regular insert
Note the case where we had an empty list, set tail_ptr if so.
Increment many_nodes.

The attach function - three cases again, add to end, attach to empty
list, and attach in middle. Update tail_ptr if attach at end.
Increment many_nodes.

The remove_current function - remove from head (may empty list),
remove from another position (may remove from tail), decrement
many_nodes.

tester.cpp (a main program to exercise the package)

#include <iostream.h>
#include "list3.h"

int main(int argc,
	 char *argv[])
{
  List my_list;
  cout << "Check empty list\n";
  cout << "List is " << my_list.size() << " items long\n";
  cout << "Is item is " << my_list.is_Item() << ".\n";

  cout << "Adding some items; 1, 2, 3\n";
  my_list.attach(1.0);
  my_list.attach(2.0);
  my_list.attach(3.0);
  cout << "List is " << my_list.size() << " items long\n";
  cout << "Is item is " << my_list.is_Item() << ".\n";
  
  cout << "Check list of three items\n";
  my_list.start();
  cout << "Is item is " << my_list.is_Item() << ".\n";
  cout << "Value [1] is = " << my_list.current() << ".\n";
  my_list.advance();
  cout << "Is item is " << my_list.is_Item() << ".\n";
  cout << "Value [2] is = " << my_list.current() << ".\n";
  my_list.advance();
  cout << "Is item is " << my_list.is_Item() << ".\n";
  cout << "Value [3] is = " << my_list.current() << ".\n";
  my_list.advance();
  cout << "Is item is " << my_list.is_Item() << ".\n";

  cout << "Inserting of three more items\n";
  my_list.insert(0.5);
  my_list.advance();
  my_list.advance();
  my_list.insert(my_list.current()-0.5);
  my_list.advance();
  my_list.advance();
  my_list.insert(my_list.current()-0.5);
  cout << "List is " << my_list.size() << " items long\n";
  cout << "Is item is " << my_list.is_Item() << ".\n";

  cout << "Check list of six items\n";
  my_list.start();
  cout << "Is item is " << my_list.is_Item() << ".\n";
  cout << "Value [0.5] is = " << my_list.current() << ".\n";
  my_list.advance();
  cout << "Is item is " << my_list.is_Item() << ".\n";
  cout << "Value [1] is = " << my_list.current() << ".\n";
  my_list.advance();
  cout << "Is item is " << my_list.is_Item() << ".\n";
  cout << "Value [1.5] is = " << my_list.current() << ".\n";
  my_list.advance();
  cout << "Is item is " << my_list.is_Item() << ".\n";
  cout << "Value [2] is = " << my_list.current() << ".\n";
  my_list.advance();
  cout << "Is item is " << my_list.is_Item() << ".\n";
  cout << "Value [2.5] is = " << my_list.current() << ".\n";
  my_list.advance();
  cout << "Is item is " << my_list.is_Item() << ".\n";
  cout << "Value [3] is = " << my_list.current() << ".\n";
  my_list.advance();
  cout << "Is item is " << my_list.is_Item() << ".\n";
  
  cout << "Remove three items\n";
  my_list.start();
  cout << "Is item is " << my_list.is_Item() << ".\n";
  my_list.remove_current();
  my_list.advance();
  cout << "Is item is " << my_list.is_Item() << ".\n";
  my_list.remove_current();
  my_list.advance();
  cout << "Is item is " << my_list.is_Item() << ".\n";
  my_list.remove_current();
  my_list.advance();
  cout << "Is item is " << my_list.is_Item() << ".\n";
  cout << "List is " << my_list.size() << " items long\n";
  
  cout << "Check list of three items\n";
  my_list.start();
  cout << "Is item is " << my_list.is_Item() << ".\n";
  cout << "Value [1] is = " << my_list.current() << ".\n";
  my_list.advance();
  cout << "Is item is " << my_list.is_Item() << ".\n";
  cout << "Value [2] is = " << my_list.current() << ".\n";
  my_list.advance();
  cout << "Is item is " << my_list.is_Item() << ".\n";
  cout << "Value [3] is = " << my_list.current() << ".\n";
  my_list.advance();
  cout << "Is item is " << my_list.is_Item() << ".\n";

  cout << "Remove last three items\n";
  my_list.start();
  cout << "Is item is " << my_list.is_Item() << ".\n";
  my_list.remove_current();
  cout << "Is item is " << my_list.is_Item() << ".\n";
  my_list.remove_current();
  cout << "Is item is " << my_list.is_Item() << ".\n";
  my_list.remove_current();
  cout << "Is item is " << my_list.is_Item() << ".\n";

  cout << "Check empty list\n";
  cout << "List is " << my_list.size() << " items long\n";
  cout << "Is item is " << my_list.is_Item() << ".\n";
}

Makefile (to build the test program & compile support packages)

CPPFLAGS=-g -Wall


tester : tester.o list3.o link1.o
	g++ -g -o tester tester.o list3.o

tester.o : tester.cpp list3.h

link1.o : link1.cpp link1.h

list3.o : list3.cpp list3.h link1.h

[make sure a single tab is prior to the g++ line after tester]

Results of testing

Check empty list
List is 0 items long
Is item is 0.
Adding some items; 1, 2, 3
List is 3 items long
Is item is 1.
Check list of three items
Is item is 1.
Value [1] is = 1.
Is item is 1.
Value [2] is = 2.
Is item is 1.
Value [3] is = 3.
Is item is 0.
Inserting of three more items
List is 6 items long
Is item is 1.
Check list of six items
Is item is 1.
Value [0.5] is = 0.5.
Is item is 1.
Value [1] is = 1.
Is item is 1.
Value [1.5] is = 1.5.
Is item is 1.
Value [2] is = 2.
Is item is 1.
Value [2.5] is = 2.5.
Is item is 1.
Value [3] is = 3.
Is item is 0.
Remove three items
Is item is 1.
Is item is 1.
Is item is 1.
Is item is 0.
List is 3 items long
Check list of three items
Is item is 1.
Value [1] is = 1.
Is item is 1.
Value [2] is = 2.
Is item is 1.
Value [3] is = 3.
Is item is 0.
Remove last three items
Is item is 1.
Is item is 1.
Is item is 1.
Is item is 0.
Check empty list
List is 0 items long
Is item is 0.

This was built and run on a Unix system using gcc (gcc --version)
gcc (GCC) 3.1 20020420 (prerelease)
Copyright (C) 2002 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There
is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR
PURPOSE.

Let me know if you have any further questions or it fails to run with
your test program.

  --Maniac
martim07-ga rated this answer:5 out of 5 stars
Nice job. Very clear answer.

Comments  
Subject: Re: C++ Correction
From: jdog-ga on 08 Mar 2003 12:58 PST
 
I started working on this for you, but I don't have enough time right
now. I'll tell you what I've noticed you need to do so far. If the
question is still open later, I can try to answer it then.

1) Template your classes and functions

     You want the list to be able to store a wide variety of data
types, so there's no option but to use templating. I'm assuming you've
seen templating before, but let me know if you need help.

2) Combine .h and .cpp files

     Unfortunately, most (all?) compilers don't support the export
keyword, so you have to combine the .h and .cpp files for templated
classes. This means that you have to turn link1.h and link1.cpp into a
single file as well as joining link3.h and link3.cpp (you can just
insert the contents of the .cpp into the corresponding .h)


These aren't vary hard, but they might take a little time. There might
be more work to do, but I think these should be done first. I'm not
sure that you even need to use the list_piece() function where you say
you don't know how you should. I'm assuming that you still want to
copy the whole list, regardless of where the cursor is. If so, I
believe there's one case that can handle any list (as opposed to
several case that depend on the position of the cursor). Let me know
if I have misunderstood anything.

Important Disclaimer: Answers and comments provided on Google Answers are general information, and are not intended to substitute for informed professional medical, psychiatric, psychological, tax, legal, investment, accounting, or other professional advice. Google does not endorse, and expressly disclaims liability for any product, manufacturer, distributor, service or service provider mentioned or any opinion expressed in answers or comments. Please read carefully the Google Answers Terms of Service.

If you feel that you have found inappropriate content, please let us know by emailing us at answers-support@google.com with the question ID listed above. Thank you.
Search Google Answers for
Google Answers  


Google Home - Answers FAQ - Terms of Service - Privacy Policy