Output not reading correctly for pond simulator:

The output should look like:

WEEK 20 RESULTS
Fish With Weight 20
Plant weight 13.95
Plant weight 21.05
Plant weight 45.19
Plant weight 19.74
Plant weight 29.69
Plant weight 46.15
FISH DIED
Plant weight 9.49
Fish With Weight 6
Plant weight 28
15Plant weight 42.55
Fish With Weight 3
Ending simulation
FISH DIED
PLANT DIED
PLANT DIED
PLANT DIED
PLANT DIED
PLANT DIED
PLANT DIED
PLANT DIED
FISH DIED
PLANT DIED
PLANT DIED
FISH DIED

instead, on mine it looks like:

WEEK 20 RESULTS
Fish With Weight 1
Plant weight 1
Plant weight 1
Plant weight 1
Plant weight 1
Plant weight 1
Plant weight 1
Plant weight 1
Fish With Weight 1
Plant weight 1
Plant weight 1
Fish With Weight 1

Ending simulation

PLease help me figure out why the output is different.

The int main() is written for you, however you will need to implement the following functions
• void buildPondSimulator(ifstream& infile, organism *** pond) - this function takes in an already opened filestream that reads from a CSV file and your empty ”2D” array of organism objects, your job will be to insert an herbivore or plant object into pond[r][c]. Every line in the CSV file will contain
ORGANISM_TYPE , SIZE , GROWTH_RATE , X_COORDINATE , Y_COORDINATE
Once you parse the line and convert each element into its correct type (SIZE and GROWTH_RATE should be converted in double and X_COORDINATE and Y_COORDINATE should be converted into int, and ORGANISM_TYPE will remain a string), you then assign pond[X_COORDINATE][Y_COORDINATE] with new herbivore(size, rate, size * 0.1) or new plant(size, rate) based on whether ORGANISM_TYPE contains "FISH" or "PLANT" respectively.

You may use getNextField function from previous assignments or you can use a stringstream type to parse each comma separated line. You can see a description of that in the video (it’s linked at the end of the pdf).

Not all elements of pond[r][c] will be assigned to point to an object, thus for those elements assign pond[r][c] = NULL or pond[r][c] = nullptr
• void simulateAWeek(organism *** pond, randNum& rN) - this function simulates one week of the pond simulator, you will simulate 100 activities and each activity does the following
1. Get a random x1, y1, x2, and y2 indices to investigate two potential organisms in the pond array
2. Create two pointers organism * o1, * o2 and set them with the content in pond[x1][y1] and
pond[x2][y2] respectively
3. Check the contents in o1 and o2 for whether they are NULL or if they point to an herbivore
and/or plant object (this could involve using a dynamic_cast)
4. If they are both NULL then this is a failed activity, thus nothing happens
5. If they both point to plant objects, then this would be a failed activity, thus nothing happens
6. If one of the pointers is NULL and the other is a plant then nothing happens
7. If one of the pointers is NULL and the other points to an herbivore, assign NULL to where the
herbivore object used to be be and assign the herbivore obect to where the NULL used to be
8. If they both point to herbivore objects then you need to swap their positions in the pond array
9. If one of the pointers points to an herbivore object and the other points to a plant object,
then you must called the herbivore object’s nibble function and pass in the plant object as the
parameter (you may need to dereference, use the arrow operator, and/or use dynamic_cast here), then you swap their positions in the pond array (I guess the plant submerges underground and
spawns where the fish used to be)
Once all 100 activities are simulated, you call simulateWeek() function for each element. Check each object if it is still alive, if no longer alive then deallocate the object pond[r][c] and then set pond[r][c] to NULL or nullptr
Then you call the outputOrganism function for each object in the pond.

main.cpp:

#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <cstdlib>
#include "herbivore.h"
#include "plant.h"
#include "organism.h"
#include "randNum.h"

using namespace std;

const int ROWS = 5;
const int COLS = 5;

void buildPondSimulator(ifstream&, organism***);
void simulateAWeek(organism***, randNum&);
void outputOrganism(organism*);
void clearSimulation(organism***);

