Create a randomly connected set of nodes? - c++

I'm trying to write a function, generate_labyrinth(), that creates a fixed number of randomly connected nodes. Each node is connected with three other nodes.
Here is what I have now:
labyrinth.h:
#ifndef LABYRINTH_H
#define LABYRINTH_H
// node
class Room {
public:
Room ()
: room_number(0), left_door(nullptr),
center_door(nullptr), right_door(nullptr) { }
// data member
int room_number;
// pointers to other nodes
Room* left_door;
Room* center_door;
Room* right_door;
};
//=================================================
class Labyrinth {
public:
Labyrinth (int s) : size(s) { generate_labyrinth (); }
private:
// number of nodes
int size;
// root node
Room* entrance;
// Helper functions
int random_number (int from, int to);
int random_number_without_i (int min, int max, int i);
// Initialiazation function
void generate_labyrinth ();
};
#include "labyrinth.cpp"
#endif
labyrinth.cpp:
// Class Labyrinth member implementations
int Labyrinth::random_number (int min, int max) {
static bool seed_initialized = false;
if (!seed_initialized) {
seed_initialized = true;
srand((unsigned int) time(NULL));
}
return rand() % (max - min + 1) + min;
}
int Labyrinth::random_number_without_i (int min, int max, int i) {
int res = random_number(min, max);
while (res == i){
res = random_number(min, max);
}
return res;
}
void Labyrinth::generate_labyrinth () {
// create "size" number of nodes
entrance = new Room[size];
// initialize Room (node) data members
for (auto i = 0; i < size; ++i) {
entrance[i].room_number = i;
}
// connect each room with three others
int first_room = 1;
int last_room = size - 1;
for (int i = 1; i < size; ++i) {
// avoid connecting a room with itself
int left_goes_to = random_number_without_i (first_room, last_room, i);
int center_goes_to = random_number_without_i (first_room, last_room, i);
int right_goes_to = random_number_without_i (first_room, last_room, i);
entrance[i].left_door = (&entrance[left_goes_to]);
entrance[i].center_door = (&entrance [center_goes_to]);
entrance[i].right_door = (&entrance [right_goes_to]);;
}
// TEST IF NODES POINT TO EACH OTHER
for (auto i = 0; i < size; ++i) {
if (entrance[i].left_door == nullptr || entrance[i].center_door == nullptr ||
entrance[i].right_door == nullptr) {
std::cout <<"Uninitialized pointer value\n";
}
}
getchar();
}
main:
#include <iostream>
#include <time.h>
#include "labyrinth.h"
//=================================================
int main()
{
int cave_size = 20;
Labyrinth cave(cave_size);
}
It appears that after the node initialization in generate_labyrinth () the three pointers, left_room, center_room, right_room remain uninitialized, i.e. the output I get is :
Uninitialized pointer value
Questions:
Why aren't the pointers in the nodes initialized?
Is there another way to generate a randomly connected set of nodes?
Note: I'm not using an insert() function as the number of nodes is fixed and determined during the construction of the data structure.

