Super Noob C++ variable help - c++

Ok, I must preface this by stating that I know so so little about c++ and am hoping someone can just help me out...
I have the below code:
string GoogleMapControl::CreatePolyLine(RideItem *ride)
{
std::vector<RideFilePoint> intervalPoints;
ostringstream oss;
int cp;
int intervalTime = 30; // 30 seconds
int zone =ride->zoneRange();
if(zone >= 0)
{
cp = 300; // default cp to 300 watts
}
else
{
cp = ride->zones->getCP(zone);
}
foreach(RideFilePoint* rfp, ride->ride()->dataPoints())
{
intervalPoints.push_back(*rfp);
if((intervalPoints.back().secs - intervalPoints.front().secs) > intervalTime)
{
// find the avg power and color code it and create a polyline...
AvgPower avgPower = for_each(intervalPoints.begin(),
intervalPoints.end(),
AvgPower());
// find the color
QColor color = GetColor(cp,avgPower);
// create the polyline
CreateSubPolyLine(intervalPoints,oss,color);
intervalPoints.clear();
intervalPoints.push_back(*rfp);
}
}
return oss.str();
}
void GoogleMapControl::CreateSubPolyLine(const std::vector<RideFilePoint> &points,
std::ostringstream &oss,
QColor color)
{
oss.precision(6);
QString colorstr = color.name();
oss.setf(ios::fixed,ios::floatfield);
oss << "var polyline = new GPolyline([";
BOOST_FOREACH(RideFilePoint rfp, points)
{
if (ceil(rfp.lat) != 180 && ceil(rfp.lon) != 180)
{
oss << "new GLatLng(" << rfp.lat << "," << rfp.lon << ")," << endl;
}
}
oss << "],\"" << colorstr.toStdString() << "\",4);";
oss << "GEvent.addListener(polyline, 'mouseover', function() {" << endl
<< "var tooltip_text = 'Avg watts:" << avgPower <<" <br> Avg Speed: <br> Color: "<< colorstr.toStdString() <<"';" << endl
<< "var ss={'weight':8};" << endl
<< "this.setStrokeStyle(ss);" << endl
<< "this.overlay = new MapTooltip(this,tooltip_text);" << endl
<< "map.addOverlay(this.overlay);" << endl
<< "});" << endl
<< "GEvent.addListener(polyline, 'mouseout', function() {" << endl
<< "map.removeOverlay(this.overlay);" << endl
<< "var ss={'weight':5};" << endl
<< "this.setStrokeStyle(ss);" << endl
<< "});" << endl;
oss << "map.addOverlay (polyline);" << endl;
}
And I'm trying to get the avgPower from this part:
AvgPower avgPower = for_each(intervalPoints.begin(),
intervalPoints.end(),
AvgPower());
the first part to cary over to the second part:
<< "var tooltip_text = 'Avg watts:" << avgPower <<" <br> Avg Speed: <br> Color: "<< colorstr.toStdString() <<"';" << endl
But of course I haven't the slightest clue how to do it... anyone feeling generous today?
Thanks in advance

Well you didn't state the problem with the code other than it doesn't work. I'm suspicious of your use of AvgPower() in the for_each. Also, you have AvgPower as a class. why not a double or something? For this code I would have expected to see something like this:
PowerType addIntervals(const RideFilePoint &p1, const RideFilePoint &p2) {
//Add and return.
}
...
...
PowerType total = accumulate(i.begin(), i.end(), PowerType(0.0), &addIntervals);
avg = total/i.length();
read these docs carefully:
http://www.sgi.com/tech/stl/accumulate.html

It seems like you are asking how to access the local variable avgPower within a different function (sorry if I am misunderstanding). This is less about c++ specifically and more about functional or object oriented design. There are many different ways to do this, but here are the sane ones I can think of, in the order of my preference.
Create avgPower (and color), within CreateSubPolyLine. There doesn't really seem to be any reason they are in CreatePolyLine anyway. Implement a separate call if there are other consumers. The function signature would change to
void GoogleMapControl::CreateSubPolyLine(const std::vector &points,
std::ostringstream &oss)
Include it in the function's paramemters, e.g., change the signature to:
void GoogleMapControl::CreateSubPolyLine(const std::vector &points,
std::ostringstream &oss,
const QColor& color,
const AvgPower& avgPower)
Put it in a member variable of GoogleMapControl. It doesn't seem like this would be a bad design choice in my opinion.

