1

Note:This Is Homework

Specifically my issue is with the + assignment operator, I am writing a singly linked list Template and have to create operators +=, +, -, [] ect. I have written the array, and += so far without to much of an issue but now im working on the + operator currently i have...

Queue.h

#ifndef QUEUE_H
#define QUEUE_H

#include<iostream>
//#include "UnderGrad.h"
//#include "Grad.h"
#include <string.h>
#include<cstdlib>

template <typename T>
class Queue
{
class Node
{
    friend class Queue;
    private:
    T* data;
    Node* next;
};

public:
    Queue() {head = NULL; tail = NULL; numNodes = 0;}
    ~Queue () {clear();}

    //overloaded operators
    T& operator [] (int);
    const T& operator [] (int) const;
    Queue<T>& operator += (T*);
    Queue<T>& operator += (Queue<T>&);
    friend Queue<T> operator+ (Queue<T> inList,T* tbAdded)
    {
        inList.pushBack(tbAdded);

        return inList;
    }
    //Queue<T> operator + (Queue<T>, Queue<T>&);
    //Queue<T>& operator -= (T*&);
    //Queue<T>& operator -= (const Queue<T>&);
    //Queue<T> operator - (T, const T&);
    //Queue<T> operator -(Queue<T>, const Queue<T>&);
    //Queue<T>& operator ! ();



    void pushBack(T*);
    //nice to be ble to clear all sometimes rather than write a for loop evertime you want ot clear the list
    void clear();
    void popFront();

    bool empty();
    T* front();
    int size() const;

    //used while an individual is using create app, so you can go back and edit prevous pages of the app
    T* getPrev(T*);
    T* back();
    void removeNode(T*);
    void sortList();

private:
Node* head;
Node* tail;
int numNodes;

};


//be carefule here with automatic variables
//as it will not create a new instance
template <typename T>
Queue<T>& Queue<T>::operator += (T* tbAdded)
{
    this -> pushBack(tbAdded);
return *this;
}


template <typename T>
Queue<T>& Queue<T>::operator += (Queue<T> &tbAdded)
{   
T* temp;

while (tbAdded.front() != NULL)
{
    temp = (T*) new T(*(tbAdded.front()));
    this -> pushBack(temp);
    tbAdded.popFront();
}

return *this;
}

template <typename T>
const T& Queue<T>::operator[] (int index) const
{
int count = 0;
Node *temp = head;

while (count < index && temp -> next != NULL)
{
    count++;
    temp = temp -> next;
}

if (count < index)
{
    std::cerr << "ArrayOutOfBounds: Index at: " << index << " ArrayLength: " << count << std::endl;
    exit(1);
}
else
{
    return *(temp -> data);
}
}

template <typename T>
T& Queue<T>::operator[] (int index)
{
int count = 0;
Node *temp = head;

while (count < index && temp -> next != NULL)
{
    count++;
    temp = temp -> next;
}

if (count < index)
{
    std::cerr << "ArrayOutOfBounds: Index at: " << index << " ArrayLength: " << count << std::endl;
    exit(1);
}
else
{
    return *(temp -> data);
}
}



//adds node to the back of the list
template <typename T>
void Queue<T>::pushBack(T *tbAdded)
{
    //  std::cout << "hello" << std::endl;

Node *temp = new Node;
//I copy the data into the heap, because for some operations i want to use save   local variables which poses problematic
temp -> data = tbAdded;
temp -> next  = NULL;
    //  std::cout << "hello" << std::endl;
if (head == NULL)
{
    //  std::cout << "bye" << std::endl;
    head = temp;
    tail = head;
}   
else
{
    //  std::cout << "shy" << std::endl;
    tail -> next = temp;
    tail = tail -> next;

}
    //  std::cout << "hello" << std::endl;
numNodes++;
}

//returns length of Queue
template <typename T>
int Queue<T>::size() const
{
return numNodes;
}


