Help on passing pointers

Started by
18 comments, last by DevFred 14 years, 2 months ago
I decided to make a little text - based horse racing simulator. I have run into some trouble. The horses and thier property's come from a struct called horse, each horse is declared and their property's are changed in the same .cpp file. Another file needs to acsess these structs. I tried making a pointer to each struct. but i dont really have a way in my head on how to pass them menu.cpp - This is the file that needs the struct.

#include "stdafx.h"
#include <iostream>
#include "windows.h"
#include "horses.h"

using namespace std;

//Call and draw the menu
void displayMenu()
{
	cout<<"\nYou walk up to the betting stands, the horse's statistics are\ndisplayed on a screen"<<endl;
	
}






//Text Functions
void clear_screen()
{
	system("cls");
}

void stall_program(int milleseconds_to_stall)
{
	Sleep(milleseconds_to_stall);
}

void call_horse_stats()
{
	cout<<"\nCharlie - Wins: ";
}


horses.cpp

#include "stdafx.h"
#include <string>
#include <iostream>

using namespace std;

     
  struct horse
	{
		string name;
		int wins;
		int losses;
		double percentChanceOfWining;

	};




//the function used to calculate the horses chances
	double calculate_horses_chances(int wins,int losses)
{

	double horsesChance = (wins / losses) * 100;

	return horsesChance;
}



//initiliaze the horses stats
void init_horses()
{
	
//initliaze the horses
horse charlie;
horse cooldude;
horse shiningFury;
horse burningSoap;
horse smellyPages;

//Set the horses names
charlie.name = "Charlie";
cooldude.name = "Cool Dude";
shiningFury.name = "Shining Fury";
burningSoap.name = "Burning Soap";
smellyPages.name = "Smelly Pages";

//set each horse's wins/losses to a number beetween  1 and 5
//to make it seem like the horse's have raced before and dont have 0 percent odds 

charlie.wins = rand() % 5 + 1;
charlie.losses = rand() % 5 + 1;

cooldude.wins = rand() % 5 + 1;
cooldude.losses = rand() % 5 + 1;

shiningFury.wins = rand() % 5 + 1;
shiningFury.losses = rand() % 5 + 1;

burningSoap.wins = rand() % 5 + 1;
burningSoap.losses = rand() % 5 + 1;

smellyPages.wins = rand() % 5 + 1;
smellyPages.losses = rand() % 5 + 1;


//set up their percent chance of winning
charlie.percentChanceOfWining = calculate_horses_chances(charlie.wins, charlie.losses);
cooldude.percentChanceOfWining = calculate_horses_chances(cooldude.wins, cooldude.losses);
shiningFury.percentChanceOfWining = calculate_horses_chances(shiningFury.wins, shiningFury.losses);
burningSoap.percentChanceOfWining = calculate_horses_chances(burningSoap.wins, burningSoap.losses);
smellyPages.percentChanceOfWining = calculate_horses_chances(smellyPages.wins, smellyPages.losses);


//Set up pointers to the horses
horse * pntrCharlie = &charlie;
horse * pntrCoolDude = &cooldude;
horse * pntrShiningFury = &shiningFury;
horse * pntrSmellyPages = &smellyPages;
}


Any help would be greatly appreciated. :)
Advertisement
One suggestion would be to declare the horses outside of your initialization function. This way you can access them in other places.

//.hhorse charlie;horse cooldude;horse shiningFury;horse burningSoap;horse smellyPages;//.cppinit_horses(){     ...}
Quote:Original post by KyleM
I decided to make a little text - based horse racing simulator. I have run into some trouble. The horses and thier property's come from a struct called horse, each horse is declared and their property's are changed in the same .cpp file. Another file needs to acsess these structs. I tried making a pointer to each struct. but i dont really have a way in my head on how to pass them

menu.cpp - This is the file that needs the struct.
*** Source Snippet Removed ***





horses.cpp
*** Source Snippet Removed ***


Any help would be greatly appreciated. :)


This would be a messy solution but you could try doing this:

