I have written a templates stack linked list for an assignment I have to complete. When I run it, it prints out the first element, but then crashes. Any ideas on what could be going wrong? I have a feeling it might be the pop function, but its so basic, I'm not sure what is even wrong.
template<typename T>
struct StackNode
{
T data;
StackNode* next;
StackNode(T t, StackNode* ptr);
~StackNode();
};
template <typename T>
StackNode<T>::StackNode(T t, StackNode* ptr = nullptr)
:data(t), next(ptr)
{
}
template <typename T>
StackNode<T>::~StackNode()
{
delete next;
}
template<typename T>
struct LinkedStack
{
LinkedStack();
LinkedStack(const StackNode<T> &s);
~LinkedStack();
bool isEmpty();
void push(const T& t);
void pop();
T top();
StackNode<T>* head;
int numElements;
};
template <typename T>
LinkedStack<T>::LinkedStack()
: head(nullptr), numElements(0)
{
}
template<typename T>
LinkedStack<T>::LinkedStack(const StackNode<T> &s)
: head(nullptr), numElements(0)
{
for (auto t = s.head; t; t = t->next)
push(t->item);
}
template<class T>
LinkedStack<T>::~LinkedStack()
{
while (!isEmpty())
{
pop();
}
}
template<typename T>
bool LinkedStack<T>::isEmpty()
{
if (numElements > 0)
{
return false;
}
else
{
return true;
}
}
template<typename T>
void LinkedStack<T>::push(const T& t)
{
head = new StackNode<T>(t, head);
numElements++;
}
template<typename T>
void LinkedStack<T>::pop()
{
if (isEmpty())
{
cout << "Stack is empty." << endl;
}
else
{
StackNode<T>* oldnode = head;
head = head->next;
numElements--;
delete oldnode;
}
}
template<typename T>
T LinkedStack<T>::top()
{
if (isEmpty())
{
cout << "Stack is empty..." << endl;
}
else
{
return head->data;
}
}
int main()
{
LinkedStack<string> x;
x.push("Test");
x.push("One");
x.push("Two");
x.push("Three");
cout << "Now popping all elements of the stack:" << endl;
while (x.isEmpty() == false)
{
cout << x.top() << endl;
x.pop();
}
}
When you delete a node, you also delete the node it points to :
template <typename T>
StackNode<T>::~StackNode()
{
delete next;
}
When you pop an item, you delete the whole linked list as the deletion propagate from a node to another. The segfault is raised after deleting the last node, your programs try to delete nullptr.
The delete statement in the pop function is enough. No need to delete Stacknode.next as you do not assign it with the new keyword
I've successfully runned your code after removing the problematic delete.
Related
I have a class called stackTester that is trying to inherit from another class stackofChars. The methods defined in stackofChars that I am trying to use in stackTester are all virtual, but when I try to use them in stackTester, I get an error
request for member which is of non-class type
Here is my stackofChars.h file:
#define STACK_OF_CHARS_H
#include "node.h"
class stackofChars
{
private:
node* m_top;
public:
//constructor for the stack, takes in no paramaters
stackofChars();
//copy constructor, takes in a referance to the original stack
stackofChars(const stackofChars& orig);
//destructor for the stack, no parameters
~stackofChars();
//destructor for the copy, takes in a referance to the copy
void operator=(const stackofChars& rhs);
//pushes the stack back and creates a new node at the stop, takes in an entry, returns nothing
virtual void push(char entry);
//deletes the top entry and pushes the stack up, takes in nothing, returns nothing
virtual void pop();
//peeks at the top entry, takes in nothing, returns a char, const because nothing is changed
virtual char peek() const;
//checks if the stack is empty, takes in no parameters, returns nothing, const because nothing is changed
virtual bool isEmpty() const;
};
#endif
Here is my stackTester.h file:
#ifndef STACK_TESTER_H
#define STACK_TESTER_H
#include "stackofChars.h"
class stackTester : public stackofChars
{
public:
stackTester();
//This will call all your test methods
void runTests();
private:
//Creates an empty stack and verifies isEmpty() returns true
void test1();
//Creates an empty stack pushes 1 value, verifies isEmpty() returns false
void test2();
//Creates an empty stack, then pushes once, pops once, and verifies isEmpty returns true
void test3();
//more test methods as needed
};
#endif
If needed, here is my stackTester.cpp file:
#include "stackTester.h"
#include "stackofChars.h"
#include <iostream>
void stackTester::test1()
{
stackofChars test();
std::cout << "Test#1: Newly created stack is empty: ";
if(test.isEmpty() == true)
{
std::cout << "Pass\n";
}
else
{
std::cout << "Fail\n";
}
}
void stackTester::test2()
{
stackofChars test();
test.push(???);
std::cout << "Test#2: Push on empty stack makes it non-empty: ";
if(test.isEmpty() == true)
{
std::cout << "Pass\n";
}
else
{
std::cout << "Fail\n";
}
}
void stackTester::test3()
{
stackofChars test();
test.push(???);
test.pop();
std::cout << "Test#3: Popping all elements makes stack empty: ";
if(test.isEmpty() == true)
{
std::cout << "Pass\n";
}
else
{
std::cout << "Fail\n";
}
}
Can someone tell me why I am getting this error?
stackofChars test(); is wrong.The right way to declare a class object should be: stackofChars test; or stackofChars test{};
There is an explanation here enter link description here
This is what i want to make.
int lua:
object1 = MyObjectClass({1,2,3});
in c++
class MyObjectClass
{
public:
MyObjectClass(/*How to passed lua table here?*/)
{
}
void printmynum()
{
}
};
getGlobalNamespace(L)
.beginClass<MyObjectClass>("MyObjectClass")
.addConstructor<>()//???
.addFunction("printmynum",&MyObjectClass::printmynum)
.endClass();
I am sorry about the weak English skills.
I want to receive the table of lua from the constructor of MyObjectClass.
solved
class MyObjectClass
{
public:
MyObjectClass(lua_State* L)
{
LuaRef param = LuaRef::fromStack(L, 2);
if (param.isTable())
{
cout << param[1] << endl;
}
}
void printmynum()
{
}
};
getGlobalNamespace(L)
.beginClass<MyObjectClass>("MyObjectClass")
.addConstructor<void (*)(lua_State*)>()
.addFunction("printmynum",&MyObjectClass::printmynum)
.endClass();
If I have a templated class, I can do the following to detect if a vector was passed:
template<typename T> struct is_vector { static const bool value=false; };
template<typename T> struct is_vector<std::vector<T>> { static const bool value=true; };
template<class T>
class Parser {
public:
Parser() {}
void parse(T obj) {
if (is_vector<T>::value) {
std::cout << "vector\n";
//obj.push_back(T {});
}
else {
std::cout << "not vector\n";
}
}
};
int main() {
Parser<int> p1;
p1.parse(123);
Parser<std::vector<int>> p2;
p2.parse({ 1, 2, 3});
return 0;
}
Output:
not vector
vector
I can detect a vector, yet the compiler complains when I uncomment the push_back call:
main.cpp: In instantiation of ‘void Parser<T>::parse(T) [with T = int]’:
main.cpp:26:14: required from here
main.cpp:15:17: error: request for member ‘push_back’ in ‘obj’, which is of non-class type ‘int’
obj.push_back(T {});
~~~~^~~~~~~~~
Obviously, an int does not have a push_back function, but the vector does. The is_vector call is evaluated at runtime, but the push_back is caught at compile time.
With partial template specialization, I can do what I want:
template<typename T>
void parse(T obj) {
std::cout << "not vector: " << obj << "\n";
}
template<typename T>
void parse(std::vector<T> obj) {
std::cout << "is vector\n";
for (auto i : obj) std::cout << i << " ";
obj.push_back(T {});
std::cout << "\n";
for (auto i : obj) std::cout << i << " ";
std::cout << "\n";
}
int main() {
parse(1);
parse('a');
parse(std::vector<int> { 1, 2, 3 });
return 0;
}
Output:
not vector: 1
not vector: a
is vector
1 2 3
1 2 3 0
So, how can I combine these 2 ideas, either at compile-time or at runtime? That is, have a templated class with a function that can handle vectors and non-vectors?
What you're looking for is a new feature in C++17, if constexpr. It's the same as a regular if, except that the condition is evaluated at compile time, and when instantiating the branch(es) will discard the non-taken branch at compile time. The discarded branch does not need to well-formed. So, for your example:
template<class T>
class Parser {
public:
Parser() {}
void parse(T obj) {
if constexpr (is_vector<T>::value) {
std::cout << "vector\n";
obj.push_back(T {});
}
else {
std::cout << "not vector\n";
}
}
};
See Difference between if constexpr vs if for some more talk on the differences. You can also read the cppreference page on if statements to get a detailed overview of some of the nitty-gritty details.
I'm working on a program to learn the concept of stack-array. I'm facing a error where the stack isn't displayed properly [display() function]. Where am i going wrong??
I tried checking the code twice. it doesn't display the output from display()
#include <iostream>
#include <conio.h>
#include <process.h>
using namespace std;
const int size =50;
int pop(int [] ,int&);
int push(int [] ,int , int);
void display(int [] ,int);
int main()
{
int s[size],item,top=-1,res;
char ch='y';
while (ch=='y'||ch=='Y')
{
cout<<"\n Enter the item for insertion: ";
cin>>item;
res=push(s,top,item);
if(res==-1)
{
cout<<"\nOVERFLOW!!!";
system("pause");
exit(1);
}
cout<<"\nThe stack is :"<<endl;
display(s,top);
cout<<"More elements??";
cin>>ch;
}
cout<<"Now deletion begins\n";
ch='y';
while(ch=='y'||ch=='Y')
{
res=pop(s,top);
if(res==-1)
{
cout<<"UNDERFLOW!!";
system("pause");
exit(1);
}
else
{
cout<<"\nElement deleted is: "<<res<<endl;
cout<<"\n The stack now is: "<<endl;
display(s,top);
}
cout<<"delete elements??";
cin>>ch;
}
getch();
return 0;
}
int push(int s[],int top,int ele)
{
if(top==size-1) return-1;
else
{
top++;
s[top]=ele;
}
return 0;
}
int pop (int s[],int &top)
{
int ret;
if(top==-1) return -1;
else
{
ret=s[top];
top--;
}
return ret;
}
void display (int s[], int top)
{
if(top==-1) return;
cout<< s[top]<<"<--"<<endl;
for(int i=top-1;i>=0;i--)
{
cout<<s[i]<<endl;
}
}
the display() function should display the array elements in form of a stack.
I am practicing build a doubly linked list contains string value.
In find method, I have a NullPointer Exception
here is my code.
package LinkedList;
package LinkedList;
public class LinkedList {
// 노드 클래스
class Node {
String value;
Node prev;
Node next;
Node(String v, Node p, Node s) {
value = v;
prev = p;
next = s;
}
public String getValue() {
return value;
}
public Node getPrev() {
return prev;
}
public Node getNext() {
return next;
}
public void setPrev(Node p) {
prev = p;
}
public void setNext(Node n) {
next = n;
}
}
Node head;
Node tail;
int size = 0;
public LinkedList() {
head = new Node(null, null, null);
tail = new Node(null, head, null);
head.setNext(tail);
}
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
public String first() {
if (isEmpty()) {
return null;
}
return head.getNext().getValue();
}
public String last() {
if (isEmpty()) {
return null;
}
return tail.getPrev().getValue();
}
public void addFirst(String value) {
addBetween(value, head, head.getNext());
}
public void addLast(String value) {
addBetween(value, tail.getPrev(), tail);
}
public void addBetween(String v, Node p, Node s) {
Node newNode = new Node(v, p, s);
p.setNext(newNode);
s.setPrev(newNode);
size++;
}
public String remove(Node node) {
Node p = node.getPrev();
Node s = node.getNext();
p.setNext(s);
s.setPrev(p);
size--;
return node.getValue();
}
public String removeFirst() {
if (isEmpty()) {
return null;
}
return remove(head.getNext());
}
public String removeLast() {
if (isEmpty()) {
return null;
}
return remove(tail.getPrev());
}
public void insert(String value) {
Node current = head;
// first
if (isEmpty()) {
addFirst(value);
} else {
// check
while (current.getNext() != tail || current.getValue().compareTo(value) > 0) {
current = current.getNext();
}
// last
if (current.getNext() == tail) {
addLast(value);
} else // between
{
addBetween(value, current.getNext(), current);
}
}
}
/* !!!!!!!!!!!!!! ERORR !!!!!!!!!!!! */
public void find(String value) {
Node current = head.getNext();
while ((current != null) || !(current.getValue().equals(value)))
current = current.getNext();
if (current.getValue().equals(value)) {
System.out.println("found " + value);
} else {
System.out.println("Not found " + value);
}
}
// • Traverse the list forwards and print
// 순회
public void fowardTraverse() {
Node current = head.getNext();
System.out.print(current.getValue());
while (current.getNext() != tail) {
current = current.getNext();
System.out.print(" -> " + current.getValue());
}
}
// • Traverse the list backwards and print
// 뒤로 순회
public void backwardTraverse() {
Node current = tail.getPrev();
System.out.print(current.getValue());
while (current.getPrev() != head) {
current = current.getPrev();
System.out.print(" -> " + current.getValue());
}
}
// • Delete a node from the list
// 지우기
public String delete(String value) {
return value;
}
// • Delete/destroy the list
// 파괴하기
public void destroy() {
}
public static void main(String[] args) {
// TODO Auto-generated method stubs
LinkedList a = new LinkedList();
a.insert("a");
a.insert("b");
a.insert("c");
a.insert("d");
a.insert("e");
a.insert("f");
a.insert("g");
a.insert("h");
a.insert("i");
// a.fowardTraverse();
a.find("a");
}
I don't understand why I get a nullpointException at the line,
It suppose to put a node contains a.
Make sure you check for Non-NULL before dereferencing:
Node current = head.getNext();
and
if (current.getValue().equals(value)) {
to be replaced by
Node current;
if(head != NULL) current = head.getNext();
and
if (current != NULL && current.getValue().equals(value)) {
Because your Head is empty...(No pun intended)
before Addfirst calling..your structure:
head=[null,null,tail],tail=[null,head,null];
you are sending ("a",head,tail)
and your storing it in new node making it a structure like:
head=[null,null,newNode]==>newNode["a",head,tail]==>tail[null,newNode,null]
So search will compare null to a (in find) giving you the error .....
---Edit 1:
#JanghyupLee, My Bad, Didn't do a closer look on find method...however , I found that in condition of "if" you are using condition
current != null || ......
After first line that is ( current=head.next)..current becomes not null..
which is causing the condition in while to ignore the right part of '||' (short circuit) until current has a value of null...
Once the current becomes null then it goes for the next statement to check for value..causing null pointer exception