You generate connections for first_room to last_room, which are rooms 1 to size-1.
// connect each room with three others
int first_room = 1;
int last_room = size - 1;
for (int i = 1; i < size; ++i) {
But when you check the connections you start with room 0 (probably supposed to be the entrance itself).
// TEST IF NODES POINT TO EACH OTHER
for (auto i = 0; i < size; ++i) {

Related

Discrete Event Simulation Algorithm debug

I am working on a discrete event simulation program in C++. My output is completely incorrect but all the output values are pretty close to the correct output. I have tried debugging my algorithm but I couldn't find any errors. Below is my main algorithm for the simulation.
I implemented the event priority queue using a min heap and array. I am not allowed to use any STL libraries. The FIFO queue used in the code is a linked list. When I print the event time at the top of the priority queue, the events are not always getting passed in ascending order (which I think is how event priority queues are supposed to work) and I do not understand why. The ascending order is breached mostly around event completion times. Please help!
#include <iostream>
#include <fstream>
#include "PQueue.h"
#include "SPqueue.h"
#include "LinkedList.h"
using namespace std;
int serverCount; //number of servers
Spqueue spq; //priority queue for servers
Pqueue pq; //priority queue for events
LinkedList list; //FIFO queue to put arriving events in
double totalTime; //variables for statistics calculation
double timeNow;
double totalWait;
int ql;
int qlength = 0;
double totalQlength;
int time = 0;
bool available(); //checks availability of servers
int main() {
ifstream fin;
fin.open("Sample2.txt");
if (!fin.good())
cerr << "Couldn't find file/corrupted file" << endl;
fin >> serverCount; //reads number of servers and efficiency
//from file
for (int i = 0; i < serverCount; i++) {
server s;
fin >> s.effi;
s.status = true;
s.count = 0;
spq.insert(s);
}
//reads first event from file
event e;
fin >> e.eventTime;
fin >> e.serviceTime;
e.eventType = -1;
pq.insert(e);
int i = 1;
//while priority queue is not empty
while (!pq.isEmpty()) {
timeNow = pq.getArrivalTime(1);
while (time < pq.getArrivalTime(1)) {
totalQlength = totalQlength + list.getLength();
time++;
}
//get event from priority queue
if (pq.getServer(1) == -1) { //if arrival event, add to FIFO queue
list.AddTail(pq.getArrivalTime(1), pq.getServiceTime());
if (list.getLength() > qlength) {
qlength = list.getLength();
}
//read next arrival event from file
if (!fin.eof()) {
event e;
fin >> e.eventTime;
fin >> e.serviceTime;
e.eventType = -1;
pq.insert(e);
i++;
}
}
else //must be customer complete event
{
spq.setIdle(pq.getServer(1)); //set the server to idle
}
pq.deleteMin(); //remove the evnt from priority queue
//if FIFO queue is not empty and servers are available
//process event
if ((list.isEmpty() == false) && (available() == true)) {
list.getHead();
int s = spq.getMin();
spq.setBusy(s); //set server to busy
spq.incrementCustNumber(s); //increment number of customers
//served
double waitTime = timeNow - list.getHead().arrivalTime;
totalWait = totalWait + waitTime;
double serviceT = spq.getEffi(s) * list.getHead().serviceTime;
double eventT = list.getHead().arrivalTime +serviceT;
event e2;
e2.eventTime = eventT;
e2.serviceTime = list.getHead().serviceTime;
e2.eventType = s;
pq.insert(e2); //add customer complete event to the priority
//queue
list.RemoveHead(); //remove head from FIFO
}
totalTime = pq.getArrivalTime(1);
}
fin.close();
return 0;
}
bool available() {
bool ava = false;
for (int i = 1; i <= serverCount; i++) {
if (spq.getStatus(i) == true) {
ava = true;
break;
}
}
return ava;
}
Below is the priority queue implementation:
#include <iostream>
#include <fstream>
#include "PQueue.h"
using namespace std;
Pqueue::Pqueue() {
inde = 0; //length of heap
}
void Pqueue::insert(event i) { //inserts new element into the heap array and maintains min heap property
inde++;
pqueue[inde] = i;
siftup(inde);
}
int Pqueue::getServer(int i) {
return pqueue[i].eventType;
}
void Pqueue::siftup(int i) { //shifts element up to the correct position in the heap
if (i == 1)
return;
int p = i / 2;
if (pqueue[p].eventTime > pqueue[i].eventTime)
{
swap(pqueue[i], pqueue[p]);
siftup(p);
}
}
void Pqueue::deleteMin() { //removes element at the root of the heap
swap(pqueue[inde], pqueue[1]);
inde--;
siftdown(1);
}
void Pqueue::siftdown(int i) { //shifts element to its position in the min heap
int c = i * 2;
int c2 = (i * 2) + 1;
if (c > inde) return;
int in = i;
if (pqueue[i].eventTime > pqueue[c].eventTime)
{
in = c;
}
if ((c2 < inde) && (pqueue[i].eventTime > pqueue[c2].eventTime))
{
in = c2;
}
if (pqueue[c].eventTime < pqueue[c2].eventTime) {
in = c;
}
if (in != i) {
swap(pqueue[i], pqueue[in]);
siftdown(in);
}
}
void Pqueue::swap(event& i, event& j) {
event temp;
temp = i;
i = j;
j = temp;
}
bool Pqueue::isEmpty() { //checks if the priority queue is empty
if (inde == 0) return true;
else
return false;
}
double Pqueue::getArrivalTime(int i) {
return pqueue[i].eventTime;
}
double Pqueue::getServiceTime() {
return pqueue[1].serviceTime;
}
There are five servers with varying efficiency. The most efficient idle server is to be used. For this, I sorted the array of servers efficiency wise in the beginning.
#include <iostream>
#include <fstream>
#include "SPqueue.h"
using namespace std;
Spqueue::Spqueue() {
inde = 0;
}
void Spqueue::insert(server i) { //inserts new element into the array
inde++;
spqueue[inde] = i;
}
void Spqueue::heapify(int n, int i)
{
int largest = i; // Initialize largest as root
int l = 2 * i; // left = 2*i + 1
int r = 2 * i +1; // right = 2*i + 2
// If left child is larger than root
if (l < n && spqueue[l].effi > spqueue[largest].effi)
largest = l;
// If right child is larger than largest so far
if (r < n && spqueue[r].effi > spqueue[largest].effi)
largest = r;
// If largest is not root
if (largest != i)
{
swap(spqueue[i], spqueue[largest]);
// Recursively heapify the affected sub-tree
heapify(n, largest);
}
}
void Spqueue::heapSort()
{
// Build heap (rearrange array)
for (int i = inde / 2 - 1; i > 0; i--)
heapify(inde, i);
// One by one extract an element from heap
for (int i = inde - 1; i > 0; i--)
{
// Move current root to end
swap(spqueue[1], spqueue[i]);
// call max heapify on the reduced heap
heapify(i, 1);
}
}
void Spqueue::swap(server& i, server& j) {
server temp;
temp = i;
i = j;
j = temp;
}
int Spqueue::getMin() { //iterates to the next available server in the sorted list of servers
int i = 0;
while (i <=20){
if (spqueue[i].status == true)
{
return i;
}
else
{
i++;
}
}
}
bool Spqueue::getStatus(int i) {
return spqueue[i].status;
}
void Spqueue::setBusy(int i) {
spqueue[i].status = false;
}
void Spqueue::addServiceTime(int i,double s) {
spqueue[i].busyTime = spqueue[i].busyTime + s;
}
double Spqueue::getTotalServiceTime(int i) {
return spqueue[i].busyTime;
}
void Spqueue::setIdle(int i) {
spqueue[i].status = true;
}
double Spqueue::getEffi(int i) {
return spqueue[i].effi;
}
void Spqueue::incrementCustNumber(int i) {
spqueue[i].count++;
}
int Spqueue::getCount(int i) {
return spqueue[i].count;
}
And the following function is supposed to return the most efficient server.
int Spqueue::getMin() { //iterates to the next available server in
the already sorted array
int i = 0;
while (i <=20){
if (spqueue[i].status == true)
{
return i;
}
else
{
i++;
}
}
}
Your priority queue implementation of siftdown has some problems.
void Pqueue::siftdown(int i) { //shifts element to its position in the min heap
int c = i * 2;
int c2 = (i * 2) + 1;
// *** Possible bug
// *** I think that if c == inde, then c is indexing beyond the current queue
if (c > inde) return;
int in = i;
if (pqueue[i].eventTime > pqueue[c].eventTime)
{
in = c;
}
if ((c2 < inde) && (pqueue[i].eventTime > pqueue[c2].eventTime))
{
in = c2;
}
// ***************
// ** Bug here
if (pqueue[c].eventTime < pqueue[c2].eventTime) {
in = c;
}
if (in != i) {
swap(pqueue[i], pqueue[in]);
siftdown(in);
}
}
First, I think you want to test c1 >= inde. Also, when you're checking to see if pqueue[c].eventTime < pqueue[c2].eventTime, you do so without making sure that c2 is within bounds.
I find the following to be a more clear and succinct way to do things:
// find the smallest child
int in = c;
if (c2 < inde && pqueue[c2] < pqueue[c])
{
in = c2;
}
if (pqueue[in] < pqueue[i]) {
swap(pqueue[i], pqueue[in]);
siftdown(in);
}

"No instance of constructor "PlayerData::PlayerData" matches the argument list." error Visual Studio is giving me when I try to run the program

Header File
#pragma once
#ifndef PLAYERDATA_H
#define PLAYERDATA_H
#include <string>
using namespace std;
class PlayerData
{
private:
Private member variables
static const int SIZE = 10;
string name; //Player Name
int jnum; //Jersey Number
string team; //Player Team
string position; //Player position
int points[SIZE]; // Array of points for last 10 games
int rebounds[SIZE]; // Array of rebounds for last 10 games
int assist[SIZE]; // Array of assist for last 10 games
double ap = 0.0; // Average number of points
double ar = 0.0; // Average number of rebounds
double aa = 0.0; // Average number of assits
public:
Constructor to initialize data if no data is passed
// Constructor #1
PlayerData()
{
jnum = 0;
name = "";
team = "";
position = "";
for (int i = 0; i < SIZE; i++)
{
points[SIZE] = 0;
rebounds[SIZE] = 0;
assist[SIZE] = 0;
}
}
// Constructor #2
Constructor to accept parameter. Collects jersey number, name, team name, position, array of points for last 10 games, array of rebounds for last 10 games, array of assist for last 10 games.
PlayerData( int jn, string n, string t, string pos, int p[SIZE], int r[SIZE], int a[SIZE])
{
jnum = jn;
name = n;
team = t;
position = pos;
for (int i = 0; i < SIZE; i++)
{
points[SIZE] = p[SIZE];
rebounds[SIZE] = r[SIZE];
assist[SIZE] = a[SIZE];
}
}
// Mutator Function
void setJersery(int jn)
{
jnum = jn;
}
void setName(string n)
{
name = n;
}
void setTeam(string t)
{
team = t;
}
void setPosition(string pos)
{
position = pos;
}
void setPoints(int p[SIZE])
{
for (int z = 0; z < SIZE; z++)
{
points[SIZE] = p[SIZE];
}
}
void setRebounds(int r[SIZE])
{
for (int z = 0; z < SIZE; z++)
{
rebounds[SIZE] = r[SIZE];
}
}
void setAssist(int a[SIZE])
{
for (int z = 0; z < SIZE; z++)
{
assist[SIZE] = a[SIZE];
}
}
// Acessor methods
string getName()
{
return name;
}
int getJersey()
{
return jnum;
}
string getTeam()
{
return team;
}
string getPosition()
{
return position;
}
int getPoints()
{
return points[SIZE];
}
int getRebounds()
{
return rebounds[SIZE];
}
int getAssist()
{
return assist[SIZE];
}
/*
double averageP(int p[], const int SIZE);
double averageR(int r[], const int SIZE);
double averageA(int a[], const int SIZE);
*/
void averageP(int p[], const int SIZE);
void averageR(int r[], const int SIZE);
void averageA(int a[], const int SIZE);
double getAP()
{
return ap;
}
double getAR()
{
return ar;
}
double getAA()
{
return aa;
}
};
#endif // !PLAYERDATA_H
Calculates average points,rebounds, assist from the arrays that were passed.
PlayerData.cpp
#include "PlayerData.h"
using namespace std;
// Calculate average points
void PlayerData::averageP(int p[], const int s)
{
for (int c = 0; c < s; c++)
{
ap += p[c];
}
ap /= s;
//return ap;
}
// Calculate average rebounds
void PlayerData::averageR(int r[], const int s)
{
for (int c = 0; c < s; c++)
{
ar += r[c];
}
ar /= s;
//return ar;
}
// Calculate average assist
void PlayerData::averageA(int a[], const int s)
{
for (int c = 0; c < s; c++)
{
aa += a[c];
}
aa /= s;
//return aa;
}
Main
#include <iostream>
#include <iomanip>
#include "PlayerData.h"
using namespace std;
int main()
{
const int SIZE = 10;
int points[SIZE] = { 10,10,10,10,10,10,10,10,10,10 };
int assist[SIZE] = { 2,2,2,2,2,2,2,2,2,2, };
int rebounds[SIZE] = { 3,3,3,3,3,3,3,3,3,3 };
Here is where the problem occurs. The compiler marks under the 6 as if the int is not part of the arguments for the constructor. I'm not sure why it is doing this. I receive this message "No instance of constructor "PlayerData::PlayerData" matches the argument list."
PlayerData player1(6, "Jimmy Butler", "Chicago Bulls", "Forward", points[SIZE], rebounds[SIZE], assist[SIZE]);
getchar();
return 0;
}
Constructor requires an array of integers and in main you are passing a pointer to int. If you want to pass the whole array you should delete the [SIZE] because that is translated as (if SIZE is 5 for example) "give me the 6th element of 5 element array".
Try calling it like this.
PlayerData player1(6, "Jimmy Butler", "Chicago Bulls", "Forward", points, rebounds, assist);

I have an array of objects. These objects have arrays of integers and I can't access them within the array

This is my class
class Process {
public:
Process();
void createBurstArray(int *bursts, int sizeOfArray);
void createIOArray(int *IO, int capacity);
int *burstArray;
int *ioArray;
int currentBurst;
int currentIO;
int currentState;
};
Process::Process()
{
}
void Process::createBurstArray(int *bursts, int capacity){
burstArray = new int[capacity];
burstArray = bursts;
};
void Process::createIOArray(int *IO, int capacity) {
ioArray = new int[capacity];
ioArray = IO;
for (int i = 0; i < capacity; i++)
};
void main(){
int processOneBursts[7] = { 12,10,15,11,9,10,11 };
int processOneIO[6] = { 44,52,21,42,31,77 };
Process processes[9];
Process one;
processes[0] = one;
one.createBurstArray(processOneBursts, 7);
one.createIOArray(processOneIO, 6);
}
When I try accessing the ioArray
one.ioArray[1]
I get the value stored in the ioArray at index 1, butw hen I try accessing the ioArra through my object array index it doesn't work:
for (int i = 0; i < 9; i++) {
cout << processes[i].ioArray[i] << endl;
}
What am I doing wrong?
#include <iostream>
using namespace std;
class Process {
public:
// Process();
void createBurstArray(int *bursts, int sizeOfArray);
void createIOArray(int *IO, int capacity);
int *burstArray;
int *ioArray;
int currentBurst;
int currentIO;
int currentState;
};
int main()
{
Process p[10];
for (int i = 0; i < 9; i++) {
p[i].ioArray = new int[1];
}
for (int i = 0; i < 9; i++) {
p[i].ioArray[0] = i;
}
for (int i = 0; i < 9; i++) {
cout << p[i].ioArray[0] << endl;
}
return 0;
}
This works, i think you didn't initialize the dynamic array.
You are object of the class with default constructor which means all the elements in the class will be uninitialized including the element int *ioArray;.
And you are trying to access ioArray in the for loop which is road set to segmentation fault.
To correct this, you must initialize the element before using them.
Also, Your below function is problematic.
void Process::createIOArray(int *IO, int capacity) {
ioArray = new int[capacity];
ioArray = IO;
}
This is a memory leak, since you have assign ioArray to IO ,new int[capacity] memory will not be freed.
Solution:
#include <iostream>
using namespace std;
class Process {
public:
Process();
void createBurstArray(int sizeOfArray);
void createIOArray(int capacity);
int *burstArray;
int *ioArray;
int currentBurst;
int currentIO;
int currentState;
// Don't forget to delete burstArray, ioArray in destructor.
};
void Process::createIOArray(int capacity) {
ioArray = new int[capacity];
};
void Process::createBurstArray(int sizeOfArray) {
burstArray = new int[sizeOfArray];
};
Process::Process(){
createIOArray(10);
createBurstArray(10);
// Similarly you have to initialize other members of the class
}
int main()
{
Process processes[9];
for (int i = 0; i < 9; i++) {
cout << processes[i].ioArray[i] << endl;
}
}

C++ program runs in linux but not windows

I am writing this program for college and keep having problems with it. I wrote in using codeblocks in ubuntu and it runs fine no errors or anything. But when I run it in windows on codeblocks it crashes and I keep getting the same error "terminate called after throwing an instance of 'std::bad_alloc' what<>: std::badalloc' then it stops working.
Any help would be appreciated!
Thankyou
Ron
main.cpp
#include <iostream>
#include "set.h"
using namespace std;
int main()
{
Set Set1;
List List1;
List1.header();
int choice = 0;
int value = 0;
cout<<"Press 1 to use a list or press 2 for a set"<<endl;
cin>>choice;
if(choice == 1) //List
{
while(choice != 4)
{
value = 0;
List1.menu();
cin>>choice;
switch(choice)
{
case 1:cout<<"Please enter value"<<endl;
cin>>value;
List1.set_value(value);
break;
case 2:List1.print_list();
break;
case 3:List1.test_copy_constructor();
break;
}
}
}
else if(choice == 2) //Set
{
while(choice != 4)
{
value = 0;
List1.menu();
cin>>choice;
switch(choice)
{
case 1:cout<<"Please enter value"<<endl;
cin>>value;
Set1.set_value(value);
break;
case 2:Set1.print_list();
break;
case 3:Set1.test_copy_constructor();
break;
}
}
}
else
{
cout<<"Please Enter a valid option"<<endl;
}
return 0;
}
set.cpp
#include "set.h"
#include <iostream>
#include <string>
using namespace std;
//Constructor
List::List()
{
int array_size;
int *array = new int[array_size];
// delete [] array;
}
List List1;
//Print functions
void List::header(void) const
{
cout<<"Program Name: Program 2"<<endl;
cout<<"Program Created: March 20,2014"<<endl;
cout<<"Created by: Ron Miller"<<endl;
cout<<"--------------------------------"<<endl;
cout<<" "<<endl;
}
void List::menu(void) const
{
cout<<" Menu"<<endl;
cout<<"---------------------------------------------------------"<<endl;
cout<<"1. Insert (value to be inserted is entered from keyboard)"<<endl;
cout<<"2. Print List (all values, one per line)"<<endl;
cout<<"3. Test Copy Constructor (pass list by value to a function"<<endl;
cout<<" and from within the function change all values in list"<<endl;
cout<<" to 0, then call Print List before function ends)"<<endl;
cout<<"4. Quit"<<endl;
cout<<"---------------------------------------------------------"<<endl;
}
//Modification Functions
void List::set_value(const int value)
{
if (slot == 0) //If first run set array size
{
array = new int[array_size];
}
if (slot == array_size) //If array needs extended save data in temp array expand original array then copy back to original
{
cout<<"EXPAND ARRAY"<<endl;
temp_array = array;
array_size = array_size + 2;
array = new int[array_size];
array = temp_array;
}
array[slot] = value; //Set current array slot to value
slot = slot+1;
}
void List::print_list(void) const
{
int i = 0;
cout<<"---------------"<<endl;
while(i < slot)
{
cout<<array[i]<<endl;
i = i+1;
}
cout<<"---------------"<<endl;
}
void List::test_copy_constructor(void) const
{
int* test_array;
test_array = array;
int i = 0;
test_array = new int[array_size]; //Copy original array to test_Array
while(i < slot) //Set array to 0
{
test_array[i] = 0;
i = i+1;
}
i = 0;
cout<<"---------------"<<endl;
while(i < slot) //REMOVE THIS ONLY FOR TESTING PURPOSES
{
cout<<test_array[i]<<endl;
i = i+1;
}
i = 0;
cout<<"---------------"<<endl;
List::print_list(); //Print original array
}
void Set::set_value(const int value)
{
array = get_array(); //Use get functions to obtain copies of private data
temp_array = get_temp_array();
array_size = get_array_size();
temp_array_size = get_temp_array_size();
slot = get_slot();
char match;
match = Set::search_array(value);
if(match == 'y')
{
cout<<"Match"<<endl;
}
if(match == 'n')
{
if (slot == 0) //If first run set array size
{
array = new int[array_size];
}
if (slot == array_size) //If array needs extended save data in temp array expand original array then copy back to original
{
cout<<"EXPAND ARRAY"<<endl;
temp_array = array;
array_size = array_size + 2;
array = new int[array_size];
array = temp_array;
}
array[slot] = value; //Set current array slot to value
slot = slot+1;
set_array(array); //Use set values to update private data
set_temp_array(temp_array);
set_array_size(array_size);
set_temp_array_size(temp_array_size);
set_slot(slot);
}
}
char Set::search_array(int value)
{
array = get_array();
array_size = get_array_size();
slot = get_slot();
int array_value;
char match = 'n';
int i =0;
while(i < slot) //Searches array for a match if there is return y otherwise return n
{
if( array[i] == value)
{
match = 'y';
}
else
{
match = 'n';
}
i = i+1;
}
return match;
}
//Set Functions
void List::set_array(int* value)
{
array = value;
}
void List::set_array_size(int value)
{
array_size = value;
}
void List::set_temp_array(int* value)
{
temp_array = value;
}
void List::set_temp_array_size(int value)
{
temp_array_size = value;
}
void List::set_slot(int value)
{
slot = value;
}
//Get Functions
int* List::get_array(void) const
{
return array;
}
int* List::get_temp_array(void) const
{
return temp_array;
}
int List::get_array_size(void) const
{
return array_size;
}
int List::get_temp_array_size(void) const
{
return temp_array_size;
}
int List::get_slot(void) const
{
return slot;
}
set.h
#ifndef set_H_INCLUDED
#define set_H_INCLUDED
class List
{
public:
//Constructor
List();
//Print Functions
void header (void) const;
void menu (void) const;
//Modification Functions
void set_value (const int);
void print_list(void) const;
void test_copy_constructor(void) const;
//Set functions
void set_array( int*);
void set_temp_array(int*);
void set_array_size( int);
void set_temp_array_size(int);
void set_slot(const int);
//Get functions
int* get_array (void) const;
int* get_temp_array (void) const;
int get_array_size (void) const;
int get_temp_array_size (void) const;
int get_slot(void) const;
private:
int array_size;
int *array;
int *temp_array;
int temp_array_size;
int slot = 0;
};
class Set : public List
{
public:
//Modification Functions
void set_value (const int);
char search_array(const int);
private:
int array_size = 2;
int *array;
int *temp_array;
int temp_array_size = 2;
int slot = 0;
};
#endif
List::List()
{
int array_size;
int *array = new int[array_size];
// ...
}
What value is array_size supposed to have? How large an int array is supposed to be allocated?
It seems to me that this local variable declaration is superfluous; remove it, and use the member variable, instead. (You've initialised the member variable to 2 at its point of declaration, using a new C++11 feature which allows you to do so with a variable that is not static const.)
Don't forget to hand back that allocated memory when you're done with it. In general I would propose that you use std::vector for this.

C++ pointer "losing" its value

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. ;)