//removes a node formt he fornt of the list
template <typename T>
void Queue<T>::popFront()
{
if (head != NULL)
{
    Node *temp = head;
    head = head ->next;
    delete (temp -> data);
    delete (temp);
    numNodes--;
    if (numNodes > 0)
    {
        numNodes--;
        if (numNodes == 0)
        {
            tail = NULL;
        }
    }
}
}

//clears the list
template <typename T>
void Queue<T>::clear()
{
while (head != NULL)
{
    popFront();
}
}

//returns true iff list is empty
template <typename T>
bool Queue<T>::empty()
{
if (numNodes == 0)
{
    return true;
}

return false;
}


//returns data at fornt of list unless the list is empty then it returns null
template <typename T>
T* Queue<T>::front()
{
if (head != NULL)
{
    return head -> data;
}
else
{
    return NULL;
}
}

 //sorts undgrad info
//template <>
//inline void Queue<UnderGrad>::sortList()
//{
//  Node *temp = head;
//  UnderGrad *info;
//
//  for (int i = 0; i < size(); i++)
//  {
//      while (temp -> next)
//      {
//          std::string temp1 = (*(temp -> data)).getCourse();
//          std::string temp2 = (*(temp -> next -> data)).getCourse();
//          if (strcmp(temp1.c_str(), temp2.c_str()) > 0)
//          {
//              info = temp -> data;
//              temp -> data = temp -> next -> data;
//              temp -> next -> data = info;
//
//          }
//          else if (strcmp(temp1.c_str(), temp2.c_str()) == 0 && 
//              (*(temp -> data)).getGPA() < (*(temp -> next -> data)).getGPA())
//          {
//              info = temp -> data;
//              temp -> data = temp -> next -> data;
//              temp -> next -> data =    info;                 
//          }
//
//          temp = temp -> next;
//      }
//      
//      temp = head;
//  }
//  
//
//  
//}


//sorts Grad info
//template <>
//inline void Queue<Grad>::sortList()
//{
//  Node *temp = head;
//  Grad *info;
//
//  for (int i = 0; i < size(); i++)
//  {
//      while (temp -> next)
//      {
//          std::string temp1 = (*(temp -> data)).getCourse();
//          std::string temp2 = (*(temp -> next -> data)).getCourse();
//          std::string temp3 = (*(temp -> data)).getResearch();
//          std::string temp4 = (*(temp -> next -> data)).getResearch();
//          if (strcmp(temp1.c_str(), temp2.c_str()) > 0)
//          {
//              info = temp -> data;
//              temp -> data = temp -> next -> data;
//              temp -> next -> data = info;
//
//          }
//          else if (strcmp(temp1.c_str(), temp2.c_str()) == 0 && 
//              strcmp(temp3.c_str(), temp4.c_str()) > 0)
//          {
//              info = temp -> data;
//              temp -> data = temp -> next -> data;
//              temp -> next -> data = info;                    
//          }
//
//          temp = temp -> next;
//      }
//      temp = head;
//  }
//  
//
//  
//}


//these mothds i was considering using for a bonus but never completed they are used   no where in my code for now atleast
//this method is used when a back button is pressed so i can go from end to front of a list (since this is supposed to be a singly linked list this will be inneficient)
//that way if i have multiple things i.e related courses saved i can go back and edit  them b4 i save the app
template <typename T>
T* Queue<T>::getPrev(T* curNode)
{
if (curNode == head)
{
    return NULL;
}

Node *temp = head;
while (temp -> next != curNode)
{
    temp = temp -> next;
}

return temp -> data;
}


//if editing data i need a acces the last node in order to be able to go back and eit nodes back -> front
template <typename T>
T* Queue<T>::back()
{
if (tail != NULL)
{
    return head -> data;
}
else
{
    return NULL;
}
}

//if we decide to go back and edit we will need to remove the old node
template <typename T>
void Queue<T>::removeNode(T *tbRemoved)
{
Node *curNode, *prevNode;

curNode = head;

if (tbRemoved == head -> data)
{
    head = head -> next;
    delete curNode -> data;
    delete curNode;
}

while (curNode -> data != tbRemoved)
{
    prevNode = curNode;
    curNode = curNode -> next;
}

prevNode -> next = curNode -> next;
delete curNode -> data;
delete curNode;
}

