Clear a class within a method - c++

I want a function of the class that I have to clear the class before it applies its function without having to manually do it every time I ask the function of that class in a loop using the default constructor (as I do now).
An example
class Hello
{
public:
std::vector<int> a,b,c; //,d,e,... etc...
void set ( int value )
{
a.push_back(value);
b.push_back(value);
c.push_back(value);
//d.push_back...
//e.push_back...
//etc...
return;
}
};
std::ostream& operator<<(std::ostream& os, const Hello &hello)
{
for ( int i=0; i<hello.a.size(); i++ )
{
os << hello.a[i] << "\t";
os << hello.b[i] << "\t";
os << hello.c[i] << "\t";
//etc...
os << std::endl;
}
os << std::endl;
return os;
}
Somewhere in main
Hello hello;
for ( int i=0; i<5; i++ )
{
hello = Hello(); //want to get rid of this line and move its functionality to the set function
hello.set(i);
std::cout << hello << std::endl;
}
This will produce the correct result, however if I remove the line that clears the variable ( hello = Hello() ) then the set function will keep on appending to the vector and not clear the vector before it appends to it.
So basically I want to not worry about having to type the line hello = Hello(), every time I loop over the set function. By incorporating this clearing of the variable inside the set function of the class itself.
Typing a.clear(), b.clear() etc... before the push_back functions could work but with many vectors that would be a lot of lines. I was looking for a more elegant solution.

Related

How to iterate over a vector containing many stucts (C++)

// In my Class A, I have many nodes and every node data is stored in a struct like this:
Class A
{
private:
struct BriteNodeInfo
{
int nodeId;
double xCoordinate;
double yCoordinate;
int inDegree;
int outDegree;
int asId;
std::string type;
};
};
// Each node instance is stored in a vector like this:
typedef std::vector<BriteNodeInfo> BriteNodeInfoList;
BriteNodeInfoList m_briteNodeInfoList;
//And then, here is the function that I want to implent down below
void SaveNodeData (std::string fname);
};
Problem: How do I implent that SaveNodeData() function to save my nodes data in .txt file like this?:
nodeId0 yCoordinate0 xCoordinate0
nodeId1 yCoordinate1 xCoordinate1
nodeId2 yCoordinate2 xCoordinate2
nodeId3 yCoordinate3 xCoordinate3
etc...
I have tried but my iteration syntax is not good enough. Here is my function, please help:
Here is my failed function:
void SaveNodeData (std::string fname)
{
ofstream os(fname.c_str(), ios::trunc);
vector<BriteNodeInfo> BriteNodeInfoList;
BriteNodeInfoList m_briteNodeInfoList;
for (BriteNodeInfoList::Iterator i = m_briteNodeInfoList.Begin(); i != m_briteNodeInfoList.End(); ++i)
{
os << BriteNodeInfo[i].nodeId "\t" << "\t" << BriteNodeInfo[i].yCoordinate; << "\t"BriteNodeInfo[i].xCoordinate<< "\n";
}
os << "\n";
}
Before starting, this code as written will clearly have some compile errors. But assuming you can manage to fix those issues, there's one huge flaw.
Your function SaveNodeData creates an empty BriteNodeInfoList, and then tries to read from it. The for loop you have written will always simply exit.
What you need to do is create and populate a BriteNodeInfoList somewhere that this function reads. You could pass it in as an argument to the function, have it as a private variable for class A (assuming SaveNodeData is made into a member of class A). Or you could make it a static member variable of class A (not really recommended: static member variables of objects have some serious problems).
void SaveNodeData (std::string fname) // file path
{
ofstream os(fname.c_str(), ios::trunc);
vector<BriteNodeInfo> BriteNodeInfoList = m_briteNodeInfoList;
for (std::vector<BriteNodeInfoList>::Iterator it = BriteNodeInfoList.Begin(); it != BriteNodeInfoList.End(); ++it)
{
os << (*it).nodeId << "\t" << (*it).yCoordinate << "\t" << (*it).xCoordinate << "\n";
}
}

C++ use a class in a class (in a class) and call their functions