Related

How do I stream into a string without creating a named stringstream?

I often end up writing code like this:
SomeStreamableType x;
std::stringstream ss;
ss << "Value is: " << x;
log(ss.str());
The extra line needed to generate the stringstream feels superfulous. I can do this, but it's equally cumbersom:
SomeStreamableType x;
const std::string str = "Value is: " + boost::lexical_cast<std::string>(x);
log(str);
I want to be able to do this:
SomeStreamableType x;
log(std::stringstream() << "Value is: " << x);
Have others encountered this issue and come up with a workaround? I don't want to create any helper functions or classes.
Your code will work without modifications, as long as log accepts an ostream& reference:
void log(ostream& o) {
stringstream* s = dynamic_cast<stringstream*>(&o);
if (s) {
cout << s->str() << endl;
}
}
int main() {
int x = 5, y = 6;
log(stringstream() << "x=" << x << ", y=" << y);
return 0;
}
Demo.
To solve this problem I have often simply done something like this:
#define LOG(m) do{std::ostringstream oss;oss<<m;std::cout<<oss.str()<<'\n';}while(0)
// ...
LOG("some text: " << value1 << ' ' << value2); // no need for '\n'
Now I tend to use a more sophisticated class based solution that has an even nicer interface and doesn't use a horrible macro.

Setting precision of floating point number

Hello guys I am new in C++
I am trying to write the function to calculate the second moment of inertia and set the precision with 3 decimal places.
In the output does not apply the 3 decimal places in the first call but the following 4 calls does applied. Here is my codes , please help me find the error and if possible please explain some details thank you very much !
double beamMoment(double b, double h) //the function that calculating the second moment of inertia
{
double I; //variables b=base, h=height, I= second moment of inertia
I = b * (pow(h, 3.0) / 12); // formular of the second momeent of inertia
ofs << "b=" << b << "," << "h=" << h << "," << "I=" << I << setprecision(3) << fixed << endl;
ofs << endl;
return I;
}
int main()
{
beamMoment(10,100);
beamMoment(33, 66);
beamMoment(44, 88);
beamMoment(26, 51);
beamMoment(7, 19);
system("pause");
return 0;
}
The output in my text file is as follow :
b=10,h=100,I=833333
b=33.000,h=66.000,I=790614.000
b=44.000,h=88.000,I=2498730.667
b=26.000,h=51.000,I=287410.500
b=7.000,h=19.000,I=4001.083
You have to set stream precision before printing a number.
ofs << 5.5555 << setprecision(3) << endl; // prints "5.5555"
ofs << setprecision(3) << 5.5555 << endl; // prints "5.555"
Stream operators << and >> are, in fact, methods that can be chained. Let's say we have a piece of example java code like:
dog.walk().stopByTheTree().pee();
In C++, if we'd use stream operators, it'd look like:
dog << walk << stopByTheTree << pee;
Operations on dog objects are executed from left to right, and the direction of "arrows" doesn't matter. These method names are just syntactic sugar.
Look here for more details.

how to use variables in C++ in the gnuplot-iostream

