C++ Visual Studio 2010, compile error C3867 when implementing dynamic stack - c++

Currently working on an assignment for my datastructures class in university using stacks with dynamic memory allocation. Currently I'm getting a compile error C3867 saying I'm missing a function call from an argument list. I'm not really understanding where this error is coming from / I'm having trouble identifying what exactly is my error in my code; so I was wondering if someone might be kind enough to explain to me what it is, and maybe a friendly tip to remember so I can not have this happen again.
also, I apologize for the poor formatting, I've never posted here before sorry if its hard to read. :(
code posted below.
Thanks, and regards. :P
Header File:
#ifndef STACK_H
#define STACK_H
#include <iostream>
#include <iomanip>
struct Node
{
Node *nextPtr;
int value;
};
class Stack
{
public:
//Constructors and Deconstructers Here
Stack(); //Default Constructor
~Stack(); //Default Deconstructor
//logical methods || functions here
bool isEmpty(void); //prototype checks if stack is empty
//stack operations || function prototypes here
void push(int); //prototype to push values of type int onto the stack
int pop(); //prototype to pop values off of the stack and return a value
int top(); //prototype to return the top value
private:
Node *topPtr; //pointer to class Node Object, specifically for the top of the stack
};
#endif
Class File:
#include "CPTN278_A3_Stack_Arsenault.h"
using namespace std;
Stack::Stack()
{
topPtr = 0; //set the top pointer equal to zero.
}
Stack::~Stack()
{
while (!Stack::isEmpty())
{
Stack::pop();
}
}
bool Stack::isEmpty()
{
if(top == 0)
{
return true;
}
else
{
return false;
}
}
void Stack::push(int valueTMP)
{
Node *itemPtr = new Node;
itemPtr->nextPtr = topPtr;
itemPtr->value = valueTMP;
topPtr = itemPtr;
return;
}
int Stack::pop()
{
int returnValue; //unintialized int
Node *itemPtr; //unintialized pointer to node
returnValue = topPtr->value;
itemPtr = topPtr;
topPtr = itemPtr->nextPtr;
delete itemPtr;
return returnValue;
}
int Stack::top(void)
{
return topPtr->value; //**this is where my error is being thrown**
}

bool Stack::isEmpty()
{
if(top == 0) // <-- here is the problem
{
return true;
}
else
{
return false;
}
}
top is a function, to check its result you need top(). But I think you should be testing topPtr instead.

Before you had:
bool Stack::isEmpty()
{
if(top == 0) <-- top is a function, did you mean 'topPtr'?
{
return true;
}
else
{
return false;
}
}
Fix:
bool Stack::isEmpty()
{
return topPtr == 0;
}
That's your only build error. I'm not sure why you or the compiler thought it was in the top method. That's perfectly fine. Also there's no need to write:
if (expression_that_is_true_or_false)
return true;
else
return false;
Just do:
return expression_that_is_true_or_false;
I might be borderline preaching style here, but try to get used to understanding expressions this way. Expressions involving logical operators like ==, !=, &&, ||, <, >, etc. evaluate to true or false, so there is no need to do conditional branching only to then return what the expression originally evaluated to in the first place.
Oh and I realize this is homework, but check out std::stack later in your free time if you haven't already.

In function Stack::isEmpty(), something wrong with top.
bool Stack::isEmpty()
{
if(top == 0) // here
{
return true;
}
else
{
return false;
}
}
I think it should be as below:
if(topPtr==0)
...

Related

Binary Tree with class in c++