I have the following problem: I wanted to redo a project from good old C to C++ and make everything class(y) :) and keep it scalable from the beginning.
It is a simulation of cells (being part of a swarm) on a grid, so I decided the following structure:
class Simulation has an instance of
class Grid has an instance of
class Swarm has an instance of
class Cell
I defined the classes in separate header files. Then I need, of course, to be able to call functions in grid, swarm and cell as well. I wanted to do it straight forward:
Simulation mysim;
mysim.get_grid(0).any_function_here();
with the grid as return parameter
Grid Sim::get_grid(int grid_no)
{
std::cout << "sim.get_grid(" << grid_no << ") called." << std::endl;
if (grid_no <= amount_of_grids)
return this->test;//##//this->gridlist[grid_no];
else
std::cout << "you have not created this grid number yet" << std::endl;
Grid dummy;
return dummy;
}
It calls the function and works as long as no changes in the grid are made. These seem to be lost in space. Probably a pointer error, but I cannot find an error, since exactly the same code is working for the Simulation class...
More source:
int Grid::create_swarm(std::string name)
{
Swarm new_swarm;
new_swarm.set_name("Protoswarm");
swarmlist.push_back(new_swarm);
this->amount_of_swarms ++;
std::cout << "amount_of_swarms = " << amount_of_swarms << std::endl;
return 0;
}
Swarm Grid::get_swarm(int swarm_no)
{
std::cout << "grid.get_swarm(" << swarm_no << ") called." << std::endl;
if (swarm_no <= amount_of_swarms)
return swarmlist[swarm_no];
else
std::cout << "oh oh - you have not this swarm in here..." << std::endl;
Swarm dummy;
return dummy;
}
I can call the create_swarm function as often as I want, but the swarms do never appear and the counter does not raise in that grid, just temporarily as long as the funtion is in there. Am I missing something? Is it really just a pointer error? Why does this code work if I call it like this:
Grid newgrid;
newgrid.create_swarm();
A quickly c&p'ed MWE
#include <iostream>
#include <string>
#include <vector>
class Sim
{
public:
Sim();
virtual ~Sim();
Grid get_grid(int grid_no);
protected:
private:
std::vector<Grid> gridlist;
int amount_of_grids = -1;
};
class Grid
{
public:
Grid();
virtual ~Grid();
int set_size(int x, int y);
int create_swarm(std::string name);
Swarm get_swarm(int swarm_no);
void print_swarms();
protected:
private:
std::vector<Swarm> swarmlist;
int amount_of_swarms = -1;
/*static const*/ int size_x;
/*static const*/ int size_y;
std::vector<std::vector<Field>> fields;
std::string gridname;
};
Grid Sim::get_grid(int grid_no)
{
std::cout << "sim.get_grid(" << grid_no << ") called." << std::endl;
if (grid_no <= amount_of_grids)
return this->gridlist[grid_no];
else
std::cout << "you have not created this grid number yet" << std::endl;
Grid dummy;
return dummy;
}
int Grid::create_swarm(std::string name)
{
Swarm new_swarm;
new_swarm.set_name("Protoswarm");
swarmlist.push_back(new_swarm);
this->amount_of_swarms ++;
std::cout << "amount_of_swarms = " << amount_of_swarms << std::endl;
return 0;
}
Swarm Grid::get_swarm(int swarm_no)
{
std::cout << "grid.get_swarm(" << swarm_no << ") called." << std::endl;
if (swarm_no <= amount_of_swarms)
return swarmlist[swarm_no];
else
std::cout << "oh oh - you have not this swarm in here..." << std::endl;
Swarm dummy;
return dummy;
}
using namespace std;
int main(int argc, char* argv[])
{
Sim mysim;
mysim.create_grid();
mysim.get_grid(0).create_swarm("Alpha-Swarm");
mysim.get_grid(0).create_swarm("Betaa-Swarm"); //doesn't work
Grid newgrid;
newgrid.create_swarm("Gamma-Swarm");
newgrid.create_swarm("Delta-Swarm"); // works, but is not needed.
return 0;
}
Grid Sim::get_grid(int grid_no) {...}
You are returning by value, not by reference. That means that what you are returning is a copy of your actual member. In your case, however, you want to be returning by reference in order to be able to make changes to the original object. Your code would become
Grid& Sim::get_grid(int grid_no) {...}
Keep in mind, however, that you will not be able to return any temporaries that way (such as your dummy Grid), so you will need to change your methods to circumvent this issue. If you do not want to do this, you could still return a pointer, although this would change the syntax a little.
Your get_grid and get_swarm methods return copies of original array items. You should return reference (or a pointer) to Grid or Swarm instead.