I am using gnuplot-iostream for c++,my problem is like below:
gp << "set object 1 rect from 3,1 to 3.2,4 fc lt 1 \n";
In the numbers of above, can we use some variables in c++ to replace them? and how to do that? Adding one rectangle is easy, but when I want to add more, that will be very intractable.
I try several ways ,but it does not work.
Thanks ahead!
Never used gnuplot-iostream, but maybe some vanilla C++ will help you, iostream is just a pipe to console, so you cant interrupt the buffer but concatenate information, you could do something like this:
gp << "set object " << 1 << " rect from "
<< 3,1 << " to " << 3.2 << "," << 4 << " fc lt 1 \n";
But i suppose you don't want to do that.
I'd create a struct and overload the << operator to return whatever you need.
struct Rect {
float from[2];
float to[2];
}
std::ostream& operator<<(std::ostream& os, const Rect& obj)
{
std::string formated = "from "
+ std::to_string(obj.from[0]) + ","
+ std::to_string(obj.from[1]) + " to "
+ std::to_string(obj.to[0]) + ","
+ std::to_string(obj.to[1]);
os << formated;
return os;
}
So you can just define rectangles and pass them to the stream
Rect r1 = {{2,41},{63,1.4}};
std::cout << r1; // "from 2,41 to 63,1.4"

How do I modify variables in a function from the main script in C++

