I'm still stuck on an issue that keeps occurring with a class assignment which works with templates and Linked-List-based Stacks. I am constantly getting segmentation faults and I cannot for the life of me see why.
main() asks for a value to determine how many disks to play the game with, which calls set_Discs(), which appends "x"s to a string object tmp_str to represent disks for the game. This string object is then pushed onto the stack rod[0] (the first rod) and then it loops back. I call a cout to print the top stack object each time through the loop as a test and it works, so I can successfully store the string objects. However upon calling the next function print_Game() it does the first iteration of the for-loop (printing the first line) and goes bust again.
int main() {
TowerHanoi game;
size_t disc_in;
//How many discs to be used
cout << "Welcome to Towers of Hanoi!"<< "Please enter how many discs you want to play with: " << endl;
cin >> disc_in;
game.set_Discs(disc_in);
game.print_Game();
//Ask for source and target rod
return EXIT_SUCCESS;
}
The set_Discs() function:
void TowerHanoi::set_Discs(size_t disc) {
//cout << "test: " << rod[0].top() << endl;
discs = disc;
while (disc > 0) {
string tmp_str;
for (size_t i=0; i<disc; i++) {
tmp_str.append("x");
}
disc--;
rod[0].push(tmp_str);
cout << "test: " << rod[0].top() << endl;
}
}
The function print_Game() is a recent logical endeavour so forgive me if it's bad and under-worked. The loop adds spacing, then prints the top string object, then calls pop() (which calls removeFromHead() in LinkedList.template) to make the next string object the top object for the next time through the loop, and so on. Refer to addToHead().
void TowerHanoi::print_Game() {
size_t spaces = discs;
string topLen = rod[0].top();
string xString;
cout << "top length: " << topLen.length() << endl;
for (size_t a=0; a<discs;a++) {
LStack<string> rodCopy = rod[0];
cout << "==="; //3 spaces
for (size_t i=0; i<spaces-topLen.length();i++) { //add to xString
xString.append("=");
}
cout << "===" << xString << rod[0].top() << xString << endl;
rod[0].pop();
spaces--;
}
}
Some relevant code from LStack.template (this is the Stack):
//push
template <typename Obj>
void LStack<Obj>::push(Obj& head_in) {
list->addToHead(head_in);
used++;
}
//pop
template <typename Obj>
Obj LStack<Obj>::pop() {
used--;
return list->removeFromHead();
}
//top
template <typename Obj>
const Obj& LStack<Obj>::top() {
return list->list_getHead();
}
Relevant code from LinkedList.template:
template <typename Item>
void LinkedList<Item>::addToHead(Item& entry) {
node<Item>* temp = head;
head = new node<Item>();
head->set_data(entry);
head->set_link(temp);
}
template <typename Item>
const Item& LinkedList<Item>::removeFromHead() {
node<Item>* head_copy = head; //create a copy of head
head->set_data(head_copy->link()); //set head's data to the previous object
return head_copy->data(); //return head's original data
}
Node.template:
template <typename Object>
void node<Object>::set_data(const Object& new_data){
word = new_data;
}
template <typename Object>
void node<Object>::set_link(node<Object>* new_link){
next= new_link;
}
template <typename Object>
void node<Object>::set_previous(node<Object>* new_prev) {
previous = new_prev;
}
template <typename Object>
const Object& node<Object>::data() const{ //return the word
return word;
}
template <typename Object>
const Object& node<Object>::link() const { //return next node (const function)
return next->data();
}
template <typename Object>
const Object& node<Object>::back() const { //return previous node (const)
return previous->data();
}
Identifying the data being pushed on stack:
void TowerHanoi::set_Discs(size_t disc)
{
while (disc > 0)
{
string tmp_str; <-- note here, tmp_str is stack variable
rod[0].push(tmp_str);
}
}
Now, let us see the LStack::push() function:
//push
template <typename Obj>
void LStack<Obj>::push(Obj& head_in) <-- note here, input to push() is pass by reference
{
list->addToHead(head_in);
used++;
}
Once, set_Discs() function call is done, the reference to the used stack variables inside this function is not valid.
This may be related to the problem of program crashing / terminating abruptly when print_Game() function is called where LStack stored data is being used.
Related
I'm having a bit of trouble wrapping this around my head; I used the debugger in VS to go through my code. I realized that when I call the insertBack() function in main() the elements aren't inserted since the condition if (!isFull) isn't met--returning false causing the insertion to not happen. I tried removing the condition and got some errors regarding my code trying to insert a number into an invalid portion of the array. While going through this, I started to ask myself is the isFull() function required since a dynamic array can be resized; but, how can it be full if this is the case? I looked a bit into vectors on cpprefrence and didn't find an isFull() member function.
#include <iostream>
template<typename T>
class container
{
template <typename T2>
friend std::ostream& operator<<(std::ostream& out, const container<T2> &cobj);
// Postcondition: contents of the container object cobj is displayed
public:
container();
// Postcondition: an empty container object is created with data members arr set to NULL, n set to -1 and Capacity set to 0
~container();
// Destructor; required as one of the Big-3 (or Big(5) because of the presence of a pointer data member. Default version results in
// memory leak!
// Postcondition: dynamic memory pointed to by arr has been release back to the “heap” and arr set to NULL or nullptr
// In order to see the action, message "destructor called and dynamic memory released!" is displayed
bool isEmpty() const;
// Postcondition: returns true is nothing is stored; returns false otherwise
bool isFull() const;
// Postcondition: returns true if arr array is filled to capacity; returns false otherwise
int size() const;
// Postcondition: returns the size or the number of elements (values) currently stored in the container
int capacity() const;
// Postcondition: returns the current storage capacity of the container
bool insertBack(const T& val);
// Postcondition: if container is not full, newVal is inserted at the end of the array;
// otherwise, double the current capacity followed by the insertion
bool deleteBack();
// Precondition: The array must not be empty
// Postcondition: the last element stored in the array is removed! size of the container is decremented by 1, capacity unchanged
void clear();
// Postcondition: all elements in arr of calling container object are cleared and the dynamic memory is released back to “heap”
private:
void allocate(T* &temp);
// Postcondition: if Capacity = 0, allocate a single location; otherwise the current capacity is doubled
T *arr;
int Capacity; // Note: Capital 'C' as capacity is used as a function name
int n; // size or actual # of values currently stored in the container; n <= SIZE
};
template<typename T2>
std::ostream& operator<<(std::ostream& out, const container<T2> &cobj)
{
std::cout << "Currently it contains " << cobj.size() << " value(s)" << std::endl
<< "Container storage capacity = " << cobj.capacity() << std::endl
<< "The contents of the container:" << std::endl;
if (cobj.isEmpty())
{
std::cout << "*** Container is currently empty!" << std::endl;
}
else
{
for (int i=0; i<cobj.size(); ++i)
{
std::cout << cobj.arr[i];
}
}
return out;
}
template<typename T>
container<T>::container()
{
arr = nullptr;
Capacity = 0;
n = 0;
}
template<typename T>
container<T>::~container()
{
delete arr;
arr = nullptr;
std::cout << "Destructor called! (this line is normally not displayed)" << std::endl;
}
template<typename T>
bool container<T>::isEmpty() const
{
return n==0;
}
template<typename T>
bool container<T>::isFull() const
{
return n==Capacity;
}
template<typename T>
int container<T>::capacity() const
{
return Capacity;
}
template<typename T>
int container<T>::size() const
{
return n;
}
template<typename T>
bool container<T>::insertBack(const T& val)
{
if (!isFull())
{
n++;
arr[n-1] = val;
return true;
}
else
{
return false;
}
}
template<typename T>
bool container<T>::deleteBack()
{
if (!isEmpty())
{
n--;
return true;
}
else
{
return false;
}
}
template<typename T>
void container<T>::clear()
{
if (!isEmpty())
{
n = 0;
return true;
}
else
{
return false;
}
}
template<typename T>
void container<T>::allocate(T* &temp)
{
if (Capacity==0)
{
temp = new T;
}
else
{
return Capacity*2;
}
}
int main()
{
container<int> a1;
std::cout << a1 << std::endl;
std::cout << "Currently, the container object contains 0 element(s) or 0 value(s)" << std::endl;
std::cout << "\nWe now insert 3 values at the back of the array, one at a time:" << std::endl;
const int num = 3;
for (int i=0, c=0; i<=num; ++i, c+=10)
{
a1.insertBack(c);
}
std::cout << a1;
}
I think that having an isFull method does not make sense, since your dynamic container is not limited in capacity. Instead, you can use the size and capacity methods to track the state of the container.
If you want to implement a vector and want to check if size smaller than or equals to capacity, then decide whether to resize it, you can wrapper size > = capacity as a private isFull() function. But I think it makes no sense to set it public.
Im currently studying for an exam in c++.
I'm doing some practice questions on templates and have became totally stuck, i'v checked my code and it follows the solutions but this error keeps poping up. I'm unsure how I am passing in the wrong arguements (this is what I believe the issue is.
Code is listed below, any help is greatly appreciated
Tester
int main(){
s_array array(10);
array[5] = 5; //inbound access
cout << array[5] << endl;
array[-1] = 2;
cout << array[15];
return 0;
}
header, class and templates:
template <typename T>
class s_array {
public:
s_array(int size);
~s_array();
T &operator[](int i);
private:
int size;
T* data;
};
template <typename T>
s_array<T>::s_array(int size) : size(size)
{
/*
* If the size of the array is greater than zero
* A new array is created at the value of size
*/
if(size > 0) data = new T[size];
else{
std::cout << "Invalid array" << endl;
exit(1);
}
}
template <typename T>
s_array<T>::~s_array()
{
delete [] data;
}
/*
* Safety feature for the array going out of bounds
*/
template <typename T>
T& s_array<T>::operator[](int i)
{
if(i < 0 || i >= size){
std::cout << "index" << i << "is out of bounds" << endl;
exit(1);
}
return data[i];
}
You need to say what type the s_array is holding, for example this would define the array to contain int types. In the template definition, int will now be substituted everywhere that T used to be
s_array<int> array(10);
I was wondering how I could call the toString() method in my Link List of the class BoxClass. BoxClass has a double length, width and height.
my BoxClass:
class BoxClass{
private:
double length;
double width;
double height;
public:
// Default constructor w/ no parameters
BoxClass(){
length = 0;
width = 0;
height = 0;
}
// Constructor with arguments
BoxClass(double boxLength, double boxWidth, double boxHeight){
length = boxLength;
width = boxWidth;
height = boxHeight;
}
// Setters and Getters
void setLength(double boxLength){
length = boxLength;
}
double getLength(){
return length;
}
void setWidth(double boxWidth){
width = boxWidth;
}
double getWidth(){
return width;
}
void setHeight(double boxHeight){
height = boxHeight;
}
double getHeight(){
return height;
}
// Returns the volume of the boxes
double Volume(){
return (length * width * height);
}
// toString method for boxes, returns "(length) x (width) x (height) string
string toString(){
return ("(" + to_string(length)+ "x" + to_string(width) + "x" + to_string(height) + ")");
}
}; // End of BoxClass() class
LinkNode.h
//Template ListNode class definition.
#ifndef LINKNODE_H
#define LINKNODE_H
template <typename T> class LinkList;
template <typename T> class LinkNode{
friend class LinkNode <T>;
public:
LinkNode(const T &);
T getData()const;
T data;
LinkNode <T> *nextPtr;
};
template <typename T> LinkNode <T>::LinkNode(const T &info):data(info), nextPtr(NULL){
// Empty body
}
template <typename T>T LinkNode<T>::getData()const{
return data;
}
#endif
Main (Creating the class, adding it to Link List
// Create the Box class
BoxClass userBox(length, width, height);
// Add box class to Link List
Box.insertNode(userBox);
Box.print();
LinkList.h print() method
template<typename T>void LinkList<T>::print()const {
// To list off nodes
int counter = 1;
if (isEmpty()) {
cout << "No boxes in list!\n";
} else {
LinkNode<T>*currentPtr = firstPtr;
cout << "Your boxes in increasing order of volume is:\n";
// while (currentPtr) {
while (currentPtr != NULL) {
// Output as "#. (length x width x height)
cout << counter << ". " << currentPtr->data << endl;
printf(" %i. %.2f\n", counter, currentPtr->data);
currentPtr = currentPtr->nextPtr;
counter++;
}
}
}
LinkList.h
//Template LinkList class definition.
#ifndef LINKLIST_H
#define LINKLIST_H
#include <iostream>
#include "LinkNode.h"
using namespace std;
template<typename T> class LinkList {
public:
LinkList();
void addNode(const T &);
void insertNode(const T &);
bool isEmpty() const;
void print() const;
private:
LinkNode<T>*firstPtr;
LinkNode<T>*getNewNode(const T &);
};
template<typename T>LinkList<T>::LinkList() :firstPtr(NULL) {
// Empty body
}
template <typename T>void LinkList<T>::insertNode(const T &value) {
LinkNode<T>*newPtr = getNewNode(value);
bool inserted = false;
if (isEmpty() || (newPtr->data < firstPtr->data)) {
newPtr->nextPtr = firstPtr;
firstPtr = newPtr;
// cout << " " << newPtr->data << " inserted at front of list.\n";
printf(" %.2f inserted at front of list.\n", newPtr->data);
} else {
LinkNode<T>*currentPtr = firstPtr;
while (currentPtr->nextPtr && !inserted) {
if (newPtr->data < currentPtr->nextPtr->data) {
// cout << " " << newPtr->data << " inserted before " << currentPtr->nextPtr->data << ". " << endl;
printf(" %.2f inserted before %.2f.\n", newPtr->data, currentPtr->nextPtr->data);
newPtr->nextPtr = currentPtr->nextPtr;
currentPtr->nextPtr = newPtr;
inserted = true;
} else {
currentPtr = currentPtr->nextPtr;
}
}
if (!inserted) {
currentPtr->nextPtr = newPtr;
printf(" %.2f inserted at the end of list.\n", newPtr->data);
}
}
}
template<typename T>bool LinkList<T>::isEmpty()const {
return firstPtr == NULL;
}
template<typename T>LinkNode<T>*LinkList<T>::getNewNode(const T &value) {
return new LinkNode<T>(value);
}
template<typename T>void LinkList<T>::print()const {
// To list off nodes
int counter = 1;
if (isEmpty()) {
cout << "No boxes in list!\n";
} else {
LinkNode<T>*currentPtr = firstPtr;
cout << "Your boxes in increasing order of volume is:\n";
// while (currentPtr) {
while (currentPtr != NULL) {
// Output as "#. (length x width x height)
cout << counter << ". " << currentPtr->data << endl;
printf(" %i. %.2f\n", counter, currentPtr->data);
currentPtr = currentPtr->nextPtr;
counter++;
}
}
}
#endif
So again, my question is- How do I go about traversing the list and calling the toString() BoxClass method? I tried everything from cout << data.toString() << endl; but that doesn't work. I've been stuck on this for days, can someone help me out?
edit: added LinkList.h
When you write template <typename T> class LinkNode{ you are specifically stating that your node class will have no built-in knowledge of the type of the node that it contains.
You have not shown us your LinkList<T> class, but obviously, the same thing applies to it: since it consists of LinkNode<T> it has to also accept a generic parameter of type <T>, so it cannot have built-in knowledge of the actual type of <T> either.
Therefore, you cannot suddenly introduce a method which has such knowledge. It does not make sense. "It does not compute".
What you need to do instead is add this print() method of yours elsewhere, and make it accept a LinkList<BoxClass>. Then, it will be able to view the LinkNodes as LinkNode<BoxClass>, and it will be able to invoke linkNode.data.toString().
The problem is that your implementation of LinkList<T> class has no way for the client code to go through each node of the list in a loop. What if we don't want to print, but do something else with each box?
In addition, it would look weird if I have a LinkList<Widget>, and I see the text when I call print():
"Your boxes in increasing order of volume is:";
I would say, "what boxes? what volume? I have Widgets, not boxes".
A more complete implementation would look something like this (caveat: This has not been compiled. It is to give you the gist of what you should be doing):
template<typename T> class LinkList {
public:
LinkList();
void addNode(const T &);
void insertNode(const T &);
bool isEmpty() const;
// this is what you're missing from the current implementation
typedef LinkNode<T>* Iterator;
Iterator begin() { return firstPtr; }
Iterator next(Iterator ptr) { return ptr->nextPtr; }
Iterator end() { return NULL; }
private:
LinkNode<T>* firstPtr;
LinkNode<T>* getNewNode(const T &);
};
Then with this, the print function need not be part of the linked list. It can live on the outside:
LinkList<BoxClass> boxList;
//...
void print()
{
if (boxList.isEmpty())
cout << "No boxes in list!\n";
else
{
int counter = 1;
cout << "Your boxes in increasing order of volume is:\n";
// get first box
LinkList<BoxClass>::Iterator curBox = boxList.begin();
// loop until no more boxes
while (curBox != boxList.end())
{
// now use curBox to do whatever you want with this box
BoxClass& b = curBox->getData();
cout << counter << ". " << b.toString();
// go to the next box
curBox = boxList.next(curBox);
counter++;
}
}
}
Note how print is no longer a member of LinkList. Also, note the typedef to give us a "nice" name for the LinkNode pointer that the client uses. The comments should be self-explanatory.
I didn't want to overcomplicate the code by introducing a "real" iterator (i.e. overloaded ++), but that operator would replace the LinkList<T>:::next() function call. I leave that to you as an additional exercise.
I was trying to build my own binary search tree. However , my tree is not getting built. Please see code below and help.
#include<iostream>
#include<string>
using namespace std;
class Binarytree
{
private:
struct node
{
int data;
node *left;
node *right;
};
node *root;
public:
Binarytree();
void insertdata(node*,int);
void deletedata();
void printdata(node*);
void userprint(char);
void getdata(int);
};
Binarytree::Binarytree()
{
root=NULL;
cout<<"Setting root as NULL"<<endl;
}
void Binarytree::insertdata(node* temp3,int temp)
{ cout << "in insert data"<<endl;
node Dummy=node();
Dummy.data=temp;
Dummy.left=NULL;
Dummy.right=NULL;
cout << "Data To be inserted is "<<temp <<endl;
if (temp3 == NULL)
{ cout<<"Found NULL ROOT"<<endl;
temp3=&Dummy;
cout << "Entered a Data in tree"<<endl;
cout<<"Data in root"<<root->data<<endl;
}
else if (temp3->data > temp)
{ cout<<"Making a Left Recursive Call"<<endl;
insertdata(temp3->left,temp);
}
else
{ cout<<"Making a right Recursive Call"<<endl;
insertdata(temp3->right,temp);
}
}
void Binarytree::getdata(int check)
{ cout <<"in getdata"<<endl;
cout << "before insertdata"<<endl;
insertdata(root,check);
}
void Binarytree::printdata(node* printrt)
{
if (printrt ==NULL)
cout << "Nothing to print";
else
{ cout << printrt->data << endl;
printdata(printrt->left);
printdata(printrt->right);
}
}
void Binarytree::userprint(char in)
{ node* data;
data=root;
if (in == 'Y' || in == 'y')
printdata(data);
}
void main()
{ Binarytree element=Binarytree();
int userdata,i=0;
bool check = true;
while(check)
{ cout <<"Please Enter your Data"<<endl;
cin >> userdata;
element.getdata(userdata);
cout<<"FUnction returned to main"<<endl;
i++;
if(i==5)
check=false;
}
element.userprint('Y');
}
The very first value is not getting inserted in root pointer. I know there are lots of code available for doing this but if i don't code it my own I feel my learning will be limited.
So please help in figuring error in this code.
Having really tried to compile and there might be other problems... but
change
void Binarytree::insertdata(node* temp3,int temp)
to
void Binarytree::insertdata(node* &temp3,int temp)
so that the node created inside insertdata really modifies the outside pointer.
and change
node Dummy=node();
Dummy.data=temp;
Dummy.left=NULL;
Dummy.right=NULL;
to
node *Dummy=new node();
Dummy->data=temp;
Dummy->left=NULL;
Dummy->right=NULL;
As I said there might be other problems... you should worry about deleting nodes and all that...
Alternative you could create nodes outside of insertdata() and keep the same signature.
Anyway, good luck
The root cause (if you'll pardon the pun) is the way you're adding things to the root of the tree. Your code creates a temporary variable called Dummy on the stack and then takes its address. That's the first mistake because that temporary variable gets destroyed when the function ends.
The second problem is that in order to change the value of a pointer that you pass to a function, you have to pass a pointer to a pointer. In other words, your member function that was insertdata(node *, int) must become insertdata(node **, int)if you want to actually change the passed pointer rather than just a local copy as your original code had done.
To illustrate that fact, try this code.
#include <iostream>
int Y = 99;
void makeitsix(int n) {
n = 6;
}
void pointToY(int *ptr) {
ptr = &Y;
}
int main()
{
int x = 5;
int *p = &x;
std::cout << "x = " << x << ", *p = " << *p << std::endl;
makeitsix(x);
pointToY(p);
std::cout << "x = " << x << ", *p = " << *p << std::endl;
return 0;
}
When makeitsix() gets called, it's only the local copy of n that is altered, and not the value of 5 that was originally passed in. Similarly, ptr in the pointToY() function is only altering a local copy of ptr and not p that was used to call the function from within main(). If it were not so, an invocation such as makeitsix(3) would lead to some very strange effects!
I took the liberty of changing things somewhat in your code to make it a little cleaner, including
giving the node structure its own constructor
creating an extractor for the Binarytree
removing the various diagnostic printout statements (for brevity)
making the tree printout look more like a tree with the root to the left and the branches extending rightward
made some member functions private
and a few other minor things. The complete working code is below:
#include<iostream>
#include<string>
class Binarytree
{
private:
struct node
{
node(int d=0) : data(d), left(NULL), right(NULL) {};
int data;
node *left;
node *right;
};
node *root;
void insertdata(node**,int);
std::ostream& printdata(std::ostream &out, node*, int depth=0);
public:
Binarytree() : root(NULL) {};
std::ostream &printTo(std::ostream &out);
void insert(int);
};
void Binarytree::insertdata(node** temp3,int temp)
{
node *Dummy=new node(temp);
if (*temp3 == NULL) {
*temp3=Dummy;
} else if ((*temp3)->data > temp) {
insertdata(&((*temp3)->left),temp);
} else {
insertdata(&((*temp3)->right),temp);
}
}
void Binarytree::insert(int check)
{
insertdata(&root,check);
}
std::ostream &Binarytree::printdata(std::ostream &out, node* printrt, int depth)
{
if (printrt != NULL)
{
printdata(out, printrt->left, depth+1);
for (int i = 0; i < depth; ++i)
out << '\t';
out << printrt->data << std::endl;
printdata(out, printrt->right, depth+1);
}
return out;
}
std::ostream &Binarytree::printTo(std::ostream &out)
{
return printdata(out, root);
}
std::ostream &operator<<(std::ostream &out, Binarytree &b)
{
return b.printTo(out);
}
int main()
{
Binarytree element;
int userdata,i=0;
bool check = true;
while(check)
{
std::cout << "Please Enter your Data" << std::endl;
std::cin >> userdata;
element.insert(userdata);
i++;
if(i==5)
check=false;
}
std::cout << "Tree:\n" << element << std::endl;
return 0;
}
I have a very silly problem that I just can't figure out. I'm trying to overload the << operator in my "PrioQueue" class. I'm still pretty new to C++ and i've tried almost every example I could find on the web but nothing works.
The PrioQueue is a template class I made that works like a normal Queue but puts the highest value it receives on the top.
PrioQueue<int> intq1(5);
intq1.push(1);
intq1.push(2);
intq1.push(1);
cout << intq1;
The << operator should write all the values that I've pushed to the queue with a '|' in between. So like this:
2 | 1 | 1 |
This is my overload operator << method.
friend std::ostream& operator<<(std::ostream& out, PrioQueue q){
while(!q.empty()){
out.write(q.pop()); //This method pops off the top value and returns it
}
return out;
}
I hope this is enough information but if not. This is my full code:
#include "stdafx.h"
#include <iostream>
#include <ostream>
using namespace std;
template <typename Type>
class PrioQueue
{
private:
Type *bottom_;
Type *top_;
int size_;
public:
PrioQueue(Type size){
bottom_ = new Type[size];
top_ = bottom_;
size_ = size;
}
friend PrioQueue operator+(PrioQueue q1, PrioQueue q2){
while(!q2.empty()){
q1.push(q2.pop());
}
return q1;
}
friend std::ostream& operator<<(std::ostream& out, PrioQueue q){
while(!q.empty()){
out.write(q.pop());
}
return out;
}
//Checks to see if the given value is bigger than the bottom character.
//If so, the bottom and the given value swap places.
//If not, the value gets placed at the top of the queue
void push(Type t){
if(*bottom_ < t){
*top_ = *bottom_;
*bottom_ = t;
}else{
*top_ = t;
}
top_++;
}
int num_items() {
return (top_ - bottom_);
}
Type pop(){
return *(bottom_++);
}
int full() {
return (num_items() >= size_);
}
int empty() {
return (num_items() <= 0);
}
void print(){
cout << "Queue currently holds " << num_items() << " items: " ;
for (Type *element=top_-1; element >= bottom_; element--) {
cout << " " << *element;
}
cout << "\n";
}
int getSize(){
return size_;
}
~PrioQueue(){ // stacks when exiting functions
bottom_ = 0;
delete[] bottom_;
}
};
void intExample(){
PrioQueue<int> intq1(5);
intq1.push(1);
intq1.push(2);
intq1.push(1);
cout << intq1;
intq1.print();
PrioQueue<int> intq2(5);
intq2.push(8);
intq2.push(2);
intq2.push(5);
intq2.print();
PrioQueue<int> intq3(10);
intq3 = intq1 + intq2;
intq3.print();
cout << intq3;
}
void charExample(){
PrioQueue<char> charq1(5);
charq1.push('t');
charq1.push('h');
charq1.push('g');
charq1.print();
PrioQueue<char> charq2(5);
charq2.push('i');
charq2.push('q');
charq2.push('k');
charq2.print();
PrioQueue<char> charq3(10);
charq3 = charq1 + charq2;
charq3.print();
}
int main(){
intExample();
charExample();
return 0;
}
This would work:
friend std::ostream& operator<<(std::ostream& out, PrioQueue q){
while(!q.empty()){
out << q.pop() << "|";
}
return out << "\n"; // if you want a newline, otherwise just "return out;"
}
Edit Note that for this to work, you will have to modify your queue to be copyable. You need to add a copy constructor and an assignment operator (see the rule of three) or use a type that is copyable and assignable to store your data (see std::vector, std::deque, or container adapter std::priority_queue if this is not an exercise).
The problem is that the out.write() expects a const char* and size. First of all, your Type will not implicitly convert to const char* and also, you're missing an argument.
Using out << q.pop() will fix the problem for you.