int main()
{
organism *** pond;
ifstream infile;
string filename;
randNum rN("RandomNums.txt");
int weeks;

pond = new organism**[ROWS];

//allocate the columns for each row
for (int i = 0; i < ROWS; i++)
pond[i] = new organism*[COLS];

for (int i = 0; i < ROWS; i++)
for (int j = 0; j < COLS; j++)
pond[i][j] = NULL;

//ask for pond file and re-prompt if not found
do
{
cout << "Enter pond data file: ";
cin >> filename;

infile.open(filename.c_str());
}
while (!infile.is_open());

buildPondSimulator(infile, pond);

cout << "Enter amount of weeks for the simulation: ";
cin >> weeks;

while (cin.fail() || weeks <= 0)
{
if (cin.fail())
{
cin.fail();
cin.ignore(100, '\n');
}
cout << "Enter amount of weeks for the simulation: ";
cin >> weeks;
}

for (int i = 0; i < weeks; i++)
{
cout << "WEEK " << i + 1 << " RESULTS" << endl;
simulateAWeek(pond, rN);
cout << endl << endl;
}

cout << "Ending simulation" << endl;

//destroy the simulation
clearSimulation(pond);

return 0;
}

void buildPondSimulator(ifstream& infile, organism *** pond)
{
string line;
string organismType;
string size;
string growthRate;
string xCoordinate;
string yCoordinate;

while (!infile.eof())
{
getline(infile, line);
stringstream s(line);
getline(s, organismType, ',');

if(organismType == "FISH")
{
getline(s, size, ',');
getline(s, growthRate, ',');
getline(s, xCoordinate, ',');
getline(s, yCoordinate, '\r');
int x1 = stoi(xCoordinate);
int y1 = stoi(yCoordinate);
herbivore *placeInArray = new herbivore(stod(size), stod(growthRate), stod(size) * 0.1);
pond[y1][x1] = placeInArray;
}
else
{
getline(s, size, ',');
getline(s, growthRate, ',');
getline(s, xCoordinate, ',');
getline(s, yCoordinate, '\r');
int x1 = stoi(xCoordinate);
int y1 = stoi(yCoordinate);
plant *placeInArray = new plant(stod(size), stod(growthRate));
pond[y1][x1] = placeInArray;
}
}
}
/*

void simulateAWeek(organism *** pond, randNum& rN)
{
for(int i = 0; i < 100; i++)
{
int x1 = rN.getNextRand() % 5;
int y1 = rN.getNextRand() % 5;
int x2 = rN.getNextRand() % 5;
int y2 = rN.getNextRand() % 5;

organism *o1, *o2;
o1 = pond[x1][y1];
o2 = pond[x2][y2];

if(o1 == NULL && o2 == NULL)
{
continue;
}
else if (dynamic_cast<plant *>(o1) && dynamic_cast<plant *>(o2))
{
continue;
}
else if (dynamic_cast<plant *>(o1) && o2 == NULL)
{
continue;
}
else if (dynamic_cast<plant *>(o2) && o1 == NULL)
{
continue;
}
else if (dynamic_cast<herbivore *>(o1) && o2 == NULL)
{
pond[x2][y2] = pond[x1][y1];
pond[x1][y1] = NULL;
}
else if (dynamic_cast<herbivore *>(o2) && o1 == NULL)
{
pond[x1][y1] = pond[x2][y2];
pond[x2][y2] = NULL;
}
else if (dynamic_cast<herbivore *>(o2) && dynamic_cast<herbivore *>(o1))
{
organism *temp = o1;
pond[x1][y1] = pond[x2][y2];
pond[x2][y2] = temp;
}
else if (dynamic_cast<plant *>(o2) && dynamic_cast<herbivore *>(o1))
{
dynamic_cast<herbivore *>(o1)->nibble(dynamic_cast<plant &>(*o2));
organism *temp = o1;
pond[x1][y1] = pond[x2][y2];
pond[x2][y2] = temp;
}
else if (dynamic_cast<herbivore *>(o2) && dynamic_cast<plant *>(o1))
{
dynamic_cast<herbivore *>(o2)->nibble(dynamic_cast<plant &>(*o1));
organism *temp = o2;
pond[x2][y2] = pond[x1][y1];
pond[x1][y1] = temp;
}
}
for (int i = 0; i < ROWS; i++)
{
for (int j = 0; j < COLS; j++)
{
if (pond[i][j] != NULL)
{
if (pond[i][j]->isAlive() == false)
{
pond[i][j] == NULL;
}
else
{
outputOrganism(pond[i][j]);
cout << endl;
}
}
}
}
}

void outputOrganism(organism * org)
{
if(dynamic_cast<animal *>(org))
{
cout << "Fish with weight" << org->getSize();
}
if(dynamic_cast<plant *>(org))
{
cout << "Plant with weight" << org->getSize();
}
}

void clearSimulation(organism *** pond)
{
delete[] pond;
}
You haven't provided enough of your code to answer this.

Also, it helps if your use the Code format tags (in the palette to the right) to format your code. Also the code stops in the middle of a commented out section.

It's also a little odd to be asked to use C++ in a simulation that'll generate data without using STL containers, just new/delete on stuff.
main.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <cstdlib>
#include "herbivore.h"
#include "plant.h"
#include "organism.h"
#include "randNum.h"

using namespace std;

const int ROWS = 5;
const int COLS = 5;

void buildPondSimulator(ifstream&, organism***);
void simulateAWeek(organism***, randNum&);
void outputOrganism(organism*);
void clearSimulation(organism***);

int main()
{
    organism *** pond;
    ifstream infile;
    string filename;
    randNum rN("RandomNums.txt");
    int weeks;

    //allocate the pond structure

    //allocate the amount of rows
    pond = new organism**[ROWS];

    //allocate the columns for each row
    for (int i = 0; i < ROWS; i++)
        pond[i] = new organism*[COLS];

    //This would be an empty pond initial so each cell is set to empty
    for (int i = 0; i < ROWS; i++)
        for (int j = 0; j < COLS; j++)
            pond[i][j] = NULL;

    //ask for pond file and re-prompt if not found
    do
    {
        cout << "Enter pond data file: ";
        cin >> filename;

        infile.open(filename.c_str());
    }
    while (!infile.is_open());
    
    //Time to build the simulation, reads the contents from the CSV file
    //and inserts objects into pond array
    buildPondSimulator(infile, pond);

    //Asks the user for the amount of weeks they wish to simulate
    //re-prompts if invalid input read
    cout << "Enter amount of weeks for the simulation: ";
    cin >> weeks;

    while (cin.fail() || weeks <= 0)
    {
        if (cin.fail())
        {
            cin.fail();
            cin.ignore(100, '\n');
        }
        cout << "Enter amount of weeks for the simulation: ";
        cin >> weeks;
    }

    //Simulates the amount of weeks, calls simulateAWeek function
    //weeks amount of times
    for (int i = 0; i < weeks; i++)
    {
        cout << "WEEK " << i + 1 << " RESULTS" << endl;
        simulateAWeek(pond, rN);
        cout << endl << endl;
    }

    cout << "Ending simulation" << endl;

    //destroy the simulation
    clearSimulation(pond);

    return 0;
}

//this function takes in an already opened filestream that reads from a
//CSV file and your empty "2D" array of organism objects.
void buildPondSimulator(ifstream& infile, organism *** pond)
{
  string line;
  string organismType;
  string size;
  string growthRate;
  string xCoordinate;
  string yCoordinate;

  while (!infile.eof())
    {
      getline(infile, line);
      stringstream s(line);
      getline(s, organismType, ',');

      if(organismType == "FISH")
	{
	  getline(s, size, ',');
	  getline(s, growthRate, ',');
	  getline(s, xCoordinate, ',');
	  getline(s, yCoordinate, '\r');
	  int x1 = stoi(xCoordinate);
	  int y1 = stoi(yCoordinate);
	  herbivore *placeInArray = new herbivore(stod(size), stod(growthRate), stod(size) * 0.1);
	  pond[y1][x1] = placeInArray;
	}
      else
	{
	  getline(s, size, ',');
	  getline(s, growthRate, ',');
	  getline(s, xCoordinate, ',');
	  getline(s, yCoordinate, '\r');
	  int x1 = stoi(xCoordinate);
	  int y1 = stoi(yCoordinate);
	  plant *placeInArray = new plant(stod(size), stod(growthRate));
	  pond[y1][x1] = placeInArray;
	}
    }
}
/*
@brief takes in a pre-populated pond and random number generator and assigns
values based upon where the random x and y coordinates are
@param pond the pond of plants and fishes in a 2D array
@param rN the random number generator
 */