I'm trying to write class for binary tree in c++ but I think in inserting function I have some problem it doesnt work correctly I'm begginer in c++ and I can't find the problem.
I should write this code without using "struct" it should Compeletly write with classes
I'm so sorry beacuse my code doesn't have any comment
and also sorry for bad English
Thank you very much
#include<iostream>
using namespace std;
///////////////////////////////////////////////////////////////////////////
class Tree
{
public:
Tree* left;
Tree* right;
string info;
Tree()
{
this->left=NULL;
this->right=NULL;
this->info="";
}
Tree(string info)
{
this->left=NULL;
this->right=NULL;
this->info=info;
}
Tree(string info,Tree* left,Tree* right)
{
this->left=left;
this->right=right;
this->info=info;
}
};
/////////////////////////////////////////////////////////////////////
class LinkedList
{
public:
Tree* root;
LinkedList()
{
root=NULL;
}
void mainInsert(Tree* newroot , string info)
{
if(newroot==NULL)
{
Tree* newNode = new Tree(info);
newroot=newNode;
return;
}
if(info.compare(newroot->info)==-1)
{
mainInsert(newroot->left,info);
}
else
{
mainInsert(newroot->right,info);
}
}
void mainPrintTree(Tree* newroot)
{
if(newroot==NULL)
{
return;
}
cout<<newroot->info<<endl;
mainPrintTree(newroot->left);
mainPrintTree(newroot->right);
}
void insert(string info)
{
mainInsert(this->root , info);
}
void printTree()
{
mainPrintTree(this->root);
}
};
///////////////////////////////////////////////////////////////////////////
int main()
{
LinkedList myTree;
myTree.insert("2");
myTree.insert("1");
myTree.insert("3");
myTree.insert("7");
myTree.insert("0");
myTree.printTree();
return 0;
}
Here is a (the?) culprit:
void mainInsert(Tree* newroot, string info)
{
if (newroot == NULL)
{
Tree* newNode = new Tree(info);
newroot = newNode; // Oops, only changing a local pointer here!
return;
}
...
It is a common error of beginners: you passed a pointer to a function, change that pointer and wonder why the original pointer is still unchanged... The reason is that apart from being able to change its pointee value, a pointer is a mere variable. So the function has its local copy of the pointer, and changing it has no effect in the caller. Here a simple way is probably to return the new root:
Tree* mainInsert(Tree* newroot, string info)
{
if (newroot == NULL)
{
Tree* newNode = new Tree(info);
return newNode;
}
// remember to return newroot in other branches...
Just use that in insert:
void insert(string info)
{
this->root = mainInsert(this->root , info);
}
But there are tons of possible improvements here, like separating the public interface from the private implementation, so I would advise you to post your code on Code Review as soon as is will work without errors...
Your mainInsert is wrong: after mainInsert(newroot->left,info);, newroot->left is not modified because that argument is passed by value (BTW read this SO article article, it's about C, not C++ but the concept is the same).
The simplest here is just to pass the node by reference, which makes your code even simpler:
void mainInsert(Tree* &subTree, string info)
{
if (subTree == NULL)
{
subTree = new Tree(info);
return;
}
if (info.compare(subTree->info) == -1)
{
mainInsert(subTree->left, info);
}
else
{
mainInsert(subTree->right, info);
}
}
I renamed the newroot parameter into subTree, because there is actually only one root per tree and every node of the tree is actually a also tree.
BTW: your question about writing this code without using struct is pointless, you don't use struct at all in your code.
Hint: try to write an iterative version of mainInsert. It's pretty simple and straightforward as the problem is not inherently recursive.

C++ template class error with operator '<=>' (error C2678)

I'm attempting to make a treap class in C++. I have the .h and .cpp files for this class, as well as a test class. My 'add' method gives me the following error when I attempt to build it: "error C2678: binary '<=>': no operator found which takes a left-hand operand of type 'E' (or there is no acceptable conversion)"
Here's my code:
Treap.h
#pragma once
#include <compare>
#include <string>
#include <random>
#include <stack>
template<class E>
class Treap
{
public:
class Node {
public:
// data fields
E data; // key for the search
int priority; // random heap priority
Node* left;
Node* right;
// omitted constructor for brevity
// omitted rotation methods for brevity
};
private:
// data fields
Node* root;
// methods
// omitted reheap method for brevity
public:
// omitted constructors for brevity
// omitted methods for brevity
};
Treap.cpp
#include "Treap.h"
template<class E>
bool Treap<E>::add(E& key, int priority) {
Node* newNode = new Node(key, priority);
if (root == nullptr) {
root = newNode;
return true;
}
else {
// if key is found in tree, return false
std::stack<Node*> nodeStack;
Node* current = root;
Node* prev = nullptr;
auto n = current->data <=> key;
nodeStack.push(current);
while (n != 0 && current != nullptr) {
prev = current;
if (n > 0)
current = current->left;
else
current = current->right;
if (current == nullptr)
break;
nodeStack.push(current);
n = current->data <=> key;
}
if (n > 0)
prev->left = newNode;
else
prev->right = newNode;
// omitted method that reheaps the treap
}
return true;
}
TreapTest.cpp
#include "pch.h"
#include "CppUnitTest.h"
#include "../Treap.cpp"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace TreapTest {
TEST_CLASS(TreapTest) {
public:
TEST_METHOD(addTest) {
Treap<std::string> test;
Assert::IsTrue(test.add(std::string("p"), 99)); // this seems to be the line causing the issue
}
};
}
The lines that cause the errors are lines 13 and 26 (aka the lines with the spaceship operator).
I'm using VS 2019 and the C++ language standard is C++20.
P.S.: I'm a newbie to C++. I'm converting my existing Java code to C++ as an exercise to understand and learn C++.
Edit: OK, I made some of the changes suggested by #cdhowie and #interjay. But none of those suggestions helped make this specific issue go away (which I somewhat expected since the code compiles without the test file in the solution, meaning that the original code compiles just fine despite my dumb mistakes).
Also, #Barry, I hope these updates better suit that standard.

C++ how to reach 'stack' behaviour in this code?

I would like to ask 2 question about this code. Where I just try to simulate a stack.
Stack.h
#pragma once
namespace stackandqueue {
class Stack
{
private:
int index;
int *stackdata;
public:
Stack();
~Stack();
void push(int val);
int pop();
int top();
bool isEmpty();
};
}
Stack.cpp
#include "stdafx.h"
#include "Stack.h"
namespace stackandqueue {
Stack::Stack() : index{ 0 }
{
stackdata = new int[index];
}
Stack::~Stack()
{
delete[] &stackdata;
}
void Stack::push(int val) {
stackdata[index] = val;
index++;
}
int Stack::pop() {
int val = stackdata[index];
index--;
return val;
}
int Stack::top() {
return stackdata[index];
}
bool Stack::isEmpty() {
return index == 0;
}
}
Meaning is to let me create
Stack stack;
And then it initilizes a dynamic array with 0 as first index and that let me push, pop, top values.
First question:
Why am I having unresolved symbols for method definitions?
Second question:
About 'stackdata', you find is the right way if I want to declare an "array" with dynamic size for this behaviour?
I'm open for improvements and best practices. Im used to programming languagesbut I've never delved into c ++ and I don't want to have bad practices. So you see I am taking it from the begining.
Thanks.
I post solution reached with your help that maybe helps someone.
class Stack
{
private:
int index;
int* stackdata;
public:
Stack(int size);
~Stack();
void push(int val);
int pop();
int top();
bool isEmpty();
};
Stack::Stack(int size)
: index {0}, stackdata{new int[size]}
{
}
Stack::~Stack()
{
delete[] stackdata;
}
void Stack::push(int val) {
stackdata[index] = val;
index++;
}
int Stack::pop() {
index--;
return stackdata[index];
}
int Stack::top() {
return stackdata[index-1];
}
bool Stack::isEmpty() {
return index == 0;
}
There are several problems with this.
An array, dynamically allocated or otherwise, is not a stack/queue/vector. You're creating literally 0 ints. All of your element accesses after that have undefined behaviour. You need your array to grow, i.e. be a vector, e.g. std::vector.
delete[] &stackdata has the wrong level of indirection. You meant delete[] stackdata. You were trying to delete the pointer which was not dynamically allocated.
You're missing copy/move constructors and copy/move assignment operators so as soon as you transport a Stack anywhere it will explode. (The original instance will do a delete[] on the same pointer that the copied/moved instances will!) Read about the rule of three/five/zero.
Other than that, it looks like a stack.
The problem you don't have here is an undefined reference, which is funny because that's the only one you asked about. :) If you do indeed have such a thing, it's likely a problem with your build system (failing to compile that source file), which we cannot see.

Non void delete member function in queue class

This is the implementation of a queue class in C++. What I cant figure out is I want a function delete in which I return the deleted element, but these errors appear:
expected unqualified-id before 'delete'
expected ; at end of member declaration
When I delete the delete function, everything works fine, but not when it is there.
I'm trying to find the shortest path in an unweighted undirected graph with bfs and I need queue, specifically a queue which returns the deleted vertex.
class Queue
{
public:
Queue(int maxQueueSize):MaxSize(maxQueueSize)
{
queue=new int[MaxSize];
front=rear=-1;
}
bool isFull()
{
if(rear==MaxSize-1)
return true;
else return false;
}
bool isEmpty()
{
if(front==rear)
return true;
else return false;
}
void add(const int& x)
{
if(isFull())
return;
else
queue[++rear]=x;
}
int* delete()
{
int& x;
if(isEmpty())
return 0;
else
{
x=queue[++front];
}
return x;
}
private:
int front,rear;
int* queue;
int MaxSize;
};
'delete' is a reserved keyword for C++.
See a list of reserved keywords here.
You may better call it 'remove' or something like that.
Better yet, just use a std::queue<>, it's all well written and tested for you already.

C++ compiler error: "isLeaf() has not been declared" - but it was

#include <cstdlib>
#include <iostream>
#include "Node.h"
#ifndef HW4_H
#define HW4_H
using namespace std;
/**
You are to implement the two functions in this class.
You can add any other method or members to it as well.
However, you cannot change their signature.
**/
class HW4{
public:
int count(Node* r) const
{
if(r->next==NULL&&r->bro==NULL) { return 0;}
if(r.isLeaf())
{
return ((1+count(r->next)+count(r->bro)));
}
count(r->next);
}
/*
This method will return true if the tree rooted at node sn can answer
the demand induced by its leaves.
*/
bool canDemandBeAnswered(Node* root)
{
if(count(root)>(root.getCapacity()))
{
return 0;
exit(0);
}
else
{
return (canDemandBeAnswered(root->next)&&canDemandBeAnswered(root->bro));
}
}
/*
This method should return a linked list of nodes representing the
customers with the overall highest revenue.
The resulting list should conform to the capacity limitations.
*/
// Node* getBestCustomers(Node* root);
};
#endif
#include <cstdlib>
#ifndef NODE_H
#define NODE_H
/**
The Node class. You must implement the two methods isLeaf() and addChild(Node*) below.
Otherwise, you can add any methods or members your heart's desire.
The only limitation is that they have to be in this file.
**/
class Node {
private:
int capacity;
int price;
public:
/**
Hint: to be used for saving the Node's children and for returning the linked list
**/
Node* next;
Node* bro;
Node(){
capacity = 0;
price = 0;
}
Node(int capacity_){
capacity = capacity_;
price = 0;
}
//should return true if this node has no children, false otherwise.
//this method adds a child to this node.
int getCapacity(){
return capacity;
}
int getPrice(){
return price;
}
void setPrice(int price_){
price = price_;
}
bool isLeaf()
{
if((this->next)->capacity==0)
return 1;
else return 0;
}
void addChild(Node* child)
{
Node* temp;
if(this->next!=NULL)
{
temp=this->next;
child->bro=temp;
this->next=child;
}
else
this->next=child;
}
};
#endif
I get the following error: "isLeaf() has not been declared". I don't understand why - I declared both.
bool canDemandBeAnswered(Node* root)
{
if(count(root)>(root.getCapacity()))
This attempts to call getCapacity on a Node *. But Node * doesn't have a function called getCapacity -- Node does.
You can use (*root).getCapacity() or the shorthand, root->getCapacity().
if(r.isLeaf())
You have the same issue here. r is a Node *.
Did you mean r->isLeaf() instead of r.isLeaf(), since r is a pointer?
You should be using -> instead of . to access those functions because r is a pointer.
Member access for pointers is different. You must use the indirection operator ->. These are not the actual objects but just pointers to them.