I got these two structs
struct CamelZombie{
int hp;
int attack;
CamelZombie *next;
};
struct list_of_cz{
CamelZombie *head;
};
I've made a function to create linked list with given value:
void createCamelZombie(list_of_cz *&pZ, int z_hp, int z_attack, int N){
pZ = new list_of_cz;
pZ->head->hp = z_hp;
pZ->head->attack = z_attack;
CamelZombie *temp1 = pZ->head;
CamelZombie *temp2 = NULL;
for (int i = 0; i < N - 1 ; i++){
temp2 = new CamelZombie;
temp2->hp = z_hp;
temp2->attack = z_attack;
temp1->next = temp2;
temp1 = temp2;
}
}
Then i put it in function main like this, but then the propram crashed, don't know why.
list_of_cz *pZ = NULL;
createCamelZombie(pZ, z_hp, z_attack, N);
while (pList->head != NULL && pZ != NULL){
atPlant(numPlant(pList) - 1, pList)->hp -= pZ->head->attack;
if (atPlant(numPlant(pList) - 1, pList)->hp <= 0) deletePlant(numPlant(pList) - 1, pList);
int count = 0;
CamelZombie *z_temp;
z_temp = pZ->head;
while (z_temp){
if (count == 0) z_temp->hp -= allPlantAttack(pList, numPlant(pList) - 1);
else z_temp->hp -= allLaserAttack(pList); //trouble right here
if (z_temp->hp <= 0) deleteCamelZombie(pZ, count);
z_temp = z_temp->next;
count++;
}
Seem like i miss something when writing void createCamelZombie() 'cause the compiler tells me that z_temp->hp don't have a value. Please help me!
Preferably use an existing container like std::vector or std::list
#include <iostream>
#include <string>
#include <list>
struct CamelZombie{
std::string name; //added for demonstration purposes
int hp;
int attack;
//pointer to next zombie not required
};
std::list<CamelZombie> createCamelZombie2(int z_hp, int z_attack, int N) {
std::list<CamelZombie> result;
for (int i = 0; i < N; i++){
CamelZombie newZombie;
newZombie.name = "Zombie"+std::to_string(i);
newZombie.hp = z_hp;
newZombie.attack = z_attack;
newZombie.next = NULL;
result.push_back(newZombie);
}
return result;
}
Use the code like this.
int main() {
std::list<CamelZombie> listOfZombies2 = createCamelZombie2(10,20,10);
for(std::list<CamelZombie>::iterator list_iter = listOfZombies2.begin();
list_iter != listOfZombies2.end(); list_iter++)
{
std::cout<<list_iter->name<<std::endl;
}
}
If you really want to use your own linked list try the code below.
A seperate struct (list_of_cz) for the list is not required. Each zombie links to the next zombie. So just keep a pointer to the first zombie.
createCamelZombie function returns a pointer to the first zombie in the list (no need to use the function parameter (list_of_cz *&pZ) to get the zombie list)
Too many underscores and Z makes the code hard to read.
If you use pointers you need to clean up memory yourself.
.
struct CamelZombie{
std::string name; //added for demonstration purposes
int hp;
int attack;
CamelZombie *next;
};
CamelZombie* createCamelZombie(int z_hp, int z_attack, int N){
CamelZombie *result = NULL;
CamelZombie *work = NULL; //keep track of the last node in the list
for (int i = 0; i < N; i++){
//create new zombie
CamelZombie *newZombie = new CamelZombie();
newZombie->name = "Zombie"+std::to_string(i);
newZombie->hp = z_hp;
newZombie->attack = z_attack;
newZombie->next = NULL;
if (result==NULL) {
result = newZombie;
work =result;
} else {
work->next = newZombie;
work = newZombie;
}
}
return result;
}
Example of how to use the code.
int main() {
CamelZombie *listOfZombies = createCamelZombie(10,20,10);
CamelZombie *work = listOfZombies;
// print zombie names to screen ---------
while (work!=NULL) {
std::cout << work->name << std::endl;
work = work->next;
}
And free memory.
work = listOfZombies;
while (work!=NULL) {
CamelZombie *temp =work->next;
delete work;
work = temp;
}
Related
So I am trying to implement a hash table and I am having trouble seeing what is wrong in my class or constructor. In summary when I try to reach an element of hash table array, I can in constructor, but I cannot in the member function (I get seg fault), which leads me to believe there is something wrong with my class/ constructor doesn't work.
website::website(int input) //Constructor
{
SIZE = input;
node** hashtable = new node * [SIZE];
for (int i = 0; i<SIZE; i++)
{
hashtable[i] = NULL;
if(!hashtable[i])
{
cout<<"It works at "<<i<<"th"<<endl;//This is to check
}
}
}
int website::hashfunction(const char array []) //Hash function
{
int inputsize = strlen(array);
int value = 0;
for (int i=0; i< inputsize; i++)
{
value = value + int(array[i]);
}
value = value % SIZE;
return value;
}
These functions do what they are supposed to do
but when I run this function. I get seg fault at hashtable[place]==NULL level.
int website::insert(const mainentry& input)
{
int place = 0;
node*temp = new node;
/* Ignore this part
temp->data.topic = new char[strlen(input.topic)+1];
strcpy(temp->data.topic, input.topic);
temp->data.url = new char[strlen(input.url)+1];
strcpy(temp->data.url, input.url);
temp->data.summary = new char[strlen(input.summary)+1];
strcpy(temp->data.summary, input.summary);
temp->data.review = new char[strlen(input.review)+1];
strcpy(temp->data.review, input.review);
temp->data.rating = input.rating;
*/
place = hashfunction(temp->data.topic);
cout<<"Place is: "<<place<<endl; //Hash function works correctly
if (hashtable[place]== NULL) // THIS IS THE PART I GET SEG FAULT
{
hashtable[place] = temp;
temp->next = NULL;
return 1;
}
else
{
temp->next = hashtable[place];
hashtable[place] = temp;
return 1;
}
return 0;
}
Here is my class:
class website
{
public:
website(int input);
// ~website();
int insert(const mainentry & input);
int retrieve( char [], mainentry output [] );
int edit (mainentry & input);
int remove();
int display(char []);
int display_all();
int hashfunction(const char []);
private:
int SIZE;
node ** hashtable;
};
I am assuming I am making a beginner's mistake but I can't see what is going on, if anyone can direct me, I'd appreciate it.
You are shadowing the class's hashtable variable in the constructor by writing:
website::website(int input) //Constructor
{
SIZE = input;
node** hashtable = new node * [SIZE]; //<<-- Shadowing. you are declaring a local scope veriable called hastable, and not using the class's instance.
}
node** hashtable = new node * [SIZE];
should be
hashtable = new node * [SIZE];
Let me paste the code first
#include <iostream>
#include <algorithm>
#define MAX 100
using namespace std;
int index;
struct node{
int key;
struct node *up;
int rank;
};
struct edge{
struct node *start, *end;
int weight;
};
struct graf{
struct node *tops[MAX];
int topsAmount;
struct edge *edges[MAX];
int edgesAmount;
};
void makeSet(struct node *z, int key){
z->up = z;
z->rank = 0;
z->key = key;
}
struct node *findSet(struct node *x){
if(x!=x->up)
x->up = findSet(x->up);
return x->up;
};
struct node *returnPath(struct node *x){
cout<<"klucz: "<<x->key<<" ranga: "<<x->rank<<endl;
if(x!=x->up)
{
returnPath(x->up);
}
}
void link(struct node *x, struct node *y){
if(x->rank>y->rank)
{
y->up=x;
}
else
{
x->up=y;
if(x->rank == y->rank)
y->rank++;
}
}
void unionFun(struct node *x, struct node *y){
link(findSet(x), findSet(y));
}
bool acompare(edge lhs, edge rhs) { return lhs.weight < rhs.weight; }
struct edge *MSTKruskal(struct graf *G){
struct edge *A = new edge[MAX];
index=0;
for(int i=0; i<G->topsAmount; i++)
{
makeSet(G->tops[i],0);
}
sort(G->edges[0], G->edges[G->edgesAmount-1], acompare);
for(int i=0; i<G->edgesAmount; i++)
{
if(findSet(G->edges[i]->start) != findSet(G->edges[i]->end))
{
A[index].start = G->edges[i]->start;
A[index].end = G->edges[i]->end;
A[index].weight = G->edges[i]->weight;
index++;
unionFun(G->edges[i]->start, G->edges[i]->end);
}
}
return A;
}
int main()
{
struct node *values[11];
for(int i=0; i<10; i++)
{
values[i] = new node;
makeSet(values[i],i);
}
unionFun(values[0], values[1]);
unionFun(values[2], values[3]);
unionFun(values[1], values[2]);
unionFun(values[5], values[6]);
unionFun(values[7], values[8]);
unionFun(values[3], values[5]);
unionFun(values[0], values[7]);
for(int i=0; i<10; i++)
{
cout<<"sciezka klucza "<<i<<endl;
returnPath(values[i]);
}
struct graf *Graf = new graf;
for(int i=0; i<10; i++)
{
Graf->tops[i] = values[i];
Graf->topsAmount++;
}
struct edge *Edges = new edge[4];
Edges[0].start = values[1];
Edges[1].start = values[2];
Edges[2].start = values[3];
Edges[3].start = values[4];
Edges[0].end = values[5];
Edges[1].end = values[6];
Edges[2].end = values[7];
Edges[3].end = values[8];
Edges[0].weight = 10;
Edges[1].weight = 12;
Edges[2].weight = 11;
Edges[3].weight = 13;
Graf->edges[0] = Edges[0]; //this line was deleted after I found out that I can't compile it
Graf->edges[0]->weight = 0;
return 0;
}
I want to set new graf so firstly in for loop I add tops to my structure and it works then I want to add edges and problem appears. I thought I can just create another array of structures edge and then just set same array in Graf on same values (Graf->edges[0] = Edges[0]; last lines of the code) but it didn't compile, so I wanted to set every value of structure edge in array Graf separately (start = start, end = end etc) but debugger shows SIGSEGV on last line (Graf->edges[0]->weight = 0;) how can I fix it?
Edges[0] has type edge, but Graf->edges[0] has type edge*, i.e. the types are incompatible, which is why the assignment is not allowed.
You probably want to take the address of Edges[0] like so:
Graf->edges[0] = &Edges[0];
I'm trying to speed up my implementation of the Held-Karp Algorithm and I've been trying to figure why after nine points, it starts to become increasingly slow. I'm also utilizing xlib to help with illustrating the graph but I don't think that's the issue.
double GetMinimumRoute(int startVertex, std::vector<int> Set, Node* root)
{
printf("%d\n", CountRecursive);
CountRecursive++;
if(Set.empty())
{
Node node;
root->Nodes.clear();
root->Nodes.push_back(node);
root->Nodes.at(0).Value = Vertices[0];
root->Nodes.at(0).Selected = true;
root->CountNodes = 0;
return AdjancyMatrix[startVertex][0];
}
double totalCost = 999999999;
int selectedIndex = 0;
//root->Nodes.clear();
for(unsigned int i=0; i<Set.size(); i++)
{
Node node;
node.Selected=false;
root->Nodes.push_back(node);
root->Nodes.at(i).Value = Set.at(i);
int costOfVisitingCurrentNode = AdjancyMatrix[startVertex][Set.at(i)];
std::vector<int> newSet(Set);
newSet.erase(newSet.begin()+i);
int costOfVisitingOtherNodes = GetMinimumRoute(Set.at(i), newSet, &(root->Nodes.at(i)));
int currentCost = costOfVisitingCurrentNode + costOfVisitingOtherNodes;
if(totalCost > currentCost)
{
totalCost = currentCost;
selectedIndex = i;
}
}
root->Nodes.at(selectedIndex).Selected = true;
return totalCost;
}
I'm trying to execute the following code, everything is fine except one thing and that is tellerArray[2] is never initialized properly, it always creates problems for me, and I don't why. It creates problem for me: I came to know this fact when I debugged the code multiple times.
#include <iostream>
#include <stddef.h>
using namespace std;
class Customer {
public:
void setTime(int time) { this->_time = time; }
int getTime() { return this->_time; }
void setNextCustomer(Customer *next) { this->_next = next; }
Customer* getNextCustomer() { return this->_next;}
private:
int _time;
Customer *_next;
};
class Teller {
public:
Teller();
~Teller();
void addCustomer(Customer *customer);
int totalCustomers();
int totalTime();
private:
Customer *head;
Customer *tail;
};
Teller::Teller() {
this->head = NULL;
this->tail = NULL;
}
Teller::~Teller() {
delete head;
delete tail;
head = NULL;
tail = NULL;
}
void Teller::addCustomer(Customer *customer) {
customer->setNextCustomer(NULL);
if(head == NULL) {
head = customer;
} else {
tail->setNextCustomer(customer);
}
tail = customer;
}
int Teller::totalTime() {
int totalTime = 0;
Customer *tempCust = new Customer;
for(tempCust = head; tempCust != NULL; tempCust = tempCust->getNextCustomer()) {
totalTime += tempCust->getTime();
}
return totalTime;
}
int Teller::totalCustomers() {
int totalCustomers = 0;
Customer *tempCust = new Customer;
for(tempCust = head; tempCust != NULL; tempCust = tempCust->getNextCustomer()) {
totalCustomers += 1;
}
return totalCustomers;
}
int getLeast(int, int, int, int);
int getMax(int, int, int, int);
int main(int argc, const char*argv[]) {
Teller *tellerArray[4];
// creating four tellers ( counters )
Teller *tellerOne = new Teller();
Teller *tellerTwo = new Teller();
Teller *tellerThree = new Teller();
Teller *tellerFour = new Teller();
tellerArray[0] = tellerOne;
tellerArray[1] = tellerTwo;
tellerArray[2] = tellerThree;
tellerArray[3] = tellerFour;
char wannaBuyAnother = 'n';
int duration = 0, minTime = 0, maxTime = 0, index = 0;
do {
cout<<"Enter duration of your transaction: ";
cin>>duration;
Customer *customer = new Customer;
customer->setTime(duration);
minTime = getLeast( tellerOne->totalTime(),
tellerTwo->totalTime(),
tellerThree->totalTime(),
tellerFour->totalTime() );
for(index = 0; index < 4; index++) {
if( (tellerArray[index]->totalTime()) == minTime ) {
break;
}
}
tellerArray[index]->addCustomer(customer);
cout<<"You can stand in Queue "<<index + 1<<"\n";
cout<<"Do you want to buy another Ticket(Y/N)? ";
cin>>wannaBuyAnother;
} while ( wannaBuyAnother == 'y' || wannaBuyAnother == 'Y' );
cout<<"Number of Customers Deal By Every Teller\n";
for(index = 0; index < 4; index++) {
cout<<"T"<<index<< "= \t"<<tellerArray[index]->totalCustomers()<<"\n";
}
maxTime = getMax( tellerOne->totalTime(),
tellerTwo->totalTime(),
tellerThree->totalTime(),
tellerFour->totalTime() );
for(index = 0; index < 4; index++) {
if( (tellerArray[index]->totalTime()) == maxTime ) {
cout<<"TELLER "<<index+1<<" Deal Maximum Customers of the Day\n";
break;
}
}
return 0;
}
int getLeast(int first, int second, int third, int fourth) {
int min = first;
if( second < min ) {
min = second;
} else if ( third < min ) {
min = third;
} else if ( fourth < min ) {
min = fourth;
}
return min;
}
int getMax(int first, int second, int third, int fourth) {
int max = first;
if( second > max ) {
max = second;
} else if ( third > max ) {
max = third;
} else if ( fourth > max ) {
max = fourth;
}
return max;
}
Here is output when I debug my code.
tellerArray[0] Teller * 0xbffff308
tellerArray[1] Teller * 0x8048c64
tellerArray[2] Teller * 0x1
tellerArray[3] Teller * 0xffff
What my code is actually doing is using a linked list ( customer class ) to create a queue ( teller class ) and then based upon the time of each queue, it determines in which queue to put the next customer?
The initialisation looks fine. Those values are odd, but unless you have a specific debug build, you can't always rely on a reported pointer value being correct. However, it's possible they are being corrupted because of the following undefined behaviour in your program:
I notice that you never initialise the _next pointer on Customer to NULL, nor to you set it when you add it to the list. So your list tail always has an undefined _next pointer. This is very likely to give you problems.
You should create a default constructor on Customer and initialise _next to NULL.
One unrelated thing I will mention is that your getLeast and getMax functions do not work. Why don't you try this:
cout << getLeast(4, 3, 2, 1) << endl;
cout << getMax(1, 2, 3, 4) << endl;
The code is a bit bizarre, I don't see how the code matches the description of what it is supposed to do.
But bugs aren't hard to find, look at this code
int Teller::totalTime() {
int totalTime = 0;
Customer *tempCust = new Customer;
for(tempCust = head; tempCust != NULL; tempCust = tempCust->getNextCustomer()) {
totalTime += tempCust->getTime();
}
return totalTime;
}
At no point does your code set a value for tempCust->_next so tempCust->getNextCustomer() returns a garbage value and so from this point all bets are off, and your code could end up doing anything.
Frankly I can't see any logic to your code so I'm not sure what to do to fix it. At the very least I'd advise to to set _next to NULL in the Customer constructor.
class Customer {
public:
Customer() { this->_next = NULL; }
...
private:
...
Customer *_next;
};
As an exercise (largely an exercise in trying to write something using pointers), I'm writing a cache simulation, specifically of the pseudo least recently used system from the old 486. I'm getting an "Access violation reading location" error on the line:
int min = treeArray[set]->root->findPLRU();
Initially the treeArray seems to be initialised properly (if I pause the program at the start and take a look, it's all as should be), but when the programme breaks and I delve in to examine things the root of the tree in question isn't defined.
I feel it's quite probable that I'm making some sort of very elementary pointer mistake, which is causing the pointer to the node to be "lost" somewhere, but I've no clue what it might be. Is there something in particular I need to do to "hold on" to a pointer value?
#include "stdafx.h"
#include "stdlib.h"
#include <conio.h>
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <io.h>
#include "main.h"
//char fn[80]; // trace filename
int tf; // trace file
trace buf[BUFSZ / sizeof(trace)]; // buffer SIZE
int LRUHits = 0;
int pLRUHits = 0;
int randomHits = 0;
int height;
int cachelinenumber;
//log2 helper function
int log2(int n)
{
int i = 0;
while (n)
{
n = n >> 1;
i++;
}
return i - 1;
}
class CacheLine{
public:
int tag;
int access;
CacheLine();
};
class Cache;
class Node{
public:
bool goRight;
Node* left;
Node* right;
int leftCacheLine;
int rightCacheLine;
Node(int depth) // constructor
{
goRight = false;
if (depth < height - 1)
{
left = new Node(depth + 1);
right = new Node(depth + 1);
leftCacheLine = -1;
rightCacheLine = -1;
}
else
{
leftCacheLine = cachelinenumber;
cachelinenumber++;
rightCacheLine = cachelinenumber;
cachelinenumber++;
}
//printf("Depth: %d, Height: %d, Left: %d, Right: %d\n", depth, height, leftCacheLine, rightCacheLine);
}
~Node()
{
delete left;
delete right;
}
int findPLRU()
{
if (leftCacheLine < 0 || rightCacheLine < 0)
{
if (goRight)
{
goRight = false;
return right->findPLRU();
}
else
{
goRight = true;
return left->findPLRU();
}
}
else
{
if (goRight)
{
goRight = false;
return rightCacheLine;
}
else
{
goRight = true;
return leftCacheLine;
}
}
}
};
class Tree{
public:
Node* root;
Tree()
{
root = new Node(0);
}
~Tree()
{
delete root;
}
};
//cache class
class Cache
{
public:
CacheLine *cache;
int l, k, n, replacementPolicy;
int log2l, log2n;
int access;
Tree** treeArray;
//constructor
Cache(int ll, int kk, int nn, int _replacementPolicy)
{
l = ll;
k = kk;
n = nn;
replacementPolicy = _replacementPolicy;
log2l = log2(l);
log2n = log2(n);
cache = (CacheLine*)malloc(sizeof(CacheLine)*k*n);
for (int i = 0; i < k*n; i++)
{
cache[i].tag = 0x80000000;
cache[i].access = 0;
}
if (replacementPolicy == 1)
{
cachelinenumber = 0;
treeArray = new Tree*[n];
for (int i = 0; i < n; i++)
{
treeArray[i] = new Tree();
}
}
access = -1;
}
//destructor
~Cache()
{
free(cache);
}
//test for hit
void hit(int a)
{
access++;
int set = (a >> log2l) & (n - 1);
int tag = a >> (log2n + log2l);
CacheLine* c = &cache[set*k];
for (int i = 0; i < k; i++)
{
if (c[i].tag == tag)
{
c[i].access = access;
if (replacementPolicy == 0)
LRUHits++;
else if (replacementPolicy == 1)
pLRUHits++;
else if (replacementPolicy == 2)
randomHits++;
break;
}
}
if (replacementPolicy == 0) //LRU
{
int min = 0;
int minv = c[0].access;
for (int i = 1; i < k; i++)
{
if (c[i].access < minv)
{
minv = c[i].access;
min = i;
}
}
c[min].tag = tag;
c[min].access = access;
}
else if(replacementPolicy == 1) // pseudoLRU
{
int min = treeArray[set]->root->findPLRU();
c[min].tag = tag;
c[min].access = access;
}
else // random
{
srand(clock());
int randomNumber = rand()%k;
c[randomNumber].tag = tag;
c[randomNumber].access = access;
}
return;
}
};
void analyse (int l, int k, int n)
{
height = log2(k) + 1;
char fn[] = "ico0.trace";
if ((tf = open(fn, _O_RDONLY | _O_BINARY )) == -1) {
printf("unable to open file %s\n", fn);
exit(0);
}
LRUHits = 0;
pLRUHits = 0;
randomHits = 0;
Cache *cache0 = new Cache(l, k, n, 0); // LRU
Cache *cache1 = new Cache(l, k, n, 1); // pseudoLRU
Cache *cache2 = new Cache(l, k, n, 2); // random
int bytes, word0, a, type, burstcount;
int hits = 0;
int tcount = 0;
while (bytes = read(tf, buf, sizeof(buf)))
{
for (int i = 0; i < bytes / (int) sizeof(trace); i++, tcount++)
{
word0 = buf[i].word0;
a = (word0 & ADDRESSMASK) << 2;
type = (word0 >> TYPESHIFT) & TYPEMASK;
burstcount = ((word0 >> BURSTSHIFT) & BURSTMASK) + 1;
cache0->hit(a);
cache1->hit(a);
cache2->hit(a);
}
}
printf("Hits: %d Total: %d\n", LRUHits, tcount);
printf("Hits: %d Total: %d\n", pLRUHits, tcount);
printf("Hits: %d Total: %d\n\n\n", randomHits, tcount);
delete cache0;
delete cache1;
delete cache2;
}
int _tmain(int argc, _TCHAR* argv[])
{
//analyse(16, 1, 8);
analyse(16, 2, 512);
//analyse(16, 4, 256);
//analyse(16, 8, 128);
//analyse(16, 1024, 1);
_getch();
return 0;
}
Your question hasn't yet been pounced upon, probably because your code still doesn't compile since you've not provided main.h.
And even then it would annoy most folks trying to help you because you make no mention of the ico0.trace file that is required to prevent the code from immediately exiting.
You say int min = treeArray[set]->root->findPLRU(); access violates.
1) the value of set can never exceed the size n of your treeArray since you & n-1 the range of input values.
2) since your ~Tree() destructor is never called there will always be a treeArray[set]->root
3) since you *always create new left & right nodes whenever leftCacheLine = -1 or rightCacheLine = -1 it cannot be due to recursive findPLRUs
So, the pointer to the node is not being "lost" somewhere; it is being stomped on.
Try replacing:
int min = treeArray[set]->root->findPLRU();
c[min].tag = tag;
c[min].access = access;
with:
int min = treeArray[set]->root->findPLRU();
if (min >= k*n)
{
printf("ook\n");
}
else
{
c[min].tag = tag;
c[min].access = access;
}
and I think you will discover what's doing the stomping. ;)