void simulateAWeek(organism *** pond, randNum& rN)
{
  for(int i = 0; i < 100; i++)
    {
      int x1 = rN.getNextRand() % 5;
      int y1 = rN.getNextRand() % 5;
      int x2 = rN.getNextRand() % 5;
      int y2 = rN.getNextRand() % 5;

      organism *o1, *o2;
      o1 = pond[x1][y1];
      o2 = pond[x2][y2];

      if(o1 == NULL && o2 == NULL)
	{
	  continue;
	}
      else if (dynamic_cast<plant *>(o1) && dynamic_cast<plant *>(o2))
	{
	  continue;
	}
      else if (dynamic_cast<plant *>(o1) && o2 == NULL)
	{
	  continue;
	}
      else if (dynamic_cast<plant *>(o2) && o1 == NULL)
	{
	  continue;
	}
      else if (dynamic_cast<herbivore *>(o1) && o2 == NULL)
	{
	  pond[x2][y2] = pond[x1][y1];
	  pond[x1][y1] = NULL;
	}
      else if (dynamic_cast<herbivore *>(o2) && o1 == NULL)
	{
	  pond[x1][y1] = pond[x2][y2];
	  pond[x2][y2] = NULL;
	}
      else if (dynamic_cast<herbivore *>(o2) && dynamic_cast<herbivore *>(o1))
	{
	  organism *temp = o1;
	  pond[x1][y1] = pond[x2][y2];
	  pond[x2][y2] = temp;
	}
      else if (dynamic_cast<plant *>(o2) && dynamic_cast<herbivore *>(o1))
	{
	  dynamic_cast<herbivore *>(o1)->nibble(dynamic_cast<plant &>(*o2));
	  organism *temp = o1;
	  pond[x1][y1] = pond[x2][y2];
	  pond[x2][y2] = temp;
	}
      else if (dynamic_cast<herbivore *>(o2) && dynamic_cast<plant *>(o1))
	{
	  dynamic_cast<herbivore *>(o2)->nibble(dynamic_cast<plant &>(*o1));
	  organism *temp = o2;
	  pond[x2][y2] = pond[x1][y1];
	  pond[x1][y1] = temp;
	}
    }
  for (int i = 0; i < ROWS; i++)
    {
      for (int j = 0; j < COLS; j++)
	{
	  if (pond[i][j] != NULL)
	    {
	      if (pond[i][j]->isAlive() == false)
		{
		  pond[i][j] == NULL;
		}
	      else
		{
		  outputOrganism(pond[i][j]);
		  cout << endl;
		}
	    }
	}
    }
}