#include "stdafx.h"#include <iostream>#include "windows.h"#include "horses.h"extern horse * pntrCharlie;extern horse * pntrCoolDude;extern horse * pntrShiningFury;extern horse * pntrSmellyPages;using namespace std;//Call and draw the menuvoid displayMenu(){	cout<<"\nYou walk up to the betting stands, the horse's statistics are\ndisplayed on a screen"<<endl;	}//Text Functionsvoid clear_screen(){	system("cls");}void stall_program(int milleseconds_to_stall){	Sleep(milleseconds_to_stall);}void call_horse_stats(){	cout<<"\nCharlie - Wins: ";}



#include "stdafx.h"#include <string>#include <iostream>using namespace std;       struct horse	{		string name;		int wins;		int losses;		double percentChanceOfWining;	};//Set up pointers to the horseshorse * pntrCharlie = NULL;horse * pntrCoolDude = NULL;horse * pntrShiningFury = NULL;horse * pntrSmellyPages = NULL;//the function used to calculate the horses chances	double calculate_horses_chances(int wins,int losses){	double horsesChance = (wins / losses) * 100;	return horsesChance;}//initiliaze the horses statsvoid init_horses(){	//initliaze the horseshorse charlie;horse cooldude;horse shiningFury;horse burningSoap;horse smellyPages;//Set the horses namescharlie.name = "Charlie";cooldude.name = "Cool Dude";shiningFury.name = "Shining Fury";burningSoap.name = "Burning Soap";smellyPages.name = "Smelly Pages";//set each horse's wins/losses to a number beetween  1 and 5//to make it seem like the horse's have raced before and dont have 0 percent odds charlie.wins = rand() % 5 + 1;charlie.losses = rand() % 5 + 1;cooldude.wins = rand() % 5 + 1;cooldude.losses = rand() % 5 + 1;shiningFury.wins = rand() % 5 + 1;shiningFury.losses = rand() % 5 + 1;burningSoap.wins = rand() % 5 + 1;burningSoap.losses = rand() % 5 + 1;smellyPages.wins = rand() % 5 + 1;smellyPages.losses = rand() % 5 + 1;//set up their percent chance of winningcharlie.percentChanceOfWining = calculate_horses_chances(charlie.wins, charlie.losses);cooldude.percentChanceOfWining = calculate_horses_chances(cooldude.wins, cooldude.losses);shiningFury.percentChanceOfWining = calculate_horses_chances(shiningFury.wins, shiningFury.losses);burningSoap.percentChanceOfWining = calculate_horses_chances(burningSoap.wins, burningSoap.losses);smellyPages.percentChanceOfWining = calculate_horses_chances(smellyPages.wins, smellyPages.losses);//Set up pointers to the horsespntrCharlie = &charlie;pntrCoolDude = &cooldude;pntrShiningFury = &shiningFury;pntrSmellyPages = &smellyPages;}
Pass the horses to the displayMenu function. You will need a container of some sort. An array is a primitive container.

You will need to move types and functions that are required in multiple files into a header file.

For example, horse.hpp
#ifndef HORSE_HPP#define HORSE_HPP#include <string>struct Horse{	string name;	int wins;	int losses;	double percentChanceOfWining;};const int MaxHorses = 5;struct Race{   Horse horses[MaxHorses];};void printHorseInfo(Horse horse);#endif


And menu.cpp
#include "stdafx.h"#include <iostream>#include "windows.h"#include "horses.h"using namespace std;//Call and draw the menuvoid displayMenu(Race race){	cout << "\nYou walk up to the betting stands, the horse's statistics are\ndisplayed on a screen" << endl;		for(int i = 0 ; i < MaxHorses ; ++i)	{		printHorseStatistics(race.horses);	}}


