C++ pointer linked list - c++

So I am new to c++ sorry if this is not to clear.
I have a class:
class Item
{
int noItem;
int qItem;
public:
Item(int noItem, int qItem)
{
this->noItem = noItem;
this->qItem = qItem;
}
int getNoItem()
{
return noItem;
}
int getQntItem()
{
return qItem;
}
};
Then the following class:
class Element
{
public:
Element()
{
data = NULL;
}
//to set and access data hold in node
void setElement(Item *data)
{
this->data = data;
}
Item* getElement(void)
{
return(data);
}
private:
Item *data;
};
This one also:
class ListeChainee
{
public:
ListeChainee()
{
courant = NULL;
}
void ajoutListe(Item *data)
{
Element *newData;
//set data
newData->setElement(data);
//check if list is empty
if( courant == NULL)
{
//set current pointer
courant = newData;
}
}
//get data from element pointed at by current pointer
Item* elementCourant(void)
{
if(courant != NULL)
{
return courant->getElement();
}
else
{
return NULL;
}
}
private:
//data members
Element *courant; //pointer to current element in list
};
The code is missing some stuff for other things, but my problem is this:
int main(int argc, char* argv[])
{
ListeChainee listeCH;
Item i1(123,456);
listeCH.ajoutListe(&i1);
cout << listeCH.elementCourant()->getNoItem();
system("pause");
return 0;
}
I expect 123 to be outputted, but I see some other number. Not sure why.
Thanks.

Your Element *newData doesn't have an instance of Element class, so it will crash when you try to access the instance pointed by newData.
Try to change Element *newData; to Element *newData = new Element;.
ps.: Don't forget to delete it when you don't need the instance any more.

This method is writing to uninitialized memory:
void ajoutListe(Item *data)
{
Element *new;
//set data
new->setElement(data); // Right here, "new" is an uninitialized pointer
//check if list is empty
if( courant == NULL)
{
//set current pointer
courant = new;
}
}
I'm surprised this compiles (does it?). This code should also crash.
The strange number you're getting is surely some random part of memory. You may want to think more about memory management -- there are numerous problems here. When ajoutListe is called, why does the courant member only get set if it's NULL? Do we just leak the new Element? How do we actually traverse this list?

Related

C++ "Bus error: 10" and working with pointers