Cannot get the value from a class in C++?

I just came from Java and Python world to C++ world, and faced a problem while trying to get the value from a public const function of a class.
I have a class as follows:
class CMDPoint
{
public:
CMDPoint();
CMDPoint(int nDimensions);
virtual ~CMDPoint();
private:
int m_nDimensions; // the number of dimensions of a point
float* m_coordinate; // the coordinate of a point
public:
const int GetNDimensions() const { return m_nDimensions; }
const float GetCoordinate(int nth) const { return m_coordinate[nth]; }
void SetCoordinate(int nth, float value) { m_coordinate[nth] = value; }
};
Ultimately, I wish to write all the clusterPoints in clusterPointArray into the file. However, now I am just testing it with the first clusterPoint (thus, GetCoordinate(0)).
ofstream outFile;
outFile.open("C:\\data\\test.txt", std::ofstream::out | std::ofstream::app);
for (std::vector<CMDPoint> ::iterator it = clusterEntry->clusterPointArray.begin(); it != clusterEntry->clusterPointArray.end(); ++it)
{
outFile << ("%f", (*it).GetCoordinate(0)); // fails
outFile << " ";
}
outFile << "\n";
outFile.close();
The problem is I only see the " " in the file. No coordinate has been written in. Did I do anything wrong while fetching the value from const float GetCoordinate(int nth)?
try to change this
outFile << ("%f", (*it).GetCoordinate(0)); // fails
to this:
outFile << (*it).GetCoordinate(0); // OK
Because the ("%f", (*it).GetCoordinate(0)) represents nothing , only a enumerations of expressions separated by , . It will not be evaluated into a pair of objects as in java is i think.
Edit:("%f", (*it).GetCoordinate(0)) actually evaluates to the last element that is (*it).GetCoordinate(0) ( PlasmaHH comment ) so it should still print something. However if nothing is printed then the collection clusterEntry->clusterPointArray could be empty and the code inside the for loop might not be executed ever.
Hope this helps,
Razvan.
outFile << it->GetCoordinate(0);

c++ overload pointer ostream