#endif 

main.cpp

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

using namespace std;

int main()
{
Queue<int> intList;
Queue<int> intList1, intList2;
int *t;

intList.pushBack((int*) new int (5));
intList.pushBack((int*) new int (10));
intList.pushBack((int*) new int (15));
intList.pushBack((int*) new int (20));


intList += ((int*) new int (25));
cout << intList[4] << "!" << endl;
cout << "?" << endl;
cout << "?" << endl;
cout << "?" << endl;
intList = intList + ((int*) new int (35));
cout << intList[5] << "!" << endl;
intList += ((int*) new int (30));
cout << intList[5] << "!" << endl;
cout << "?" << endl;
cout << "?" << endl;
cout << "?" << endl;

intList1.pushBack((int*) new int (2));
intList1.pushBack((int*) new int (7));
intList1.pushBack((int*) new int (9));
intList1.pushBack((int*) new int (11));
intList += intList1;
    intList1.clear();
cout << intList[6] << "!" << endl;
cout << intList[2] << "!" << endl;
intList.clear();
intList1.clear();
cout << "?" << endl;


Queue<string> strList;
cout << "?" << endl;    
strList.pushBack((string*) new string("hi"));
strList.pushBack((string*) new string("bi"));
strList.pushBack((string*) new string("di"));
strList.pushBack((string*) new string("ki"));
cout << "?" << endl;
cout << strList[2] << "!" << endl;
return 0;
}

output: 25!

?

?

?

Segmentation fault (core dumped)

i need to implement the + operator so it takes in a data pointer and returns a new list comprised of the old list plus the new node, i wrote this function within the class template itself because i read it was an issue writing it outside, like the rest of my functions. Ive tried a few methods to get this to work

  • using the += assignment operator I defined (plus equals works fine but when i use it with his function something goes wrong?)

  • I've tried creating a new list and filling it with the old and new data then returning that list, didn't work.. so now im confused a point in the right direction would be awsome!


Edit: i have tried removing my + operator form the class definition and reduced it to accepting one parameter

template <typename T>
Queue<T>& Queue<T>::operator+ (T* tbAdded)
{
Queue<T> *temp = (Queue<T> *) new Queue<T>(*this);
temp -> pushBack(tbAdded);
  //    std::cout << (*temp)[5] << std::endl;
  //    std::cout << (*this)[3] << std::endl;
return *temp;
}

form all of my tests on it this appears to 'Work' however at the end of my tests (after all the outputs come out correctly) there is a segmentation fault

5
  • quick note all my other functions that arnt commented out there i have well tested and am almost positive work correctly so im not showing their code inlined in my header file Commented Mar 17, 2013 at 5:00
  • What does it means that it doesn't work? Commented Mar 17, 2013 at 5:02
  • Also where's pushBack defined? Commented Mar 17, 2013 at 5:04
  • for it doesn't work i get a segmentation fault for what is currently defined for the + operator and as for where the pushback is defined one sec ill add my entire header file Commented Mar 17, 2013 at 5:08
  • Please show your definition of pushback Commented Mar 17, 2013 at 5:10

1 Answer 1

1

You need to define a copy constructor and an assignment operator for your class. These will need to copy the entire list element-by-element.

In the following code:

Queue<T> *temp = (Queue<T> *) new Queue<T>(*this);

the Queue<T>(*this) calls the copy constructor. Since you don't provide one, the compiler generates one for you. That automatically-generated copy constructor simply does a field-by-field copy of your object. In other words, it copies the head and tail pointers, as well as the value of numNodes.

This, however, is wrong, since both the original and the copy will attempt to deallocate the same elements when they go out of scope. This results in undefined behaviour, and explains the crash you're seeing.

See the Rule of Three.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.