//Outputs the string "Fish with weight" or "Plant with weight" depending on
//wheterh org points to an herbivore or plant object and then output
//org -> getSize
void outputOrganism(organism * org)
{
  if(dynamic_cast<animal *>(org))
    {
      cout << "Fish with weight" << org->getSize();
    }
  if(dynamic_cast<plant *>(org))
    {
      cout << "Plant with weight" << org->getSize();
    }
}

//deallocates all the objects in each pond [r][c] position and then deallocates
//the pointers as well (this part would be the same as deallocating any
//2D dynamic array
void clearSimulation(organism *** pond)
{
  delete[] pond;
}


animal.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include "animal.h"

animal::animal(double initSize, double initRate, double initNeed)
{
  this->growthRate = initRate;
  this->needThisWeek = initNeed;
  this->eatenThisWeek = 0;
}
	
void animal::assignNeed(double newNeed)
{
  this->needThisWeek = newNeed;
}
	
void animal::eat(double amount)
{
  this->eatenThisWeek += amount;
}

void animal::simulateWeek()
{
  double valueToEvaluate = stillNeed();
  if(valueToEvaluate == 0)
    {
      growthRate = getRate() * -1;
    }
  else
    {
      growthRate = getRate() * -1;
    }
  simulateWeek();
  eatenThisWeek = 0;
  if(isAlive() == false)
    {
      death();
    }
}
	
