Перегрузка << оператор c ++ - PullRequest
       66

Перегрузка << оператор c ++

0 голосов
/ 21 февраля 2019

Я пытаюсь вывести значения моих связанных списков, но не могу заставить свой оператор << работать.Когда я выхожу << предыдущий-> ключ;Выдается как -1, что и есть HEAD_OF_LIST.В программе я вызываю функцию l [2] = LLSortedPosInt (2);который устанавливает список № 2, содержащий один элемент, который является целым числом 2.

Это объявление класса:

struct  Node;
typedef Node* NodePtr;

// The key value HEAD_OF_LIST is used as a "sentinal" value
const int HEAD_OF_LIST = -1;

class LLSortedPosInt {
  public:
   // constructors
                         LLSortedPosInt();
                         LLSortedPosInt(int  key);
                         LLSortedPosInt(int *keys,  int n);         //int *keys is an array of integers
                         LLSortedPosInt(const LLSortedPosInt &l);

   // destructor
                        ~LLSortedPosInt();

   bool                  containsElement (int key) const;
   bool                  isEmpty         (       ) const;

   LLSortedPosInt&       operator= (const LLSortedPosInt &l);
   bool                  operator==(const LLSortedPosInt &l) const;
   bool                  operator!=(const LLSortedPosInt &l) const;

   friend LLSortedPosInt operator+ (const LLSortedPosInt &l1,
                                      const LLSortedPosInt &l2);
   friend LLSortedPosInt operator- (const LLSortedPosInt &l1,
                                      const LLSortedPosInt &l2);
   friend ostream&       operator<<(ostream &out, 
                                      const LLSortedPosInt &l);
  private:
   void                  insert    (int key);
   void                  remove    (int key);

   NodePtr head;
};

Это функция createNode:

static NodePtr createNode(int key, NodePtr p) {
   // allocate a new Node for storing the given key value
   NodePtr n = new Node;

   // store the key value and the next pointer
   n->key  = key;
   n->next = p;

   // return the new Node to the caller
   return n;
}

Это мой код для оператора << </p>

ostream&  operator<<  (ostream &out, const LLSortedPosInt &l) {

// an empty list will be printed as <>
// a singleton list (a list having one key value k) will be
//     printed as <k>
// a list having multiple keys such as 2, 5, 7 will be printed
//     as <2, 5, 7>

// print the left angle bracket
out << "<";

NodePtr previous = l.head;
NodePtr current = l.head->next;

//TEST previous AND current
out << previous->key;
out << current->key << ">" << endl << "<";

// print the values of l
while (current != NULL) {
    if (current->key >= 0) {
        if (current->next == NULL) {
            out << current->key;
            break;
        }
        out << current << ", ";
        previous = current;
        current = current->next;
    }
}

// print the right angle bracket
out << ">";

return out;
}

У меня также есть функция, которая принимает целочисленный ввод, который приведен ниже.Я уверен, что это написано правильно, но я не уверен.

LLSortedPosInt::LLSortedPosInt(int key) {
// create the sentinal Node at the head of the list
head = createNode(HEAD_OF_LIST, nullptr);

// add the single element key, as long as it is positive
if (key > 0) {
    head->next = createNode(key, nullptr);
}
}

1 Ответ

0 голосов
/ 21 февраля 2019

Определение operator<< может быть следующим:

std::ostream& operator<<(std::ostream& out, const LLSortedPosInt& l) {
    out << "<";
    NodePtr current = l.head;
    // check that it actually points to a Node before accessing any fields
    if(current) {
        out << current->key;
        // loop through the links and stream the keys
        while((current = current->next) != nullptr)
            out << "," << current->key;
    }
    out << ">";
    return out;
}

Конструктор LLSortedPosInt(int key) не должен создавать узел HEAD_OF_LIST, поскольку он ни для чего не используется.Таким образом, вы можете изменить этот конструктор, чтобы использовать тот, который у вас уже есть, для списка ключей через делегирование.Делегирование также упрощает добавление конструктора, используя initializer_list:

LLSortedPosInt(const int *keys=nullptr, size_t n=0) :
    head(nullptr)
{
    if(keys && n) {
        while(n--) {
            createNode(*keys);
            ++keys;
        }
    }
}

// single key construction
LLSortedPosInt(int key) :
    LLSortedPosInt(&key, 1) // delegate
{}

// construction using an initializer list
LLSortedPosInt(std::initializer_list<int> il) :
    LLSortedPosInt(il.begin(), il.size()) // delegate
{}

Интерфейс static createNode немного странный.Пользователям функции не нужно указывать указатель на следующий узел.Вот для чего предназначен контейнерный класс.Его можно превратить в обычную функцию-член и напрямую создать узел в правильном месте:

NodePtr createNode(int key) {
    NodePtr current = head;
    NodePtr previous = nullptr;

    while(current && (current->key < key)) {
        previous = current;
        current = current->next;
    }

    if(previous) {
        // insert the node between previous and previous->next
        NodePtr rv = new Node(key, previous->next);
        return previous->next = rv;
    } else {
        // insert the node first in the list
        NodePtr rv = new Node(key, head);
        return head = rv;
    }
}

Учитывая, что фактический Node выглядит примерно так:

struct Node {
    Node* next;
    int key;
    Node(int k, Node* n) : next(n), key(k) {}
    Node(const Node&) = delete;
    Node(Node&&) = delete;
    Node& operator=(const Node&) = delete;
    Node& operator=(Node&&) = delete;
    ~Node() = default;
};

using NodePtr = Node*;
...