It will work if we use Any Primitive Data Type but not Working for ADT Even though all copy constructor ">>" "<<" "=" operators are overloaded and also copy constructor is written you can see every code below Thanks in advance
void main(){
Array <Item> c;//It will work if we use Any Permitive Data Type but not Working for ADT Even though all copy constructor / >> << operators are overloaded
Item obj(334,"Mango Juice",90,"Drinks",10);
c.insertAtStart(obj);
c.insertAtStart(obj);/////The program Crashes Here!!
c.insertAtStart(obj);
c.PrintArray();
cout<<endl;`
////while Array.h is given below
`
#ifndef H_ARRAY
#define H_ARRAY
#include<iostream>
using namespace std;
template<class T>
class Array
{
private:
T *a;
int size; // total size
int length_used; // used size
public:
Array():a(NULL),size(0),length_used(0){}
void insertAtStart( T val){
if(isEmpty()){
a=new T();
a[0]=val;
length_used++;
size++;
cout<<"Pehli condition"<<endl;
}
else{
if(size>length_used){
shiftRight();
a[0]=val;
length_used++;
cout<<"jab size bara ho length_used"<<endl;
}
else if(size==length_used){
cout<<"jab size or length_used braber ho jao 3rd condiot"<<endl;
resizeByOne();
shiftRight();
a[0]=val;
length_used++;
}
}
}
void insertAtEnd( T val){
if(isEmpty()){
a=new T;
a[0]=val;
length_used++;
size++;
}
else{
if(size>length_used){
a[length_used+1]=val;
length_used++;
}
else if(size==length_used){
resizeByOne();
a[length_used]=val;
length_used++;
}
}
}
void deleteFromStart(){
if(isEmpty()){
cout<<"Container is Empty"<<endl;
}
else{
a[0]=='\0';
shiftLeft();
size--;
length_used--;
}
}
void deleteFromEnd(){
if(isEmpty()){
cout<<"Container is Empty"<<endl;
}
else{
a[length_used]='\0';
length_used--;
size--;
}
}
void PrintArray(){
for(int i=0;i<size;i++)
cout<<a[i]<<endl;
}
////////////////////Helper functions///////////////////////
bool isEmpty(){
if(a=='\0')
return 1;
return 0;
}
void shiftRight(){
int tempIterator=size;
for(int i=tempIterator-1;i>=0;i--)
a[i]=a[i-1];
}
void shiftLeft(){
int tempIterator=length_used;
for(int i=0;i<size;i++)
a[i]=a[i+1];
a[0]=NULL;
}
void resizeByOne(){
T *temp=new T[size+1];
for(int i=0;i<length_used;i++)
temp[i]=a[i];
a=NULL;
delete []a;
a=temp;
size++;
}
};
#endif`
void shiftRight()
{
int tempIterator=size;
for(int i=tempIterator-1;i>=0;i--)
a[i]=a[i-1];
}
Last iteration leads to a[0] = a[-1] which can cause access violation, try i>0 as end condition. Access violation in this case is pretty tricky. If memory at a[-1] is accessible (for instance some data is allocated there) then no exception/crash will occur. Exception occurs in undeterministic way.
BTW
a=NULL;
delete []a;
In resizeByOne() method. It will not cause any exceptions (delete is secured), but for sure will cause memory leak.
Related
Following codes are my own API for index prior queue.When I test insert function,I get wrong answer.Then I debug codes,I found that the value of array qp changed after executing sentence----item[k]=vwhich is in insert function.Why the value of array qp changed after assigning value to array item?
template <class T>
class IndexPriorQueue{
private:
int index;//the num of items
int size;//capacity
int* pq;//index binaryheap
int* qp;//qp[pq[i]]=pq[qp[i]]=i
T* item;//item array;
public:
IndexPriorQueue(int qsize){//constructor function
size=qsize;
index=0;
pq=new int(size+1);
qp=new int(size+1);
item=new T(size+1);
for(int i=0;i<size+1;i++)
qp[i]=-1;
}
void insert(int k,T v){
if(contain(k)){
cout<<"index is already in queue"<<endl;
return;
}
//cout<<"insert"<<endl;
item[k]=v;//debug,after excuting this sentence,the value of qp exchanged??
pq[++index]=k;
qp[k]=index;
swim(index);
}
bool contain(int k){
return qp[k]!=-1?1:0;
}
void swim(int j){
while(j>1){
if(item[pq[j/2]]<item[pq[j]]){
exch(j/2,j);
j=j/2;
}else{
break;
}
}
}
void exch(int m,int n){
int temp=pq[m];
pq[m]=pq[n];
pq[n]=temp;
qp[pq[m]]=m;
qp[pq[n]]=n;
}
void display(){
cout<<"item:";
for(int i=1;i<size+1;i++){
cout<<item[i]<<" ";
}
cout<<endl;
cout<<"pq:";
for(int i=1;i<size+1;i++){
cout<<pq[i]<<" ";
}
cout<<endl;
cout<<"qp:";
for(int i=1;i<size+1;i++){
cout<<qp[i]<<" ";
}
cout<<endl;
}
};
Following codes are main function
int main(){
cout<<"before insert:"<<endl;
IndexPriorQueue<char> ipq(10);
ipq.display();
ipq.insert(1,'a');
cout<<"after insert:"<<endl;
ipq.display();
return 0;
}
The problems is your allocations. Take for example
new T(size+1)
That allocates one object of type T and initializes it to the value size + 1 (i.e. it calls the T constructor with size + 1).
If you need to allocate an "array" you should use square brackets [] as in
new T[size+1]
That will allocate an array of size + 1 number of T objects.
A much better solution though, is to use std::vector instead of doing it all manually yourself.
#include<iostream>
#include<vector>
using namespace std;
class Stack
{
public:
int top;
vector<int> v;
Stack(int size)
{
top=0;
cout<<"Enter the values"<<endl;
for(int i=0; i<size; i++)
{
int val;
cin>>val;
v.push_back(val);
top++;
}
}
void push(int val)
{
v.push_back(val);
top++;
}
int pop()
{
int x=v[top];
top--;
return x;
}
void disp()
{
for(int j=top; j<=0; j--)
cout<<v[j]<<' ';
}
};
int main()
{
Stack s(3);
int k=s.pop();
cout<<k;
return 0;
}
I am trying to learn the basics of OOP.
Here, my Stack constructor and push function are working fine, but there is a problem with the pop and disp functions.
I'm assuming that I am using an incorrect syntax to access the elements of a vector(maybe?). Can anyone tell me where I am going wrong?
Also, the value of k always comes out to be 0.
You can use the vector functions
int k = s.back();
s.pop_back();
cout << k;
more informationhttp://www.cplusplus.com/reference/vector/vector/back/
You have a off-by-one index error.
The way you have implemented your class, when there are N items in the stack, the value of top is N.
Hence, top is not a valid index to access the elements of v. You can use:
int pop()
{
int x=v[top-1];
top--;
return x;
}
or
int pop()
{
top--;
int x=v[top];
return x;
}
As some of the other answers say, you can use the built-in vector functions to do these things (see pop_back and back.
However, if you want to define your own, I would use the vector.at(index) function. Addressing the values with the index as you have works, but it doesn't do any bounds checking at() does. Which would solve your problem above where your index isn't correct for the zero-based indexing of a vector.
So I'm making a really rudimentary implementation of a circular list. I haven't made the remove function yet. Whenever I run the cpp, I get a seg fault 11. Any feedback would be much appreciated. Thank you.
#include <iostream>
using namespace std;
struct node{
node* next=NULL;
bool tail= false;
int contents;
};
node* start;//start is a pointer that exists at the start of the list before the first element
class CircList{
node *seek;
public:
CircList (){ //creates a list of one node that points to itself
node *b= new node;
b->contents=0;
b->next = b;
start->next=b;
b->tail=true;
}
bool empty(){
if(start->next==NULL){
return true;
}
return false;
}
int size(CircList a){
if(start->next==NULL){
cout<<"size is 0 \n";
return true;
}
seek=start->next;
for(int i=0; i++;){
if(seek->tail==true){
cout<<"size is "<<i;
}
seek=seek->next;
}
return 0;
}
void insert(int pos, int val){
if(start->next ==NULL){//if inseting when the list is empty
node *b= new node;
b->next = b;
b->tail=true;
return;
}
node *b= new node;
b->contents= val;
seek=start->next;
for(int i=0;i<=pos; i++){
if(seek->tail==true){//if inserting at the end
seek->tail=false;
b->tail=true;
seek->next=b;
b->next=start->next;
}
if(pos==i){//if inserting between two nodes
b->next = seek->next;
seek->next = b;
}
seek=seek->next;
}
}
void remove(int a){
seek=start->next;
for(int i=0;i<=a-1; i++){
if(i<a){
seek=seek->next;
}
if(i==a-1){
}
}
}
void display(){
cout<<start->next->contents; //will also be completed in the near future
seek=start->next;
for(int i=0; ;i++){
if(seek->tail==false){
cout<<seek->contents<<"\n";
}
if(seek->tail==true){
cout<<seek->contents<<"\n";
return;
}
}
}
};
That was the .h file. The following is the cpp. I just plugged in numbers to test. I want to get the program running so that I can test how it behaves.
#include <iostream>
#include "CircList.h"
using namespace std;
int main(){
CircList a;
a.insert (5,5);
a.insert (5,5);
a.insert (1,4);
a.insert (20,65);
a.insert (3,7);
a.size(a);
a.display();
}
I kept treating start as a node instead of a pointer. By making start = Null and replacing all the "start->next"'s with "start", I got it to compile and run. But now it's only infinitely inserting nodes with a value of 0 in the contents.
Edit: I fixed it. By changing that weird for loop in the display function to a while loop, it doesn't do infinite inserts of the node in the constructor, anymore. It seems to work decently enough now.
This here causes a seg fault
start->next=b;
because start is NULL at the start of the program so you are de-referencing a null pointer.
instead set start to the first node in your constructor
start = b;
Your global variable start is an uninitialized pointer, yet you dereference it all over the place.
my code right now is just a simple stack that has push, pop, and display methods. How can I change my stack so that the size of the stack dynamically resizes based on the number of elements entered? So, for example, if the stack is full, I create a new stack that is twice the size of the original, and copy the data to the new stack.
Thanks.
#include <iostream>
#include <stdexcept>
using namespace std;
class Stack
{
private:
int *p;
int top,length;
public:
Stack(int = 0);
~Stack();
void push(int);
int pop();
void display();
};
Stack::Stack(int size)
{
top=-1;
length=size;
while(length <= 0) //If the stack size is zero, allow user to mention it at runtime
{
cout<<"Stack of zero size"<<endl;
cout<<"Enter a size for stack : ";
cin >> length;
}
p=new int[length];
}
Stack::~Stack()
{
delete [] p;
}
void Stack::push(int elem)
{
if(top==(length-1)) //If the top reaches to the maximum stack size
{
throw overflow_error("Can't push onto a full stack");
}
else
{
top++;
p[top]=elem;
}
}
int Stack::pop()
{
if(top==-1)
{
throw underflow_error("Can't pop from an empty stack");
}
int ret=p[top];
top--;
length--;
return ret;
}
void Stack::display()
{
for(int i = 0; i <= top; i++)
cout<<p[i]<<" ";
cout<<endl;
}
int main()
{
int len;
cout<<"Enter a size for stack : ";
cin >> len;
Stack s1(len);
try{
s1.push(1);
s1.display();
s1.push(2);
s1.push(3);
s1.push(4);
s1.push(5);
s1.display();
s1.pop();
s1.display();
s1.pop();
s1.display();
s1.pop();
s1.display();
s1.pop();
s1.display();
s1.pop();
s1.display();
}
catch(overflow_error){
cerr<< "Illegal operation. Cannot push onto a full stack.";
return -1;
}
catch(underflow_error){
cerr<< "Illegal operation. Cannot pop from an empty stack.";
return -1;
}
}
void Stack::push(int elem)
{
if(top==(length-1)) //If the top reaches to the maximum stack size
{
int* newp = new int[length * 2];
std::memcpy(newp, p, sizeof(int) * length);
delete[] p;
p = newp;
top++;
p[top]=elem;
length*=2;
}
else
{
top++;
p[top]=elem;
}
}
The stack class in the standard library (std::stack) solves this by delegating to a container class such as std::vector. That's slightly cheating, though.
However, the idea behind std::vector<> is fairly straightforward and reusable. When you hit the maxiumum size, do the following things in order:
Allocate new memory. No big problem if it fails (no data lost)
Copy all existing elements over. Use std::uninitialized_copy not std::copy
Swap the new and old pointer
Delete the old objects
Free the old allocation
One simple way is to double the stack size each time pushing a new element would overflow the stack. In that instance, you detect the potential overflow and then you would use declare a new int array that is twice the size of the old one and then copy the old array into this new array and reassign the pointer to that new array and delete the old array. The are other more optimal ways, but that is a simplistic way of doing it, you can use up considerably more memory than is necessary to add the new item, but it's a lot faster than reallocating with every new item that would overflow your stack.
Instead of throwing the exception overflow_error("Can't push onto a full stack") you can allocate more memory using new and copy the contents to that memory and release the previously allocated memory(memory swapping).
void Stack::push(int elem)
{
if(top==(length-1)) //If the top reaches to the maximum stack size
{
//throw overflow_error("Can't push onto a full stack");
int *pTemp = new int[length + 10/*value u want to increment*/];
memcpy(p,pTemp,length); //for using this include stdlib
delete[] p;
p = pTemp;
}
top++;
p[top]=elem;
}
I am getting a very strange error in my code. This assignment is for a class I'm taking and essentially we are learning how to implement a hash table. The error i'm getting is when I try and rehash to a larger size. Here's the portion of the code giving me the problem, and I'll explain more fully what the problem is.
if(htable->size>=htable->cap)
{
cout<<htable->cap<<endl;
HashTable tempht=*htable;
delete htable;
htable=new HashTable((tempht.cap * 2) + 1);
for (size_t i=0; i<tempht.cap; i++)
{
Node* n=tempht.table[i];
while (n!=NULL)
{
htable->add(n->item);
n=n->next;
}
}
if (htable->table[0]==NULL)
{
cout<<"HOORAY!"<<endl;
}
}
if (htable->table[0]==NULL)
{
cout<<"HOORAY!"<<endl;
}
else
{
cout<<htable->table[0]->item<<endl;
}
htable is a HashTable variable. In the HashTable class it contains an array Node* (Nodes are just objects I created that contain a string and a pointer to the next item in the chain). This part of the code is simply trying to rehash to a larger table. The issue I'm getting is once I exit the first if statement, my table's first value no longer equals NULL (the test I'm running rehashes a table with nothing in it to a table that still has nothing in it, but has a larger capacity). When I run the code, the first htable->table[0]==NULL passes while the second does not, despite there being no changes other than exiting the if statement (my expected result is that the table[0] should be NULL). My best guess is it's some kind of scoping error, but I honestly can't see where the problem is. Any help would be greatly appreciated.
Edit: Just to clarify, the initial hash table has a capacity of 0 (this is one of the project requirements). So when i try to add an item to the table, this if statement is executed (since the size is 0 and the cap is 0, we have to maintain a load factor of 1). I can confirm that once the table reaches the first and second "Hooray" checks, that htable->cap (which is the total capacity of the array) is 1, which is what it should be. The only thing that is getting messed is bucket 0 (which in this case is the only bucket). For whatever reason, it's null before exiting the if statement but not after.
I'm posting my whole HashTable class, let me know if you find anything.
#pragma once
#include <iostream>
#include <string>
#include <fstream>
#include "Node.h"
using namespace std;
class HashTable
{
public:
Node** table;
int size;
int cap;
HashTable (int c)
{
size=0;
cap=c;
table = new Node*[cap];
if (cap>0)
{
for (size_t i=0; i<cap; ++i)
{
table[i]=NULL;
}
}
}
~HashTable()
{
delete table;
}
size_t hash(string thing)
{
size_t total=0;
int asci;
char c;
size_t index;
for (size_t i=0; i<thing.length(); i++)
{
total=total*31;
c=thing[i];
asci=int(c);
total=asci+total;
}
index=total%cap;
cout<<"index"<<index<<endl;
system("pause");
return index;
}
void add(string thing)
{
size_t index;
index=hash(thing);
cout<<"index "<<index<<endl;
system("pause");
Node* temp=table[index];
if (temp==NULL)
{
cout<<"Here"<<endl;
system("pause");
}
else
{
cout<<"Here2"<<endl;
system("pause");
cout<<"temp"<<temp->item<<endl;
system("pause");
}
Node* n = new Node(thing);
cout<<"n"<<n->item<<endl;
system("pause");
if (temp==NULL)
{
table[index]=n;
}
else
{
while (temp->next!=NULL)
{
temp=temp->next;
}
temp->next=n;
}
size++;
}
Node* find(string search)
{
Node* n= NULL;
size_t index;
if(cap!=0)
{
index=hash(search);
Node* temp=table[index];
while (temp!=NULL)
{
if (temp->item==search)
{
n=temp;
return n;
}
}
}
return n;
}
void remove (string thing)
{
if (find(thing)==NULL)
{
return;
}
else
{
size_t index;
index=hash(thing);
Node* temp=table[index];
if (temp->item==thing)
{
table[index]=temp->next;
delete temp;
}
while (temp->next!=NULL)
{
if (temp->next->item==thing)
{
Node* temp2=temp->next;
temp->next=temp->next->next;
delete temp2;
break;
}
}
}
size--;
}
void print(ofstream &ofile)
{
for (size_t i=0; i<cap; i++)
{
Node* n=table[i];
ofile<<"hash "<<i<<":";
while (n!=NULL)
{
ofile<<" "<<n->item;
n=n->next;
}
}
}
};
Well, this is C++, and I'm more a Java guy, but I'll take a stab at it.
Turns out the problem IS with the
HashTable tempht=*htable;
delete htable;
block after all.
See, the first line there says "copy all of the members from *htable into tempht". So now tempht and htable SHARE their table memory, since table is just a pointer to memory that was allocated at construction, and you just copied the pointer. You wanted it to copy the nodes inside table, but it didn't do that.
So now you have two different HashTable objects with the same pointer value in table. Now, when tempht is freed, the destructor calls free on the table pointer, which effectively frees the table data in both objects htable and tempht.
What you really want to do is write a copy constructor, or do something like:
HashTable *tempht=htable;
htable=new HashTable((tempht->cap * 2) + 1);
for (size_t i=0; i<tempht->cap; i++)
{
Node* n=tempht->table[i];
while (n!=NULL)
{
htable->add(n->item);
n=n->next;
}
}
if (htable->table[0]==NULL)
{
cout<<"HOORAY!"<<endl;
}
delete tempht;
See how all I've really done is change tempht to a pointer, using it to point to the old hashtable while you copy all the nodes from it to the new htable object, then deleting the old Hashtable.