I'm doing a Data Structures exercise and I have been blocked since yesterday with a bus error, which I reckon is because I'm doing bad things with the memory. But I cannot figure out what exactly.
These are the requirements that I have established for the practice:
able to add a product (any way will do) to the list
able to retrieve the product in the list at the current position (next, prev, moveToStart, moveToEnd… there's cursor pointer, called "actual" here)
any changes I do to the retrieved product should be updated in the data structure (ie. list::retrieve(*product), product->visits++)
This is the code that I have. Apologies about the var names, I have to do it in spanish and therefore names are in spanish.
class producto { // My product
public:
string marca;
double precio;
int visitas;
int compras;
producto () {}
producto (string M, double P, int V = 0, int C = 0) : marca(M), precio(P), visitas(V), compras(C) {}
};
class nodo {
public:
producto valor; // value
nodo *siguiente; // next
nodo *anterior; // prev
nodo (producto P, nodo *A = NULL, nodo *S = NULL) : valor(P), anterior(A), siguiente(S) {}
};
class lista {
private:
nodo *inicio;
nodo *final;
nodo *actual;
public:
lista();
bool esta_vacia(); // is empty?
bool es_final(); // is the end?
int insertar(producto p); // insert given p
void moverPrincipio(); // "move to beginning"
void siguiente(); // "next"
void imprimir(); // "print"
int leer(producto *p); // read, return 0 or 1 if successful, return product by ref
};
lista::lista() {
this->inicio = NULL;
this->final = NULL;
this->actual = NULL;
}
bool lista::esta_vacia() {
return (this->inicio == NULL);
}
bool lista::es_final() {
return (this->actual == NULL);
}
void lista::moverPrincipio() {
this->actual = this->inicio;
}
void lista::siguiente() {
if(!this->es_final()) {
this->actual = this->actual->siguiente;
}
}
void lista::imprimir() {
int i = 1;
producto *p;
this->moverPrincipio();
while(!this->es_final()) {
if(this->leer(p) == 0) {
cout << i << ".- ##" << p->marca << "##, Views ##" << p->visitas << "##\n";
p->visitas++;
i++;
this->siguiente();
}
}
}
int lista::leer(producto *p) {
if(this->actual != NULL) {
*p = this->actual->valor;
return 0;
} else {
return 1;
}
}
int lista::insertar(producto p) {
if(this->esta_vacia()) {
nodo *tmp = new nodo(p);
this->inicio = tmp;
this->final = this->inicio;
} else {
nodo *tmp = new nodo(p, this->final);
this->final->siguiente = tmp;
this->final = tmp;
}
return 0;
}
I have removed unnecessary code. This is how I'm using it (and failing miserably):
lista *productos = new lista();
productos->insertar(producto("Shoes", 19.90));
productos->insertar(producto("Socks", 25.00));
// I should expect views = 0
productos->imprimir();
// But now, views = 1
productos->imprimir();
Upon execution, the only thing I get is "Bus error: 10" when doing imprimir ("print"), the first time. Insertion works without errors (but something could be wrong there too).
My idea is to hold the product inside the node, and give a reference to its location when returning it, so that any changes are reflected there too (for example, increase the view or purchase counter of a retrieved element, reflects the change when reading the list later).
I'd be extremely thankful if someone could point out the mistakes I'm doing here.
Thanks!!
UPDATE Here's a compilable example.
You pass a pointer to lista::leer and you want to write a value to it. You will be writing in unallocated memory. Probably, what you wanted was a pointer to the actual element.
First of all, you need to modify the signature:
int lista::leer(producto **p);
note the double star, since we will be writing the pointer itself.
Then, you have to assign a pointer to actual->valor to it in lista::leer:
*p = &(this->actual->valor);
Finally, you have to pass a pointer to p in lista::imprimir:
if(this->leer(&p) == 0) {
// ...
}
Alternatively, you might modify lista::leer to return a pointer and check if it is nullptr/NULL.

Implementation of stack in C++ without using <stack>

I want to make an implementation of stack, I found a working model on the internet, unfortunately it is based on the idea that I know the size of the stack I want to implement right away. What I want to do is be able to add segments to my stack as they are needed, because potential maximum amount of the slots required goes into 10s of thousands and from my understanding making the size set in stone (when all of it is not needed most of the time) is a huge waste of memory and loss of the execution speed of the program. I also do not want to use any complex prewritten functions in my implementation (the functions provided by STL or different libraries such as vector etc.) as I want to understand all of them more by trying to make them myself/with brief help.
struct variabl {
char *given_name;
double value;
};
variabl* variables[50000];
int c = 0;
int end_of_stack = 0;
class Stack
{
private:
int top, length;
char *z;
int index_struc = 0;
public:
Stack(int = 0);
~Stack();
char pop();
void push();
};
Stack::Stack(int size) /*
This is where the problem begins, I want to be able to allocate the size
dynamically.
*/
{
top = -1;
length = size;
z = new char[length];
}
void Stack::push()
{
++top;
z[top] = variables[index_struc]->value;
index_struc++;
}
char Stack::pop()
{
end_of_stack = 0;
if (z == 0 || top == -1)
{
end_of_stack = 1;
return NULL;
}
char top_stack = z[top];
top--;
length--;
return top_stack;
}
Stack::~Stack()
{
delete[] z;
}
I had somewhat of a idea, and tried doing
Stack stackk
//whenever I want to put another thing into stack
stackk.push = new char;
but then I didnt completely understand how will it work for my purpose, I don't think it will be fully accessible with the pop method etc because it will be a set of separate arrays/variables right? I want the implementation to remain reasonably simple so I can understand it.
Change your push function to take a parameter, rather than needing to reference variables.
To handle pushes, start with an initial length of your array z (and change z to a better variable name). When you are pushing a new value, check if the new value will mean that the size of your array is too small (by comparing length and top). If it will exceed the current size, allocate a bigger array and copy the values from z to the new array, free up z, and make z point to the new array.
Here you have a simple implementation without the need of reallocating arrays. It uses the auxiliary class Node, that holds a value, and a pointer to another Node (that is set to NULL to indicate the end of the stack).
main() tests the stack by reading commands of the form
p c: push c to the stack
g: print top of stack and pop
#include <cstdlib>
#include <iostream>
using namespace std;
class Node {
private:
char c;
Node *next;
public:
Node(char cc, Node *nnext){
c = cc;
next = nnext;
}
char getChar(){
return c;
}
Node *getNext(){
return next;
}
~Node(){}
};
class Stack {
private:
Node *start;
public:
Stack(){
start = NULL;
}
void push(char c){
start = new Node(c, start);
}
char pop(){
if(start == NULL){
//Handle error
cerr << "pop on empty stack" << endl;
exit(1);
}
else {
char r = (*start).getChar();
Node* newstart = (*start).getNext();
delete start;
start = newstart;
return r;
}
}
bool empty(){
return start == NULL;
}
};
int main(){
char c, k;
Stack st;
while(cin>>c){
switch(c){
case 'p':
cin >> k;
st.push(k);
break;
case 'g':
cout << st.pop()<<endl;
break;
}
}
return 0;
}

Create Stack in C++ with Push, Pop etc

We are trying to create a C++ program that works like a stack.
The following instructions are given:
There should be several methods:
We have to use this definition of the StackElement:
struct StackElement {
int digit;
StackElement* predecessor;
};
The problem now is how to create the push-function without an next parameter as there was with ordinary lists. The same for the pop function.
We accomplished to get push() create a new StackElement and pop() delete the new Element, but with 2 new Elements, those methods aren't working properly.
Global parameter stack0:
StackElement *stack0 = new StackElement;
This is the code for the push-function:
StackElement push(int z){
StackElement *stack1 = new StackElement;
stack1->digit = z;
stack1->predecessor = NULL;
stack0->predecessor = stack1;
stack1 = stack0;
This is the pop() method:
void pop(){
StackElement *stack1 = new StackElement;
if (stack0!=NULL){
stack1->digit = 0;
stack0->predecessor = NULL; //predecessor = NULL;
}
}
And finally the main method:
int main()
{
int z;
create();
cout << "Which number to the stack?" << endl;
cin >> z;
push(z);
pop();
print();
return 0;
}
We thought about creating a new StackElement, that would work as a 'pseudo'-StackElement and would always stay on top so that the 'real' element on the top would always be the predecessor of the pseudo-Element - but we think this would be against how the stack should work.
So do you guys have any clues on how to proceed? Is there something we are just missing?
1st) Why not using std::stack?
2nd) Stack should be LIFO. That means your stack0 should always be the newest one... This leads to:
StackElement* stack0 = NULL; // until C++11
// StackElement* stack0 = nullptr; // since C++11
void push(int z) {
StackElement *stack1 = new StackElement;
stack1->digit = z;
stack1->predecessor = stack0;
stack0 = stack1;
}
void pop() {
if(stack0) {
StackElement *tmp = stack0;
stack0 = stack0->predecessor;
delete tmp;
}
}
You don't need the allocate a new one in the pop function. This will end in a huge memory leak.
What you meant by pseudo is called root element and is sometimes used in sequences. But not necessary here, since stack0 is the root or in this case the end (the first element and the end).
A better approach would be to encapsulate it in a class as ryrich mentioned in his answer. And the best approach would be using the C++-given std::stack.
You're on the right track here. To keep track of your elements, you need a class. Something like:
class Stack{
private:
StackElement *last_data, *first_data;
public:
Stack():last_data(NULL), first_data(NULL){}
void push(int digit);
void pop();
};
Have the push/pop functions part of the Stack class. For example, push:
void Stack::push(int digit)
{
StackElement *p=new StackElement();
p->digit = digit;
if(last_data)
p->predecessor=last_data;
else // empty stack
{
p->predecessor=NULL;
first_data = p;
}
last_data=p;
}
Hope this helps.
Edit: I'll add pop function for completeness:
void Stack::pop()
{
if (last_data)
{
StackElement *tp = last_data;
last_data = last_data->predecessor;
delete tp;
}
}
if the stack is full and we try to put something in it then it will give us the error of stack overflow
void IntStack::push()
{
clrscr();
int num;
if(top>=stackSize)
cout<<"stack Overflow"<<endl;
else
{
cout<<"Enter Number=";
cin>>num;
top++;
stackArray[top]=num;
}
}

