0

我正在尝试使用一个在链表上创建和执行操作的程序。

该程序按原样工作和编译,但我必须创建一个可以处理任何类型数据(int、float、char)的程序模板版本。程序中有两个类,NodeSLList 类和 IntNode 类。

我已尽力创建这两个类的模板版本,同时按我认为应该的方式更改成员声明和定义,但对于我的生活,我无法摆脱其中一些错误。我正在阅读和重新阅读关于模板和模板类的笔记,并在网上搜索以获得更好的解释,并且在发布此内容时将继续工作,但同时我非常感谢任何帮助。

有两个头文件和一个源代码文件。

IntNode.h:

///////////////////////////////////////////////////////////////////////
// class IntNode
//
// Description: represents the data that we want to store in our 
//              linked list
///////////////////////////////////////////////////////////////////////
#ifndef __INT_NODE__
#define __INT_NODE__

#include <iostream>

using std::ostream;


// class declaration
template <typename N>
class IntNode {

// make the following friends of this class in order that they be
// able to directly access private data of this container class


    friend void NodeSLList_Test(void);
    template <typename N> friend class NodeSLList<N>;
    friend class TSArray;
    friend ostream& operator<<(ostream &, NodeSLList<N> &);

public:

///////////////////////////////////////////////////////////////////////
// ostream operator
// 
// Description: provide overloaded ostream operator
// Input: reference to ostream object
//        reference to IntNode object to output
// Output: none
// Returns: reference to same ostream operator for cascading
///////////////////////////////////////////////////////////////////////
    friend ostream& operator<<(ostream & out, IntNode<N> & n)
    {
        out << "[" << n.row << "]"
            << "[" << n.col << "]"
            << "[" << n.depth << "]:"
            << n.data;
        return out;
    }


///////////////////////////////////////////////////////////////////////
// default constructor
// 
// Description: provide default construction of an IntNode object
// Input: row of array
//        column of array
//        depth of array
//        initial value of node
//        pointer to next IntNode
// Output: none
// Returns: reference to same ostream operator for cascading
///////////////////////////////////////////////////////////////////////
    IntNode(int inRow=0, int inCol=0, int inDepth=0, N inData, IntNode<N> *in = 0)
    {
        data = inData; 
        next = in;
        row = inRow; 
        col = inCol; 
        depth = inDepth;
    }

///////////////////////////////////////////////////////////////////////
// GetRow
// 
// Description: return row member
// Input: none
// Output: none
// Returns: row member
///////////////////////////////////////////////////////////////////////
    const int GetRow() const
    {
        return row;
    }

///////////////////////////////////////////////////////////////////////
// GetColumn
// 
// Description: return column member
// Input: none
// Output: none
// Returns: column member
///////////////////////////////////////////////////////////////////////
    const int GetColumn() const
    {
        return col;
    }


///////////////////////////////////////////////////////////////////////
// GetDepth
// 
// Description: return depth member
// Input: none
// Output: none
// Returns: depth member
///////////////////////////////////////////////////////////////////////
    const int GetDepth() const
    {
        return depth;
    }


///////////////////////////////////////////////////////////////////////
// GetData
// 
// Description: return data member
// Input: none
// Output: none
// Returns: data member
///////////////////////////////////////////////////////////////////////
    const N GetData() const
    {
        return data;
    }


private:

///////////////////////////////////////////////////////////////////////
// row
// 
// this variable holds the row of the array element (i.e first demension)
///////////////////////////////////////////////////////////////////////
    int row;

///////////////////////////////////////////////////////////////////////
// column
// 
// this variable holds the column of the array element (i.e 2nd demension)
///////////////////////////////////////////////////////////////////////
    int col;

///////////////////////////////////////////////////////////////////////
// depth
// 
// this variable holds the column of the array element (i.e 3rd demension)
///////////////////////////////////////////////////////////////////////
    int depth;

///////////////////////////////////////////////////////////////////////
// data
// 
// this variable holds the actual data at the array element
///////////////////////////////////////////////////////////////////////
    N data;


///////////////////////////////////////////////////////////////////////
// column
// 
// this variable holds the column of the array element (i.e 2nd demension)
///////////////////////////////////////////////////////////////////////
    IntNode<N> *next;
};