Then your "init_horses" could return a Race, which in turn returns the horses
// initiliaze the horses statsRace init_horses(){		// initliaze the horses	horse charlie;	horse cooldude;	horse shiningFury;	horse burningSoap;	horse smellyPages;	//Set the horses names	charlie.name = "Charlie";	cooldude.name = "Cool Dude";	shiningFury.name = "Shining Fury";	burningSoap.name = "Burning Soap";	smellyPages.name = "Smelly Pages";	//set each horse's wins/losses to a number beetween  1 and 5	//to make it seem like the horse's have raced before and dont have 0 percent odds 	charlie.wins = rand() % 5 + 1;	charlie.losses = rand() % 5 + 1;	cooldude.wins = rand() % 5 + 1;	cooldude.losses = rand() % 5 + 1;	shiningFury.wins = rand() % 5 + 1;	shiningFury.losses = rand() % 5 + 1;	burningSoap.wins = rand() % 5 + 1;	burningSoap.losses = rand() % 5 + 1;	smellyPages.wins = rand() % 5 + 1;	smellyPages.losses = rand() % 5 + 1;	//set up their percent chance of winning	charlie.percentChanceOfWining = calculate_horses_chances(charlie.wins, charlie.losses);	cooldude.percentChanceOfWining = calculate_horses_chances(cooldude.wins, cooldude.losses);	shiningFury.percentChanceOfWining = calculate_horses_chances(shiningFury.wins, shiningFury.losses);	burningSoap.percentChanceOfWining = calculate_horses_chances(burningSoap.wins, burningSoap.losses);smellyPages.percentChanceOfWining = calculate_horses_chances(smellyPages.wins, smellyPages.losses);	Race race = { charlie, cooldude, shiningFury, burningSoap, smellyPages };	return race;}

Any function that needs access to the horses can be passed the race instance, or just a single horse if that is all that is required. This is a simple example, leaving aside dynamic containers and pass by reference.

One final thing, the following calculation probably won't work for you:
(wins / losses) * 100;

C++ will use integer division unless one of the types is a float or double. This means that the result is the same as division with the remainder discarded. You can change the types of the variables involved, use a cast or simply rearrange the code such that the constant 100.0 is used as the center of the operation:
(wins * 100.0 / losses);

Now the integers are "upgraded" or "promoted" to doubles and you won't have the same problem of the remainder being discarded.

You probably should include a special check in the case losses is 0.
Thanks for the help people. Is passing by pointer not a mroe efficent way to do this, im trying to learn and i was just wondering if it's what i should use here. As for the program im going to try rip-off's way. Thanks guys :)
I am uncertain if you are declaring memory on the heap or not. If you are, take caution when passing pointers around in the code that carry addresses to the heap. Generally, the function that created that pointer should be the same function that deletes the pointer.
Your computer can easily handle copying the couple of bytes that make up a Horse or a Race.

However, as I alluded to in my post, passing by reference is idiomatic in C++. Passing by const reference is safe, it incurs no unnecessary copies and also protects the data by marking it as "const", which prevents it being accidentally modified in the function.

For example, a small change like this to printHorseInfo():
void printHorseInfo(const Horse &horse);

This change needs to be made to both the declaration and definition. Note that the function body does not need to change.

Likewise, displayMenu could be:
void displayMenu(const Race &race)

References are usually a better choice than raw pointers in modern C++. Pointers are generally only used in a handful of situations, and most of these can be wrapped safely. One example is where a "null" value makes sense. It wouldn't make sense to print a null horse, so printHorseInfo() shouldn't take a pointer. But sometimes optional types make sense. For example, a homing rocket launcher might have a target. But if there is nothing to target at the moment then the rocket's target might be set to "null" to indicate this. However, we could use boost::optional to indicate this.

Dynamic allocation and polymorphism are two more cases where pointers might be used. But in modern C++ we would use smart pointers or containers, such as std::shared_ptr<> or std::vector<> to handle such cases.
In addition to the use of vectors, they manage object memory for you, however, you must remember to clear the vector before it goes out of scope.
std::vector does not require you to clear it, it is a RAII type.
Quote:Original post by rip-off
std::vector does not require you to clear it, it is a RAII type.


Is this true even if the vector holds pointers? Does the vector automatically call the destructors?

This topic is closed to new replies.

Advertisement