i have a program with 3classes.
first one is for defining a node(my node is an array with 9 elements) - 2nd one contains some functions - 3rd is defining a static stack(I have a stack with 100members that each member is an array with 9members)
suppose that in main(), I call one of the functions from 2nd class(for example expand() ). expand function is supposed to push a node into stack(push into UN) and update the stack pointer. After that for example I want to have access to top node of stack and pop that node using main(). but I'm successful. when I watch the UN and top node through debug tool, I see that their amount is being reset after each push(stack doesn't accept new elements). whats wrong?
here is some parts of code that is needed:
#include<iostream>
using namespace std;
#define max 100
class node
{
public:
int node_n[9];
friend class func;
friend class stack;
};
node n;
class node;
class func
{
public:
func();
void expand(node,stack);
friend class stack;
};
class node;
class stack
{
private:
int sp;//stack pointer
public:
node un[max];//saves expanded noded(children)
stack();
int isempty(); //this will show whether stack is empty or not
int isfull(); //this will show whether stack is full or not
void push(node);
node pop();
};
//****************************
stack::stack()
{
sp=-1;
}
//****************************
int stack::isempty()
{
if(sp==-1)
return true;
else
return false;
}
//****************************
int stack::isfull()
{
return sp==max-1;
}
//****************************
node stack::pop() //un=un-[n]
{
for(int k=0;k<=8;k++)
n.node[k]=un[sp].node[k];
sp--;
return n;
}
//****************************
void stack::push(node n ) //un=un+{x1....xn}
{
sp++;
for(int k=0;k<=8;k++)
un[sp].node[k]=n.node[k];
}
//****************************
void func::expand(node n,stack st)
{
if ( n.node_n[0]==0 )
{
if(n.node_n[1]==0)
{
n.node_n[0]=1;
n.node_n[1]=1;
st.push(n);
.
.
.
//******************************
int main()
{
func b;
stack st;
node n2;
node s; //initial state
node g; //goal state
for(int h=0;h<=8;h++)
{
s.node[h]=0;
g.node[h]=1;
}
//n2=s;
st.push(s);
Lable1:
n2=st.pop();
b.expand(n2,st);
goto Lable1;
system("pause");
return(0);
}
This function
void func::expand(node n,stack st)
is taking the st parameter by value, meaning that it has its own copy of st and any changes it makes will only affect that copy.
What you probably want is to pass st by reference, so that the function can make changes to the original passed in object. To do this, change the function declaration and definition to:
void func::expand(node n,stack &st)
Related
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.
I have been solving a question, Dijkstra's Algorithm, in C++. I've implemented it using adjacency list.
So I have a class for a node, a class for a minHeap, and a class for the Graph.
class node
{
int vertex,weight;
node *next;
friend class Graph;
friend class minHeap;
public:
node();
node(int,int);
};
node::node(){
vertex=weight=0;
next=0;
}
node::node(int v,int wt){
vertex=v;
weight=wt;
next=0;
}
Do I define the minHeap class this way (without a friend function) and create an object in the getDijkSP() function normally, which allows me to use the object only in that function?
class minHeap
{
node *heap;
int heapSize,capacity,*pos;
public:
minHeap(int);
void addElement(node);
node extractMin();
void minHeapify(int);
void decreaseKey(int,int);
};
minHeap::minHeap(int cap){
heap=new node[capacity=cap];
heapSize=-1;
pos=new int[cap]();
} //eliminating other methods
class Graph
{
node **adjList;
int v;
bool *visited;
public:
Graph(int);
void addEdge(int,int,int);
void removeEdge(int,int);
bool existsEdge(int,int);
void getDijkSP();
};
Graph::Graph(int vertices){
adjList=new node*[v=vertices];
for(int i=0;i<v;i++)
adjList[i]=NULL;
}
void Graph::getDijkSP(){
minHeap hp(v); //here
hp.addElement(node(0,0));
for(int i=1;i<v;i++)
hp.addElement(node(i,INT_MAX));
while(!hp.isempty()){
node temp=hp.extractMin();
cout<<temp.vertex<<" "<<temp.weight<<endl;
for(node *current=adjList[temp.vertex];current;current=current->next)
hp.decreaseKey(current->vertex,current->weight+temp.weight);
}
}
(OR) Do I define the minHeap class with a friend function, so that I can create an object of the minHeap class using the new keyword? (And this helps me define the minHeap object in the scope of the Graph class, so that I can use it in all of its functions for other capabilities as well.)
class minHeap
{
node *heap;
int heapSize,capacity,*pos;
friend class Graph; //say like this
public:
minHeap(int);
void addElement(node);
node extractMin();
void minHeapify(int);
void decreaseKey(int,int);
};
minHeap::minHeap(int cap){
heap=new node[capacity=cap]();
heapSize=-1;
pos=new int[cap]();
}
class Graph
{
node **adjList;
int v;
bool *visited;
minHeap *hp; //and do this
public:
Graph(int);
void addEdge(int,int,int);
void removeEdge(int,int);
bool existsEdge(int,int);
void getDijkSP();
};
Graph::Graph(int vertices){
adjList=new node*[v=vertices];
for(int i=0;i<v;i++)
adjList[i]=NULL;
hp=new minHeap(v); //dynamic allocation
}
void Graph::getDijkSP(){
hp->addElement(node(0,0));
for(int i=1;i<v;i++)
hp->addElement(node(i,INT_MAX));
while(!hp->isempty()){
node temp=hp->extractMin();
cout<<temp.vertex<<" "<<temp.weight<<endl;
for(node *current=adjList[temp.vertex];current;current=current->next)
hp->decreaseKey(current->vertex,current->weight+temp.weight);
}
}
I have read this and a few other articles, but specifically want to know the advantages, disadvantages and the appropriateness of both the methods for such similar kinds of questions.
I've provided the constructors for the classes for better clarity.
Short answer would be NO. I would suggest you to read up on smart pointers and rewrite this whole mess. In C++ there is no real reason to use manual allocation in so simple project as this ever.
Also instead of assigning 0 or NULL to a pointer use nullptr, which is C++ symbol only for null pointers unlike the previous mentioned C values that are actually just a int 0 which may cause some unintentional errors.
Edit in response to your comment:
So I've decided to rewrite your code using actual modern C++ instead of this C code with simple classes. In your whole example there are almost no pointers or dynamic allocations needed. I wasn't absolutely sure who exactly should own the actual nodes so from the example I assumed that the MinHeap should. Also I didn't get the point of MinHeap::pos and Graph::visited from what I could see. I can explain any part of that code in more detail, just ask which.
Here is the code:
class Node {
// Only friend class required if you insist on keeping members of Node private.
// If they aren't meant to change, consider declaring them as public and const.
template <unsigned Size> friend class Graph;
public:
Node(int v, int wt) : vertex(v), weight(wt) {}
private:
// Default values written in here right after declarations
// There is no need for a default constructor. You never call it anyway.
int vertex;
int weight;
Node* next = nullptr;
};
// Template parameter because of internal use of std::array.
// If the capacity shouldn't be constant, use std::vector and remove template.
template <unsigned Capacity>
class MinHeap {
public:
// No constructor needed
// ---------------------
// One small tip: write parameter names in function declarations
// even if they aren't needed there for better readability of your code.
void addElement(Node n) { /* impl */ }
Node extractMin() { /* impl */ }
unsigned capacity() { return Capacity; }
bool isEmpty() { return heap.isEmpty(); }
private:
// Default values written in here right after declarations
int heapSize = -1;
std::array<Node, Capacity> heap;
};
// Template parameter because of internal use of std::array.
// If the vertex count shouldn't be constant, use std::vector and remove template.
template <unsigned Vertices>
class Graph {
public:
// No constructor needed
// ---------------------
void getDjikSP() {
hp.addElement({0, 0});
for (unsigned i = 1; i < hp.capacity(); ++i)
hp.addElement({0, INT_MAX});
while (!hp.isEmpty()) {
Node tmp = hp.extractMin();
std::cout << tmp.vertex << " " << tmp.weight << std::endl;
for (Node* current = adjList[tmp.vertex]; current != nullptr; current = current->next)
hp.decreaseKey(current->vertex, current->weight + tmp.weight);
}
}
private:
// Default values written in here right after declarations
std::array<Node*, Vertices> adjList;
MinHeap<Vertices> hp;
};
There is still a lot of space for improvements of this code, for example the MinHeaP::extractMin should maybe return Node&& if it is removed from the heap or const Node& if it should return a reference to the top, etc. To address all the problems and inefficiencies this can still have I would need to see the full code with all functions.
In the code below I attempt to create a linked list of strings. I then use the linked list to store output generated by a function (named myFunction) which calls itself recursively. When testing/debugging the code, I noticed that if I print the contents of the linked list after executing the function (which should add items to the linked list) nothing prints out. However, if I attempt to print the linked list after adding items from inside the function it works fine.
It appears that the entire linked list is deleted after the call to myFunction. On the other hand, I'm using dynamic memory allocation when I add elements to the linked list so I don't see the issue.
Please help!
#include <cstdlib>
#include <iostream>
template <class T>
class node{
public:
node *next;
T data;
node(){next=0;};
void print();
};
template <class T>
void node<T>::print(){
std::cout << data;
}
template <class T>
class List{
public:
node<T> *head;
List(){head=0;};
void add(T data);
void print();
int len();
};
template <class T>
int List<T>::len(){
int i=0;
node<T> *current=head;
while(current!= 0){
i++;
current=current->next;
}
return i;
};
template <class T>
void List<T>::add(T myData){
node<T> *current=head;
if(head==0){
head= new node<T>;
head->data=myData;
}
else{
while(current->next!=0){
current=current->next;
}
current->next = new node<T>;
current->next->data=myData;
}
}
template <class T>
void List<T>::print(void){
node<T> *current=head;
if(head==0){
return;
}
else{
do{
std::cout << current->data << " ";
current=current->next;
}while(current!=0);
}
}
void myFunction(List<std::string> myList, int n, std::string starter, int leftParens, int rightParens){
int remainingLength = leftParens+rightParens;
if(remainingLength==0){
myList.add(starter);
std::cout <<myList.len() << std::endl;
}
if(leftParens >0){
myFunction(myList, n, starter+"(", leftParens-1, rightParens);
}
if(leftParens==0 and rightParens >0){
myFunction(myList, n, starter+")", leftParens, rightParens-1);
}
}
int main(int argc, char** argv) {
List<std::string> myList;
myFunction(myList, 5, "", 5, 5);
std::cout <<myList.len();
}
You are passing myList to myFunction by value. Any changes made to myList in the function are changes to the copy, not the original myList in main.
Change myFunction so that it accepts its argument by reference. Then, any changes made to it in myFunction will also be visible in main.
void myFunction(List<std::string>& myList, int n,
// ^^
std::string starter, int leftParens, int rightParens){
You need to use reference if you want to update the variable in the caller context (in other words, if you want to change the variable in main).
Whenever a class allocates memory, you probably need to follow the "rule of three" (constructor, copy-constructor, copy-assignment operator). If you don't, you'll get into trouble if you ever make a copy of the original class [like your call to myFunction as it currently stands]
#include<iostream>
#include<stdio.h>
#include<stdlib.h>
using namespace std;
struct node
{
int data;
struct node *next;
};
struct stack
{
node *head;
};
void push(struct stack *stack1,int data)
{
struct node *new_node= new node;
new_node->data=data;
if(stack1->head!=NULL)
new_node->next=stack1->head;
else
new_node->next=NULL;
stack1->head=new_node;
}
void pop(struct stack *stack1)
{
node *temp= new node;
if(stack1->head==NULL)
cout<<"EMPTY"<<endl;
else
{
temp=stack1->head;
stack1->head=(stack1->head)->next;
int t;
t=temp->data;
free(temp);
cout<<t<<" ";
}
}
void show(struct stack *stack1)
{
node *new_node=new node;
new_node=stack1->head;
if(stack1->head==NULL)
{
cout<<"EMPTY"<<endl;
return;
}
while(new_node!=NULL)
{
cout<<new_node->data<<" ";
new_node=new_node->next;
}
}
void peek(struct stack *stack1)
{
if(stack1->head==NULL)
cout<<"EMPTY";
else
cout<<stack1->head->data<<" ";
}
int main()
{
int temp,temp2;
struct stack *stack1=new stack;
stack1->head=NULL;
while(1)
{
cin>>temp;
switch(temp)
{
case 0: exit(0);
case 1: cin>>temp2;
cout<<endl;
push(stack1,temp2);
break;
case 2: pop(stack1);
cout<<endl;
break;
case 3: peek(stack1);
cout<<endl;
break;
case 4: show(stack1);
cout<<endl;
break;
}
}
return 0;
}
From the C++ Standard
1.3.14 [defns.parameter]
parameter formal argument
formal parameter
object or reference declared as part of a
function declaration or definition or in the catch clause of an
exception handler that acquires a value on entry to the function or
handler
From the C Standard
3.16 1 parameter
formal parameter formal argument (deprecated)
object declared as part of a function declaration or definition that
acquires a value on entry to the function, or an identifier from the
comma-separated list bounded by the parentheses immediately following
the macro name in a function-like macro definition
Thus for example in this function declaration
void push(struct stack *stack1,int data);
stack1 and data are formal parameters. They require values (arguments) on entry to the function.
Take into account that because stack1 is declared as pointer to struct stack then any changes of the object pointed to by the pointer will be keep in the object after exiting the function.
I have following code:
/* Example OOPBEI03.CPP */
#include <iostream>
using namespace std;
typedef char item;
class stack
{
private:
int p;
protected:
item *st;
public:
stack(int m=100)
{
st = new item[m];
p = 0;
}
~stack()
{
delete [] st;
}
void push(item v)
{
st[p++] = v;
}
item pop()
{
return st[--p];
}
int empty()
{
return !p;
}
};
class queue : public stack
{
private:
int q;
item *qp;
public:
queue(int m=50):stack(m)
{
q = 0;
qp = st;
}
~queue()
{
delete qp;
}
item deque()
{
return qp[q++];
}
};
int main()
{
stack s(50);
queue q(20);
s.push('a');
q.push('b');
s.push('c');
q.push('d');
cout<<"pop "<<s.pop()<<endl;
cout<<"pop "<<s.pop()<<endl;
cout<<"deque "<<q.deque()<<endl;
cout<<"deque "<<q.deque()<<endl;
cout<<"empty queue? "<<q.empty()<<endl;
cout<<"empty stack? "<<s.empty()<<endl;
getchar();
return 0;
}
I get at the end of main() in Visual Studio following error: "Debug Assertion Failed! ... _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)".
If I uncomment the delete operation either in the destructor of the class queue or stack (I uncomment only one operation!), I have no problems.
How can I solve this?
Deleting qp should me the same as newing (it's term of mine))).
delete [] qp;
^^
But in this particular case deleting qp should be removed at all
you're deleting the pointer both in the stack base class and in the queue derived class.
let your stack class handle the ownership, don't delete it also in queue
by the way you should make copy construction and copy assignment private, or else handle it (known as the "rule of three"); otherwise these classes can easily be used in ungood ways...
in code that isn't just for learning, just use std::stack and std::queue instead of implementing such classes yourself
std::stack and std::queue are class templates with customizable underlying container type