#endif __INT_NODE__

节点SLList.h:

///////////////////////////////////////////////////////////////////////
// Class NodeSLList Interface
//
// Description - This is the interface for a class which implements 
//               a singly linked list of integers. Each node in the 
//               linked list is IntNode object, defined by the IntNode
//               class. 
///////////////////////////////////////////////////////////////////////
#ifndef INT_LINKED_LIST
#define INT_LINKED_LIST

#include <iostream>

using std::ostream;
using std::cout;
using std::cin;
using std::endl;

#include "IntNode.h"

// Class NodeSLList Declaration

template< typename N >
class NodeSLList {


///////////////////////////////////////////////////////////////////////
// operator<<
// 
// Description: print the list
// Input: reference to ostream object
//        reference to an NodeSLList object to be printed
// Output: linked list printed to screen
// Returns: reference to an ostream object
///////////////////////////////////////////////////////////////////////
    //friend ostream& operator<<( ostream &, NodeSLList<N> & );
    template <typename N> friend ostream & operator<<(ostream &, NodeSLList<N> &);


public:


///////////////////////////////////////////////////////////////////////
// default constructor
// 
// Description: initialize list
// Input: none
// Output: none
// Returns: none
///////////////////////////////////////////////////////////////////////
    NodeSLList()
    {
        head = tail = 0;
    }


///////////////////////////////////////////////////////////////////////
// destructor
// 
// Description: deallocates all memory for linked list by calling
//              destroyList() member function
// Input: none
// Output: none
// Returns: none
///////////////////////////////////////////////////////////////////////
    ~NodeSLList()
    {
        // call destroyList() to remove all nodes
        // and reset linked list
        DestroyList();
    }


///////////////////////////////////////////////////////////////////////
// IsEmpty
// 
// Description: returns status of array
// Input: none
// Output: none
// Returns: TRUE if list is empty
//          FALSE otherwise
///////////////////////////////////////////////////////////////////////
    bool IsEmpty() const
    {
        return (head == 0); 
    }

///////////////////////////////////////////////////////////////////////
// GetSize
// 
// Description: get current number of nodes in list
// Input: none
// Output: none
// Returns: number of nodes in list
///////////////////////////////////////////////////////////////////////
    int GetSize() const
    {
        // check to see if the list is empty. if 
        // so, just return 0
        if ( IsEmpty() ) return 0;

        int size = 1;
        IntNode<N> *p = head;
        // compute the number of nodes and return
        while (p != tail)
        {
            size++;
            p = p->next;
        }
        return size;
    }

///////////////////////////////////////////////////////////////////////
// AddToHead
// 
// Description: add a node to the head of the list
// Input: data for node to be added
// Output: updated linked list
// Returns: none
///////////////////////////////////////////////////////////////////////
    void AddToHead(IntNode<N> & node)
    {
        // create a new node, and make it the head. the 
        // previous head will become head->next
        head = new IntNode<>(node.row, node.col, node.depth, node.data, head);

        // if this is the first node, make the tail the 
        // same as the head
        if (tail == 0)
            tail = head;
    }

///////////////////////////////////////////////////////////////////////
// DeleteFromHead
// 
// Description: remove a node from the head of the list
// Input: none
// Output: updated linked list
// Returns: data that was at the node just removed
///////////////////////////////////////////////////////////////////////
    IntNode<N> DeleteFromHead()
    {
        IntNode<N> temp;
        if (IsEmpty())
        {
            cout << "*****ERROR: Can't delete from head. List is Empty" << endl;
            return temp;
        }

        temp.data = head->data;
        temp.col = head->col;
        temp.row = head->row;
        temp.depth = head->depth;

        IntNode<N> *tmp = head;

        // if there is only one node, set the head and pointer tails
        // to NULL (0)
        if (head == tail)
            head = tail = 0;

        // otherwise, move the head pointer to the next node 
        // in the list
        else
            head = head->next;

        // delete head node
        delete tmp;

        return temp;
    }

///////////////////////////////////////////////////////////////////////
// DeleteFromTail
// 
// Description: remove a node from the tail of the list
// Input: none
// Output: updated linked list
// Returns: data that was at the node just removed
///////////////////////////////////////////////////////////////////////
    IntNode<N> DeleteFromTail()
    {
        IntNode<N> nodeData;
        nodeData.col = tail->col;
        nodeData.row = tail->row;
        nodeData.depth = tail->depth;
        nodeData.data = tail->data;


        // if there is only one node, delete the only node, and set the 
        // head and tail pointers to NULL (0) 
        if (head == tail)
        {
            delete head;
            head = tail =0;
        }

        // otherwise, traverse to the tail node and delete it
        else
        {
            IntNode<N> * temp;
            for (temp = head; temp->next != tail; temp = temp->next);       //shifts thru the node, from the head to the node right before the tail
            delete tail;
            tail = temp;
            tail->next = 0;
        }

        return nodeData;
    }

///////////////////////////////////////////////////////////////////////
// DeleteNode
// 
// Description: remove a node from the list
// Input: node number to be removed
// Output: updated linked list
// Returns: data that was at the node just removed
///////////////////////////////////////////////////////////////////////
    IntNode<N> DeleteNode(int nodeNum)
    {
        if (nodeNum <= 0) nodeNum = 1;
        IntNode<N> *prev=head , *temp=head;
        IntNode<N> current;

        // traverse to the node
        for (int loop=1; loop<nodeNum; loop++)
        {
            prev=temp, temp=temp->next;
            // check for case where nodeNum is > the number of 
            // nodes in the list. if we reach the tail before
            // we traverse to the node, delete the tail 
            if ( temp == tail )
                return DeleteFromTail();
        }

        // if deleting the head just call 
        // the appropriate member function 
        // and don't repeat that logic here
        if (temp == head) return DeleteFromHead();

        // otherwise, delete the node we traversed to
        prev->next = temp->next;
        current.row = temp->row;
        current.col = temp->col;
        current.data = temp->data;

        delete temp;

        return current;
    }

///////////////////////////////////////////////////////////////////////
// RetrieveNode
// 
// Description: retrieve data from a node without removing it from 
//              the list
// Input: node number (1-N; not 0-N-1)
// Output: none
// Returns: reference to node data
///////////////////////////////////////////////////////////////////////
    IntNode<N> &RetrieveNode(int nodeNum) const
    {
        IntNode<N> *tmp = head;

        // traverse to the node, or to the last node, whichever comes
        // first
        for (int i=1; i< nodeNum && tmp != tail; i++)
            tmp = tmp->next;

        return *tmp;
    }

///////////////////////////////////////////////////////////////////////
// UpdateNode
// 
// Description: update a node's data
// Input: node number (1-N; not 0-(N-1))
// Output: updated node
// Returns: none
///////////////////////////////////////////////////////////////////////
    void UpdateNode(int nodeNum, IntNode<N> &node)
    {
        IntNode<N> *tmp = head;

        // traverse to the node, or to the last node, whichever comes
        // first
        for (int i=1; i< nodeNum && tmp != tail; i++)
            tmp = tmp->next;

        tmp->data = node.data;
        tmp->col = node.col;
        tmp->row = node.row;
    }

///////////////////////////////////////////////////////////////////////
// DestroyList
// 
// Description: deallocates all memory for linked list
// Input: none
// Output: reset linked list
// Returns: none
///////////////////////////////////////////////////////////////////////
    void DestroyList()
    {
        // while the list is NOT empy
        // keep removing the head node and make
        // the next node the head node
        for (IntNode<N> *p; !IsEmpty(); )
        {
            p = head->next;
            delete head;
            head = p;
        }
        head = tail = 0;
    }

private:

    IntNode<N> *head, *tail;

};

#endif INT_LINKED_LIST

测试驱动程序.cpp:

// TEST DRIVER. Only used to test the class.
// Activated by defining TEST_DRIVER in the 
// Project - Settings - C/C++ - Preprocessor definitions
#ifdef LIST_DRIVER

#include <stdlib.h>
#include "NodeSLList.h"
#include "IntNode.h"



template <typename N>
void NodeSLList_template_Test()
{

    NodeSLList_template<N> s;
    IntNode_template<N> temp;

    IntNode_template<N> n1(1,1,1,10);
    IntNode_template<N> n2(1,2,1,20);
    IntNode_template<N> n3(1,3,1,30);
    IntNode_template<N> n4(1,4,1,40);
    IntNode_template<N> n5(1,5,1,50);

    cout << "Testing addToHead() operation" << endl;
    s.AddToHead(n5);
    s.AddToHead(n4);
    s.AddToHead(n3);
    s.AddToHead(n2);
    s.AddToHead(n1);

    cout << s << endl;

    cout << "\nTesting GetSize() operation" << endl;
    cout << "list contains " << s.GetSize() << " node(s)" << endl;

    cout << "\nTesting DeleteFromHead() operation" << endl;
    temp = s.DeleteFromHead();
    cout << "node retrieved " << temp << endl;
    cout << s << endl;

    cout << "\nTesting DeleteFromTail() operation" << endl;
    temp = s.DeleteFromTail();
    cout << "node retrieved " << temp << endl;
    cout << s << endl;

    cout << "\nTesting RetrieveNode() operation" << endl;
    temp = s.RetrieveNode(0);
    cout << "node retrieved (should be first node) " << temp << endl;
    temp = s.RetrieveNode(50);
    cout << "node retrieved (should be last node) " << temp << endl;
    temp = s.RetrieveNode(2);
    cout << "node retrieved (should be 2nd node) " << temp << endl;
    pause();

    cout << "Adding n3 to head" << endl;
    cout << "Adding n2 to head" << endl;
    s.AddToHead(n3);
    s.AddToHead(n2);
    cout << "List is now: " << s << endl;
    cout << "\nTesting DeleteNode() operation" << endl;
    temp = s.DeleteNode(50);
    cout << "node deleted (should be last node) " << temp << endl;
    cout << s << endl;
    temp = s.DeleteNode(3);
    cout << "node deleted (should be 3rd node) " << temp << endl;
    cout << s << endl;

    cout << "Test SsEmpty() operation" << endl;
    cout << (s.IsEmpty() ? "List IS Empty\n" : "List NOT Empty\n");

    cout << "\nTesting UpdateNode() operation (updating 3rd node with [10][20][30]:500)" 
        << endl;
    temp.row = 10;
    temp.col = 20;
    temp.depth = 30;
    temp.data = 500;
    s.UpdateNode(3,temp);
    cout << s << endl;

    pause();

    cout << "\nTesting the ability to delete nodes from head, even" << endl
        << "after list is empty" << endl
        << "Should recieve 2 errors" << endl;
    temp = s.DeleteFromHead();
    temp = s.DeleteFromHead();
    temp = s.DeleteFromHead();
    temp = s.DeleteFromHead();
    temp = s.DeleteFromHead();

    cout << "\nTest IsEmpty() operation" << endl;
    cout << (s.IsEmpty() ? "List IS Empty\n" : "List NOT Empty\n");

    cout << "\nTesting DestroyList() operation" << endl;
    s.AddToHead(n3);
    s.AddToHead(n2);
    s.AddToHead(n1);
    cout << s << endl;
    cout << "calling DestoryList()" << endl;
    s.DestroyList();
    cout << s << endl;

}

void pause()
{
    cout << "Press RETURN to continue" << endl;
    cin.get();
    system("cls");
}


void pause();

void main(void)
{
    NodeSLList_template_Test<int>();
}



#endif

还有我的错误:

Error   1   error C2143: syntax error : missing ';' before '<' c:\cis554\hw_7_2\hw_7_2\intnode.h    24
Error   2   error C2059: syntax error : '<' c:\cis554\hw_7_2\hw_7_2\intnode.h   24
Error   3   error C2238: unexpected token(s) preceding ';'  c:\cis554\hw_7_2\hw_7_2\intnode.h   24
    4   IntelliSense: default argument not at end of parameter list c:\CIS554\HW_7_2\HW_7_2\IntNode.h   61
4

1 回答 1

1

You have a circular dependency. IntNode needs the declaration of NodeSLList and vice-versa.

As an aside, names with leading underscores or two adjacent underscores are reserved for the implementation, so you should change this

#ifndef __INT_NODE__

to something like

#ifndef INT_NODE_H_
于 2012-11-21T15:47:58.633 回答