I am a learning c++ and have a class project due in 5 days. I've spent 4 hours researching how to do this however I have not come up with an answer yet. Save me stack!
Problem. I have a pointer to a class which holds a dynamic array. I need to take that array and save it to a file to retrieve later. Here are my 2 headers and the implementation. I am not writing the code to "save to file" yet as that will be easy once I get around this issue. My problem is it keeps printing the address of the pointer and not the data within.
vehReg.h
class vehReg {
public:
/* STUFF */
};
}
#endif
vehData.h
#include "vehReg.h"
using namespace std;
class vehData {
public:
//CONSTRUCTORS
vehData();
//DECONSTRUCTOR
~vehData();
//METHODS
friend ostream &operator<<( ostream &output, const vehData &v);
private:
typedef unsigned long longType;
typedef std::size_t sizeType;
sizeType used,capacity;
vehReg *data;
};
}
#endif
vehData.cpp
//CONSTRUCTOR
vehData::vehData(){
capacity = 5;
used = 0;
data = new vehReg[capacity];
}
//DECONSTRUCTOR
vehData::~vehData(){
delete []data;
}
/* TRYING TO ACCOMPLISH THIS WITH AN OSTREAM OVERLOAD */
void vehData::saveDataSloppy(){
ofstream myFile;
myFile.open ("database.db");
for(int i=0;i<used;i++){
myFile << data[i].getOwnerName() << "|";
myFile << data[i].getVehicleLicense() << "|";
myFile << data[i].getVehicleMake() << "|";
myFile << data[i].getVehicleModel() << "|";
myFile << data[i].getVehicleYear() << "\n";
}
myFile.close();
}
void vehData::saveData(){
cout << data;
}
ostream &operator<<(ostream &stream, const vehData &v){
stream << v.data;
}
}
v.data is a pointer, so it prints a pointer. How do you want it to
print whatever the pointer points to. With the exception of character
pointers, the << always prints what you give it (formatted in some
way). If you don't want it to print a pointer, give is something else.
Suppose it did dereference the pointer. What should it print: one
vehReg? 20? A pointer has no information concerning the size. If
you'd used std::vector<vehReg> (a much better choice), it would know
the size, but there's still no overload on std::vector, since the
system still doesn't know how you want it formatted (comma separated?
each on a new line?). And you've not told it how to print a vehReg
either.
You apparently understand the idea of how to overload <<. The first
thing you'll have to do is provide an overload for vehReg as well.
And both overloads must be defined in terms of existing overloads:
there's not one for std::vector, and the one for pointer doesn't do
what you want (and couldn't), so you'll have to loop in your << for
vehData and output each element, with whatever separators you decide
on. (If it's each element on its own line, then you can use std::copy
and an ostream_iterator for the loop, but this may be a bit in advance
of what you've learnt so far.) And forward to the << for vehReg for
each vehReg.
v.data is a pointer so it's a memory address.
*v.data is what the pointer is pointing to (which in this case is an integer).
For example,
#include <iostream>
using namespace std;
void main () {
int *ptr;
int var = 5;
ptr = &var;
cout << ptr << endl;
cout << *ptr << endl;
system("pause");
}
First line will print out something like: 0043F930
Second line will print out: 5
This should print out the elements held in the data array.
void vehData::showStructure() const {
for (int i = 0; i < capacity: i++) {
cout << data[i];
}
cout << endl;
}

Track/Display Array Index As Part Of Cout (C++)

I have a command line C++ program that lets you enter basic information about a person (ID number, name, age, etc.) and I want to output to a console in the following manner:
-------------------------------------------------------------------
Index ID # First Name Last Name Age
-------------------------------------------------------------------
0 1234 John Smith 25
The person objects are stored in an array of Persons and I've overload the ostream (<<) operator to print out all of the fields like you see. The dashed lines and header come from a displayHdg() function. Anyhow, I have not been able to figure out how to get the proper index value for the array. Ideally, I'd like to generate the indices for each line, but all my attempts have failed. The array is looped through and each object printed in the main() function, and the ostream is overloaded in a person class, so I tried to use global variables as well as static variables, and all of those produce incorrect numbering (i.e. show 0, 1 the first time (for 2 objects), then change to 1, 2 on the next display). Any ideas?
Wouldn't this work? (formatting of ID field ommitted)
vector<Person> v;
for (int i = 0; i < v.size(); ++i)
cout << i + 1 << v[i] << endl;
This starts indexing at 1.
EDIT:
OK now I see what you want. You want to find an element in the vector!
std::vector<person>::iterator p =
std::find(Persons.begin(), Persons.end(), element);
if( p != Persons.end() )
{
std::cout << "index of element is: " << p-Persons.begin();
}
If you have the correct formating, you should be able to do the following:
for(size_t i = 0; i < Persons.size(); ++i)
{
cout << i << '\t' << Persons[i] << endl;
}
I would recommend taking a look at the formatting facilities in brief in this post. Using setw, left, right... manipulators is better than doing it manually.
You need to use "find" algorithms to find exact index of Person object in vector < Person>.
You could use wrapper class to hold index and print it according to your formatting in operator<<:
// wrapper to hold index
template<typename T>
struct Ti
{
Ti( size_t index, const T& t ) : index(index), val(t) {}
size_t index;
const T& val;
};
// you class
struct X
{
friend ostream& operator<<( ostream& out, Ti<X>& t );
protected:
int some_data;
};
// operator<< for X
ostream& operator<<( ostream& out, Ti<X>& t )
{
out << "test " << t.index << " " << t.val.some_data;
return out;
}
int main()
{
vector<X> xxx;
for ( size_t i =0; i < xxx.size(); ++i)
cout << Ti<X>(i+1, xxx[i]) << endl;
}