I've been at this for a few hours now. I am making a small game in C++ and I am trying to figure out how I can edit variables from inside of a function. I can place the variables in the main() and edit them them there no problem, but I can't figure out what I need to do to edit from a function. Below is the function.
void HeroSelect(string& hero)
{
int gold = 20, health = 5, attack = 5, stats[2] = { health, attack };
string weapon;
cout << "Please choose your hero.\n";
cin >> hero;
if (hero == "Warrior" || hero == "warrior")
{
weapon = "Broad Sword";
cout << "You are a Warrior wielding a " << weapon << endl;
cout << "Good choice.\n"
<< "You start out with " << gold << " gold." << endl
<< "You have " << stats[0]<< " health and " << stats[1] << " attack.\n";
}
Above is the function definition and I want to be able to edit the health when the player gets attacked or say gets a stronger weapon. Below is the main() of the script.
void main()
{
double enter, room1, room2, room3, room4, BossRoom;
int, gold = 20; //This is used as part of check inventory and will be subtracted when necessary
string hero, weapon;
//Set decimal two places
cout.setf(ios::fixed);
cout.setf(ios::showpoint);
cout.precision(2);
Intro(enter);
cout << "The first step in this adventure is to choose your hero. You can choose a warrior, a wizard, or an archer.\n";
HeroSelect(hero);
So let's say he gets a new weapon and it gives +1 attack how do I reflect that in the function? Would I create a separate function for this?
As the player goes through the game, they can type in "stats" whenever, and when they do I want it to display their current health and attack and then essentially just loop back to the beginning of the room or fight they are in.
I know I can make the changes to the variables if I made all of my loops and all of my if-else statements in main(), but I wanted to try this and keep my main script clean. I did stats as an array, because I think it is good to print the array as a list. Any help would be great. Thanks!
You may need to do a refresher on C++ and OOP. Your concept is not bad, but you can possibly make it better. (Granted if you really want to do something in a particular fashion, and you are able to do it in such fashion, then by all means just do it :P).
As mentioned in your comments, a re-engineering of the game design may be in order. You will want to establish a Hero class, with multiple variables or sub-classes as the attributes (for example: strength, health points, weapons class, armor class, etc. (We could go into a lower-level description, but i don't think it's necessary yet). If you plan to have multiple weapons, a weapons class might be a good idea as well, for example you could define the weapon stats: attack damage, attack rate, weapon durability etc...
In these classes you can create "Helper Functions" which you can then use to change the stats of the associated objects. Helper function could be public functions which would allow you to increment/decrement hero health or perhaps a helper function that will increase attack damage?
It seems like you're doing a good job learning, so hopefully you can visualize the idea here. Either way, keep on grinding and feel free to ask for a more in depth answer whenever necessary! I'd love to see your game when your ready for some testing!
There are several ways to handle this.
The first being to create a class which is covered in the comments and the answer by ejsd1989.
The second option is to make these variables global variables by creating them in the main and just pass them through each function by reference. This keeps your main clean like you desired.
For example:
void HeroSelect(string& hero, int &gold, int &health)
The third option is very similar to the second, and it is to store these variables in an array and just modify the array with each function.
Essentially, it boils down to creating a class or passing the variables to the functions you wish to use.
Main is not a script and there are some conceptual problems with design in question. Word by word answer would be: pass function parameters by reference. But it would not be a good solution for the task.
Please consider this example:
uint menu;
Hero * hero;
Room entrance, next[5];
entrance.Enter();
std::cout << "1st step in this adventure is to choose your hero." <<std::endl;
std::cout << "You can choose " <<std::endl;
std::cout << "(1) a warrior " << std::endl;
std::cout << "(2) , a wizard" << std::endl;
std::cout << "(3) , or an archer." << std::endl;
std::cout << "Please choose your hero." << std::endl;
std::cin >> menu;
switch( menu )
{
case 3 : { hero = new Archer; break; }
case 2 : { hero = new Wizard; break; }
default : { hero = new Warrior; break; }
}
hero->Weapon();
hero->Gold();
hero->Health();
hero->Attack();
std::cout << "Which room to enter? 1..5" << std::endl;
std::cin >> menu;
next[menu - 1].Enter();
if( 5 == menu )
{
std::cout << "You are attacked by a troll!" << std::endl;
hero->SetHealth( hero->GetHealth() >> 1 );
}
hero->Health();
You can handle hero types, room instances this way. Find properties of them that could be generalized and make differences via members or inheritance. Design it more carefully and you could minimize e. g. tons of couts and duplicated code branches.
class Room
{
static uint cntr;
std::string name;
public:
Room() : name ( "Room#" ) { if( cntr < 5 ) { name[ name.size() - 1 ] = cntr + '0'; } else { name = "BossRoom"; } ++cntr; }
void Enter() { std::cout << "You have entered " << name << "!" << std::endl; }
};
uint Room::cntr;
struct Limint
{
uint max;
uint curr;
Limint( uint init ) : max ( init ), curr( init ) {}
};
class Hero
{
protected:
std::string type;
uint gold;
Limint hp;
Limint attack;
std::string weapon;
public:
Hero() : type( "Hero" ), gold( 20 ), hp( 50 ), attack(5), weapon( "Kitchen knife" ) {}
uint GetHealth() { return hp.curr; }
void SetHealth( uint health ) { health = std::min( health, hp.max ); hp.curr = health; }
void Weapon() { std::cout << "You are a " << type << " wielding a " << weapon << ". Good choice!" << std::endl; }
void Gold() { std::cout << "You start out with " << gold << " gold." << std::endl; }
void Health() { std::cout << "You have " << hp.curr << " / " << hp.max << " health." << std::endl; }
void Attack() { std::cout << "You have " << attack.curr << " / " << attack.max << " attack." << std::endl; }
};
class Warrior : public Hero
{
public:
Warrior() { type = "Warrior"; weapon = "Broad sword"; }
};
class Wizard : public Hero
{
public:
Wizard() { type = "Wizard"; weapon = "Magic stick"; }
};
class Archer : public Hero
{
public:
Archer() { type = "Archer"; weapon = "Crossbow"; }
};
Have fun!

TOUGH: Dealing with deeply nested pointers in C++

I define this structure:
struct s_molecule
{
std::string res_name;
std::vector<t_particle> my_particles;
std::vector<t_bond> my_bonds;
std::vector<t_angle> my_angles;
std::vector<t_dihedral> my_dihedrals;
s_molecule& operator=(const s_molecule &to_assign)
{
res_name = to_assign.res_name;
my_particles = to_assign.my_particles;
my_bonds = to_assign.my_bonds;
my_angles = to_assign.my_angles;
my_dihedrals = to_assign.my_dihedrals;
return *this;
}
};
and these structures:
typedef struct s_particle
{
t_coordinates position;
double charge;
double mass;
std::string name;
std::vector<t_lj_param>::iterator my_particle_kind_iter;
s_particle& operator=(const s_particle &to_assign)
{
position = to_assign.position;
charge = to_assign.charge;
mass = to_assign.mass;
name = to_assign.name;
my_particle_kind_iter = to_assign.my_particle_kind_iter;
return *this;
}
} t_particle;
struct s_bond
{
t_particle * particle_1;
t_particle * particle_2;
std::vector<t_bond_param>::iterator my_bond_kind_iter;
s_bond& operator=(const s_bond &to_assign)
{
particle_1 = to_assign.particle_1;
particle_2 = to_assign.particle_2;
my_bond_kind_iter = to_assign.my_bond_kind_iter;
return *this;
}
};
and then in my code I return a pointer to an s_molecule (typedef'd to t_molecule, but still).
Using this pointer I can get this code to work:
for (unsigned int i = 0;
i < current_molecule->my_particles.size();
i++)
{
std::cout << "Particle "
<< current_molecule->my_particles[i].name << std::endl
<< "Charge: "
<< current_molecule->my_particles[i].charge << std::endl
<< "Mass: "
<< current_molecule->my_particles[i].mass << std::endl
<< "Particle Kind Name: "
<< (*current_molecule->my_particles[i].my_particle_kind_iter).atom_kind_name
<< std::endl
<< "x: " << current_molecule->my_particles[i].position.x
<< " y: " << current_molecule->my_particles[i].position.y
#ifdef USE_3D_GEOM
<< "z: " << current_molecule->my_particles[i].position.z
#endif
<< std::endl;
}
If I replace it with:
for (std::vector<t_particle>::iterator it = current_molecule->my_particles.begin();
it !=current_molecule->my_particles.end();
it++)
{
std::cout << "Particle "
<< (*it).name << std::endl
<< "Charge: "
<< (*it).charge << std::endl
<< "Mass: "
<< (*it).mass << std::endl
<< "Particle Kind Name: "
<< (*(*it).my_particle_kind_iter).atom_kind_name
<< std::endl
<< "x: " << (*it).position.x
<< " y: " << (*it).position.y
#ifdef USE_3D_GEOM
<< "z: " << (*it).position.z
#endif
<< std::endl;
}
I now get nasty segfaults...
Not to put too much here, but I'm also getting segfaults when I tried to do this:
std::cout << "Bond ATOMS : "
<< (*current_molecule).my_bonds[0].particle_1->name
<< std::endl
Again, current_molecule is a pointer to a s_molecule structure, which contains arrays of structures, which in turn either directly have vars or are pointers. I can't get these multiple layers of indirection to work. Suggestions on fixing these segfaults.
FYI I'm compiling on Linux Centos 5.4 with g++ and using a custom makefile system.
#sbi Thanks for the good advice! I believe you are right -- the assignment overloaded operator is unnecessary and should be scrapped.
I've followed the approach of commenting out stuff and am very confused. Basically in the function that passes the pointer to my particular molecule to the main function to print, I can see all the data in that molecule (bonds, particles, name, etc) perfectly, printing with cout's.
Once I pass it to the main as a ptr, if I use that ptr with an iterator I get a segfault. In other words. Also for some reason the bond data (which I can freely print in my funct that returns to the pointer) also segfaults if I try to print it, even if I use the [] to index the vector of bonds (which works for the particle vector).
That's the best info I can give for now.
A wild guess: Are you using shared libraries. I remember having difficulties passing STL-containers back and forth across shared library boundaries.
Jason (OP) was asked in a comment by David Rodríguez:
Are you returning a pointer to a local variable?
Jason answered:
No its a ptr to a class variable. The class is very much in existence (it contains the function that returns the molecule).
Unless you're talking of a true class variable (qualified as static), the fact that the class exists doesn't have much to do with it. Instances of a class exist, and they might have ceased to exist even if you just called a function on them.
As such, the question is:
Does the instance of the class that returned the pointer current_molecule still exist?
Or is current_molecule qualified as static, i.e. being a true class variable?
If the answer to both questions is "no", you're in Undefined County.
At this point, it becomes very important that you post source code that can be used by us here to actually reproduce the problem; it might well be located in source you aren't showing us.
Again, this issue was answered here:
Weird Pointer issue in C++
by DeadMG. Sorry for the double post.