node array declaration

I am trying to initialize a node array in the node class, they are private members:
#include<iostream>
#include<string>
using namespace std;
class Data
{
public:
long data;
Data(long dd)
{
data=dd;
}
void displaydata()
{
cout<<data <<" "<<endl;
}
};
class node
{
//these are what i have changed
const static int order=4;
int numitems;
node *parent;
vector<node>childarray(order);
vector<Data>itemarray(order-1);
};
but unfortunately it does not compile, the errors are:
1>c:\users\dato\documents\visual studio 2010\projects\234_tree\234_tree\234_tree.cpp(26): error C2061: syntax error : identifier 'order'
1>c:\users\dato\documents\visual studio 2010\projects\234_tree\234_tree\234_tree.cpp(27): error C2061: syntax error : identifier 'order'
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
From the following java code.
class DataItem
{
public long dData; // one data item
//--------------------------------------------------------------
public DataItem(long dd) // constructor
{ dData = dd; }
//--------------------------------------------------------------
public void displayItem() // display item, format “/27”
{ System.out.print(“/”+dData); }
//--------------------------------------------------------------
} // end class DataItem
////////////////////////////////////////////////////////////////
class Node
{
private static final int ORDER = 4;
private int numItems;
private Node parent;
private Node childArray[] = new Node[ORDER];
private DataItem itemArray[] = new DataItem[ORDER-1];
// -------------------------------------------------------------
// connect child to this node
public void connectChild(int childNum, Node child)
{
childArray[childNum] = child;
if(child != null)
child.parent = this;
}
// -------------------------------------------------------------
// disconnect child from this node, return it
public Node disconnectChild(int childNum)
{
Node tempNode = childArray[childNum];
childArray[childNum] = null;
return tempNode;
}
// -------------------------------------------------------------
public Node getChild(int childNum)
{ return childArray[childNum]; }
// -------------------------------------------------------------
public Node getParent()
{ return parent; }
// -------------------------------------------------------------
public boolean isLeaf()
Java Code for a 2-3-4 Tree 479
LISTING 10.1 Continued
{ return (childArray[0]==null) ? true : false; }
// -------------------------------------------------------------
public int getNumItems()
{ return numItems; }
// -------------------------------------------------------------
public DataItem getItem(int index) // get DataItem at index
{ return itemArray[index]; }
// -------------------------------------------------------------
public boolean isFull()
{ return (numItems==ORDER-1) ? true : false; }
// -------------------------------------------------------------
public int findItem(long key) // return index of
{ // item (within node)
for(int j=0; j<ORDER-1; j++) // if found,
{ // otherwise,
if(itemArray[j] == null) // return -1
break;
else if(itemArray[j].dData == key)
return j;
}
return -1;
} // end findItem
// -------------------------------------------------------------
public int insertItem(DataItem newItem)
{
// assumes node is not full
numItems++; // will add new item
long newKey = newItem.dData; // key of new item
for(int j=ORDER-2; j>=0; j--) // start on right,
{ // examine items
if(itemArray[j] == null) // if item null,
continue; // go left one cell
else // not null,
{ // get its key
long itsKey = itemArray[j].dData;
if(newKey < itsKey) // if it’s bigger
itemArray[j+1] = itemArray[j]; // shift it right
else
{
itemArray[j+1] = newItem; // insert new item
Please help me to convert code easily, do I have to declare the order as public? I have tried but it does not work, I have also tried declaration of order outside of the class, like
const int node::order=4
but have had no success yet, what is the problem? I need array which holds members, size should be order or 4. When I was reading book, author said what you need while writing java code in C++ from this book, it says pointer, so I have added pointer, but no success yet.
The lines
node *childarray[]=new node[order];
Data *itemarray[]=new Data[order-1];
are in error here. Beside that you can not assign like this in the class, you also have the declaration wrong. You are declaring e.g. childarray to be an array of pointers, but you are creating it as a simple array. Change declarations to
node *childarray;
Data *itemarray;
To actually do the allocation you have to do it in a constructor.
However, I really recommend you use std::array (or possibly std::vector) instead.
Edit: Using std::array:
struct node
{
static const int ORDER = 4;
int numitems;
node* parent;
std::array<node*, ORDER> childarray;
std::array<Data*, ORDER - 1> itemarray;
node()
: numitems{0},
parent{nullptr},
childarray{{nullptr}},
itemarray{{nullptr}}
{ }
};
Now childarray and itemarray are arrays with ORDER and ORDER - 1 (respectively) number of pointers, all initialized to nullptr (what NULL should now).

error: request for member '..' in 'this', which is of non-class type '--* const'

My first ever question here. Please excuse me, I have just entered into C++ and was starting up with DS. STACK!!!
My code: I think
using namespace std;
typedef char stackElement;
class Stack
{
public:
stackElement *contents; //dynamically allocated: as we do not know what would be the size of our array.
int top, maxSize; // current Top index in the array
//max size of the array; we need it to know if the array is full
Stack(int maxSize)
{
contents = new stackElement(maxSize);
this.maxSize = maxSize;
if(contents == NULL)
{
cout<<"Insufficient memory";
exit(1);
}
top = -1;
}
~Stack()
{
delete [] contents;
contents = NULL;
maxSize = 0;
top = -1;
}
bool isEmpty()const
{
return top < 0;
}
bool isFull() const
{
return top == maxSize - 1;
}
void push(stackElement element)
{
if(isFull())
{
cout<<"STACK IS ALREADY FULL";
exit(1);
}
top = top + 1;
contents[top] = element;
}
};
int main()
{
cout<<"STACK IMPLEMENTATION";
int i = 1;
Stack s1(i);
s1.push('a');
s1.push('1');
return 0;
}
I am getting this error:
error: request for member 'maxSize' in 'this', which is of non-class type 'Stack* const'
If at all, you'd have to write this->maxSize = maxSize;, since this is a pointer.
But better not to write that at all and instead use the constructor-initializer list:
explicit Stack(int m)
: contents(new stackElement[m]), top(-1), maxSize(m)
{
// nothing else to do
}
I also added explicit so you don't accidentally convert 5 into a Stack.
You also wrote the array initialization wrong.
Also, you don't need to check that contents is not null: When new fails, it exits with an exception, it does not return a null pointer. (That behaviour would make no sense when you think in terms of objects.)
It is crucial to note that you have at most one naked new-expression in your constructor. Anything else is an exception-safety disaster, and a sign that you need to refactor and use single-responsibility resource-managing classes.
The destructor should just be: ~Stack() { delete [] contents; } Everything else is pointless waste.
Imagine you had to pay for every line of code you write. Be patient, lose the source, think.
Write
this->maxSize = maxSize;
instead of
this.maxSize = maxSize;
The this is a pointer type, not a reference type
this->maxSize instead of this.maxSize