double animal::stillNeed() const
{
  if(eatenThisWeek >= needThisWeek)
    {
      return 0;
    }
  else
    {
      return needThisWeek - eatenThisWeek;
    }
}

double animal::totalNeed() const
{
  return needThisWeek;
}

animal::~animal()
{
  needThisWeek = 0;
  eatenThisWeek = 0;
}


organism.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include "organism.h"

organism::organism(double initSize, double initRate)
{
  this->growthRate = initRate;
  this->size = initSize;
}
	
void organism::simulateWeek()
{
  alterSize(growthRate);
}
	
void organism::assignRate(double newRate)
{
  this->growthRate = newRate;
}
	
void organism::alterSize(double amount)
{
  this->size += amount;
  if(size <= 0)
    {
      death();
    }
}
	
void organism::death()
{
  this->growthRate = 0;
  this->size = 0;
}

double organism::getSize() const
{
  return this->size;
}

double organism::getRate() const
{
  return this->growthRate;
}

bool organism::isAlive() const
{
  if(this->size > 0)
    {
      return true;
    }
  else
    {
      return false;
    }
}

organism::~organism()
{
  this->growthRate = 0;
  this->size = 0;
}

You probably need to post all files including:
* all .cpp files
* all .h files
* RandomNums.txt
* an input file

If you want you can upload a zip somewhere and post a link here.
This is what happens when you use raw pointers, you handle the heap incorrectly.
1
2
3
4
5
6
7
8
9
10
void clearSimulation(organism*** pond) {
    for (int i = 0; i < ROWS; i++)
        for (int j = 0; j < COLS; j++)
            delete [] pond[i][j];

    for (int i = 0; i < ROWS; i++)
        delete [] pond[i];

    delete [] pond; // you only had this
}
and this is a serious logical error in addition to the memory thing
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
void simulateAWeek(organism *** pond, randNum& rN) {
    // ...
        else if (dynamic_cast<herbivore *>(o1) && o2 == NULL) {
            pond[x2][y2] = pond[x1][y1];
            pond[x1][y1] = NULL;  // should be free'd
        }   
        else if (dynamic_cast<herbivore *>(o2) && o1 == NULL) {
            pond[x1][y1] = pond[x2][y2];
            pond[x2][y2] = NULL;  // should be free'd
        }   
    // ...
    for (int i = 0; i < ROWS; i++) {
        for (int j = 0; j < COLS; j++) {
            if (pond[i][j] != NULL) {
                if (pond[i][j]->isAlive() == false) {
                    pond[i][j] == NULL; // we should be free'ing the object
                } else {
                    outputOrganism(pond[i][j]); // we'll always pass null
                    cout << endl;
                }   
            }   
        }   
    }   
}


The Standard Library has a swap() function that'll simplify this stuff:
1
2
3
4
5
6
        else if (dynamic_cast<herbivore *>(o2) && dynamic_cast<herbivore *>(o1))
        {
            organism *temp = o1;
            pond[x1][y1] = pond[x2][y2];
            pond[x2][y2] = temp;
        }



... plus what dutch said.
Last edited on
@GroovyJack. This is again quite a complicated exercise. Also you have another post http://www.cplusplus.com/forum/general/278458/ re a banking simulator which again is non-trivial.

As per my post to the other thread, may I suggest that you concentrate on one project at a time and complete that before starting another.
Last edited on
Topic archived. No new replies allowed.