Static int with array C++ - c++

I'm trying to static count my driver user. however it always give me same value instead
class Driver {
private:
static int ID;
string name;
public :
void displayDriver(string n) {
cout << ID << endl;
}
void createDriver(string n) {
name = n ;
ID++;
}
}
int Driver::id=0;
int main() {
Driver driver[10];
Driver[0].createDriver("first");
Driver[1].createDriver("second");
Driver[2].createDriver("first");
Driver[0].displayDriver();
Driver[1].displayDriver();
Driver[2].displayDriver();
}
my expected output should be :
1
2
3
but system shows me :
3
3
3

private:
static int ID;
Denotes that ID is shared among Driver instances. Any change to it (from createDriver in your current code) will be reflected in ALL instances. Don't use static field if you want each instance has its own unique field.

Do something like I show here to get the results you expect. The idea is to keep the next counter in ID but every instance to have its own id that get initialized when you create the driver.
class Driver
{
private:
static int ID;
int my_id;
string name;
public :
void displayDriver(string n)
{
cout << my_id << endl;
}
void createDriver(string n)
{
name = n ;
my_id = ID++;
}
}
int Driver::id=0;
int main
{
Driver driver[10];
Driver[0].createDriver("first");
Driver[1].createDriver("second");
Driver[2].createDriver("first");
Driver[0].displayDriver();
Driver[1].displayDriver();
Driver[2].displayDriver();
}

It is because the value of ID gets incremented each time u createDriver("");
(no matter for which Driver[]) as it is a static variable
So u r incrementing ID progressively to 3 in first 3 lines
while displaying value of ID in next 3 lines
To get the expected output
I think u need to try it like this :
Driver[0].createDriver("");
Driver[0].displayDriver();
Driver[1].createDriver("");
.
.
.
So on!
Note that all drivers have the same ID (static field).

Related

How do I return a class object to an empty state such that it may be reused?

I'm writing a entry-level script to model disease propagation. I'm trying to write it such that I can run multiple trials and output the result each time. The script uses a Person class and a Population class, which consists of a vector of persons. Each trial returns the same result (when tested individually they return different results from the same input). I think I need to wipe my population object each trial, but I'm not quite sure how.
I think I need a destructor but I'm unsure of the syntax. Online resources have been too advanced for my skill level, or have given me error messages when I try to copy their syntax.
class Person {
private: // Person constructor
int status; bool infected;
public:
Person(){
status = 0; infected = false;
};
string status_string(){ // Outputs status of each person with a symbol as a string
};
void update_per(){ // Updates status of each person if they are sic
};
void infect(int n){ // Infects person if they are susceptible (not recovered or vaccinated)
};
void vaccinate(){ // Changes status of person to being vaccinated
};
bool is_stable(){ // Determines if person has recovered from infection
};
int get_status() { // Returns status of person
};
};
class Population { //Create population class
private: //declare private variable npeople
int npeople;
vector<Person> population; //create a vector of Persons named population with size npeople
public:
Population(int n){
srand(time(NULL));
npeople = n;
population = vector<Person>(n);
};
~Population() //DESTRUCTOR
{
delete[] population;
};
void random_infection(int days){ //method to randomly infect one person
};
int count_infected() { //method to count the number of people infected
};
void update_pop(int ncontacts, float contagion, int days) { // Updates the status of each person in population, also simulates spread of disease through contact
};
void print_status(){ // Output status of each person in population
};
void vacc_pop(float prob){ // Vaccinates a set number of people in the population
};
};
int main() {
ofstream popsizeresults;
int size; // Asks user for size of population
int numtrials; // Asks user for number of trials
for (int jjjj=1; jjjj<=numtrials; jjjj++){
int maxsick = 0;
int day = 0;
Population population(size); // Create population
population.vacc_pop(0.5); // Vaccinate population
population.random_infection(5); // Infect one random person in population
int step = 1;
for ( ; ; step++){
// Output status of each person in population
cout<<"In step "<<step<< " #sick: "<<population.count_infected()<<" : ";
population.print_status();
cout<<endl;
// If no people are sick, then the disease has run its course
if(population.count_infected() == 0)
break;
// Update the status of each person and simulate spread of disease
population.update_pop(size*0.25,0.9,5);
if (population.count_infected() > maxsick){
maxsick = population.count_infected();
day = step;
}
}
popsizeresults.open("disease10.txt", ios::app);
popsizeresults << jjjj << "," << step << "," << maxsick << "," << day << "\n";
popsizeresults.close();
//population.~Population(); //call destructor
return 0;
}
}
Before I added the destructor (that isn't working), the output on disease10.txt produces a different for each trial but the same results for each. When it's tested one trial at a time (for the same inputs), it produces different results (which is the goal). I'm not sure if a destructor is actually the answer here, I'm very new to C++. Either way, I'm unsure how to replicate the different results for each trial.
Now I see what you're after, here's a very cut down demonstration of population reset.
See numbered notes in comments for improvements in style etc.
#include <vector>
#include <iostream>
// a very basic Person for exposition
class Person
{
public:
Person() { };
};
// Population cut down to the bare minimum
class Population
{
private:
// note 1: no need to store npeople. a vector has a size(). Why store the same thing twice
// note 2: never use `using namespace std;` at global scope. Spell out std:: explicitly
std::vector<Person> population;
public:
// note 3: number of people can never be negative, so why give ourselves the choice? make it unsiged
Population(unsigned n)
// note 4: use list initialisation in constructors
: population(n)
{
};
// note 5: no need for destructors. google "rule of none", "rule of 5", "rule of 3". Prefer rule of none
// answer:
// a specific function to reset the population
void reset(unsigned n)
{
// destroy old people
population.clear();
// make new people
population.resize(n);
}
// note 6: allows us to print a representation of a population for exposition
friend std::ostream& operator<<(std::ostream& os, Population const& pop)
{
for (Person const& p : pop.population)
{
os << '.';
}
os << "(" << pop.population.size() << " people)";
return os;
}
};
int main()
{
Population population = Population(10);
std::cout << population << '\n';
// note 6: reset the population
population.reset(5);
std::cout << population << '\n';
}
Expected output:
..........(10 people)
.....(5 people)
Live demo:
https://coliru.stacked-crooked.com/a/02868f61f6a3da4d

C++ Can You Change A Protected Variable in a Base Class

#include <iostream>
using namespace std;
class simpleFunction
{
protected:
int score;
public:
simpleFunction()
{
score = 5;
}
int retScore()
{
return score;
}
};
class changeFunction : public simpleFunction
{
public:
void change()
{
score = 6;
}
};
int main()
{
simpleFunction SimpleFunction;
changeFunction ChangeFunction;
cout << SimpleFunction.retScore() << endl;
ChangeFunction.change(); // Changes Score To 6
cout << SimpleFunction.retScore() << endl; // Should Return 6 But Returns 5 Instead
return 0;
}
ive set the score to 5 and when i use the change function it should change it to 6 but instead it returns the value 5.
the only way ive managed to make it work as intended to is by changing the int score variable to a global varible but all the classes can access it which makes it flawed can anyone help or try to explain this problem to me.
The Program Works but im having a problem with returning the correct values just to clear up any misunderstadnings

(C++) Cannot use string::substr to assign substrings to objects

I am designing a cheat for the game WordBrain. Basically this is just a small program that takes a number of letters, permutes the sequence, then splits the sequence into 'words' which have length attribute, then search my text file to file meaningful permutation to print out.
while (next_permutation(letters.begin(), letters.end())) //loop through possible permutations of the combination
{
int position_marker = 0; //serve specific purpose
for (auto x : substring_collection) //trouble is in this loop
{
string temp;
int k = x.take_length();
try { temp = letters.substr(position_marker, k); }
catch (out_of_range) { cout << "OUT OF RANGE"; }
x.set(temp); //member content does not register change
position_marker += x.take_length(); //also member word_length is 0 now, despite their are no invocation of methods capable of changing it
}
if (all_of(substring_collection.begin(), substring_collection.end(), [&](substring & s) {return !(library.find(s.take_content()) == library.end()); }))
{
for (auto x : substring_collection)
{
cout << x.take_content() + " ";
}
}
}
This is the location the trouble stems from. Basically, substring_collection is a vector<substring>, which contains objects of class substring
Here is how the class looks like:
class substring
{
private:
std::string content;
int word_length;
public:
substring() : content(""), word_length(0) {};
substring(std::string & s, int c) : content(s), word_length(c) {};
void set(std::string & s)
{
content = s;
}
void clear()
{
content.clear();
}
void set_length(int c)
{
word_length = c;
}
void showinfo() const
{
std::cout << "Content is " + content << " Length is : " << word_length;
}
int take_length() const
{
return word_length;
}
std::string take_content() const
{
return content;
}
};
I suspect that the reason the code goes wrong is position_marker, whose value depends on the member 'word_length' of the object substring is set to 0.
In the code prior to this loop, I only the setting method for this member to take data from users' input (from std::cin).
Can you please tell me that is there any hidden mechanism that reset the property, or create brand new objects that I did not aware of?
Also, teachings on coding styles are very welcomed. I just started learning to code so any tips are much appreciated.
for (auto x : substring_collection)
Here, x is of type substring. This is a copy of the element in the vector, and then when you modify it, you only modify the copy, not the original.
You'll have to use a reference to modify the original element in the vector
for (auto& x : substring_collection)
For why word_length is 0, I don't know, it isn't in the code you posted. My guess would be that you resized the vector, which called the default constructor of substring, which set word_length to 0.

Accessor Method to view private variable based on argument in a class in c++?

My problem is that I have many variables in my class and I want them to be accessed via an accessor method. Of course I could have several accessor functions to output my private variables but how can I make it so I can access any of them via an argument. My class:
class Character {
public:
void setAttr(string Sname,int Shealth,int SattackLevel,int SdefenseLevel) {
name = Sname;
health = Shealth;
attackLevel = SattackLevel;
defenseLevel = SdefenseLevel;
}
int outputInt(string whatToOutput) {
return whatToOutput //I want this to either be health, attackLevel or defenseLevel
}
private:
string name;
int health;
int attackLevel;
int defenseLevel;
};
Basically what I want to know is how do I return a private variable in regards to the outputInt function. Most OOP tutorials have one function to return each variable which seems like a very unhealthy thing to do in a large program.
C++ doesn't support what you try to accomplish: reflection or detailed runtime information about objects. There is something called "Run-Time Type Information" in C++, but it can't provide information about your variable name: the reason is because, in the compiled and linked binary this information (names of your variables) will not be necessarily present anymore.
However, you can accomplish something close to that, using i.e. std::unordered_map instead of plain integer variables. So it's possible to access values by their names, as strings.
Please consider the following code:
#include <string>
#include <iostream>
#include <unordered_map>
using namespace std;
class Character {
public:
void setAttr(const string& Sname, int Shealth, int SattackLevel, int SdefenseLevel) {
name = Sname;
values.insert(std::make_pair("health", Shealth));
values.insert(std::make_pair("attackLevel", SattackLevel));
values.insert(std::make_pair("defenseLevel", SdefenseLevel));
}
int outputInt(const string& whatToOutput) {
return values.at(whatToOutput);
}
private:
string name;
std::unordered_map<std::string, int> values;
};
int main(int argc, char* argv[]) {
Character yourCharacter;
yourCharacter.setAttr("yourName", 10, 100, 1000);
std::cout << "Health: " << yourCharacter.outputInt("health") <<std::endl;
std::cout << "Attack level: " << yourCharacter.outputInt("attackLevel") << std::endl;
std::cout << "Defense level: " << yourCharacter.outputInt("defenseLevel") << std::endl;
return 0;
}
It will output as expected:
Health: 10
Attack level: 100
Defense level: 1000
Another option without dependency on unordered_map would be, to use predefined static strings for your variable names and an array or vector for your values. So we could replace the class Character above with something like:
static std::string variableNames[3] = {
"health",
"attackLevel",
"defenseLevel"
};
class Character {
public:
void setAttr(const string& Sname, int Shealth, int SattackLevel, int SdefenseLevel) {
name = Sname;
variableValues[0] = Shealth;
variableValues[1] = SattackLevel;
variableValues[2] = SdefenseLevel;
}
int outputInt(const string& whatToOutput) {
int retVal = 0;
for (size_t i = 0; i < sizeof(variableNames)/sizeof(std::string); ++i) {
if (!whatToOutput.compare(variableNames[i])) {
retVal = variableValues[i];
}
}
return retVal;
}
private:
string name;
int variableValues[3];
};
And getting still same output. However, here you have to manage a list with all your variable names inside the string array manually - I don't like this solution and would prefer one of the others above personally.
Most common ways in C++ to handle such a design is to have seperate getHealth(), getAttackLevel(), getDefenseLevel() functions instead. However, this will miss one use-case, which is: if you want to let the user input a string, like i.e. "health" and display the corresponding variable then, you would need to write code by yourself to call the corresponding getXXX() function. If this is not a issue in your case, consider the following code which is much cleaner:
#include <string>
#include <iostream>
using namespace std;
class Character {
public:
void setAttr(const string& Sname, int Shealth, int SattackLevel, int SdefenseLevel) {
name = Sname;
health = Shealth;
attackLevel = SattackLevel;
defenseLevel = SdefenseLevel;
}
int getHealth() const { return health; }
int getAttackLevel() const { return attackLevel; }
int getDefenseLevel() const { return defenseLevel; }
private:
string name;
int health, attackLevel, defenseLevel;
};
int main(int argc, char* argv[]) {
Character yourCharacter;
yourCharacter.setAttr("yourName", 10, 100, 1000);
std::cout << "Health: " << yourCharacter.getHealth() <<std::endl;
std::cout << "Attack level: " << yourCharacter.getAttackLevel() << std::endl;
std::cout << "Defense level: " << yourCharacter.getDefenseLevel() << std::endl;
return 0;
}
One other unrelated advice: Instead of using string as parameter types for your functions, use const string& (const reference to string; see my example code above). This allows easier calling of your functions (they can be called directly with an string literal without the need to create additional variables in the calling code) and they will not make a additional unnecessary copy. The only copy then will take place at: name = Sname; (in your code two copies took place).
I don't know if it can be a good idea for you, but you can use a public typedef struct that you pass by reference and set your value.
class Character {
public:
//...
typedef struct allvalues{
string vname;
int vhealth;
int vattackLevel;
int vdefenseLevel;
}allvalues;
void getValues(allvalues& val){
val.vname = name;
val.vhealth = health;
val.vattackLevel = attackLevel;
val.vdefenseLevel = detenseLevel;
}
//...
};
//...
//somewhere in the code
Character myCarac;
//...
//Here how to use it
Character::allvalues values;
myCarac.getValues(values);

Best stl container for sql parameters

I have to build a dynamic sql query. To proper execute it I have to do it in 3 steps:
Prepare statement
Bind Parameters with functions: bindString(string value, int index); bindInt(int value, int index);
Execute it
Because of the fact, that this query is build dynamically I have to store somewhere proper values for given index.
For example:
SELECT * FROM Table WHERE A = ? AND E = '?';
SELECT * FROM Table WHERE A = ? AND B = ? AND E = '?';
During building query I have to store somewhere that:
In the first case:
index 0 is for int A,
index 1 is for string E
In the second case:
index 0 is for int A
index 1 is for int B
index 2 is for string E
My best idea is to create two maps: < int, string >, < int, int > and during creating query set in first place indexes and in second place values and then creating two loops, one for strings, the second one for integers and binding parameters in them and it works fine.
However I wonder if is it possible to do everything in one loop using succeeding indexes and in type safety way.
Thank You.
I would consider creating a class to wrap SQL parameters.
In fact I would create an abstract class like that :
SQLParameterBase
{
std::string toString() = 0;
void print()
{
std::cout << toString();
}
}
And then a template class :
template<class ParamType>
SQLParameter : public SQLParameterBase
{
private:
ParamType value;
public:
std::string toString()
{
// You can use std::ostringstream to convert to string,
// or create another class (derivated from SQLParameterBase) with very specific values
}
}
And you could use it like that :
SQLParameterBase * params[10];
maps[0] = new SQLParameter<int>();
Hope that will help
Actually it is modified AMDG solution. Thanks to him!
class SQLParam {
public:
virtual ~SqlParam(){}
void bind(DatabaseHandler &db, int index) = 0;
};
class SQLParamInt {
private:
int value;
public:
SqlParamInt(int p_value) : value(p_value) {
}
~SqlParamInt() {}
int bind(DatabaseHandler &db, int index) {
return db.bindInt(value, index);
}
};
class SQLParamString {
private:
string value;
public:
SqlParamString(std::string p_value) : value(p_value) {
}
~SqlParamString() {}
int bind(DatabaseHandler &db, int index) {
return db.bindString(value, index);
}
};
typedef std::vector<std::unique_ptr<SqlParam>> SqlParamsContainer;
typedef std::unique_ptr<SqlParamInt> SqlParamIntPtr;
typedef std::unique_ptr<SqlParamString> SqlParamStringPtr;
In my function, building query:
int buildQuery(RequestHandler &request) {
SqlParamsContainer params;
stringstream query << "SELECT * FROM Table WHERE A = ?";
params.push_back(SqlParamIntPtr(new SqlParamInt(request.A())));
if(request.has_B()) {
params.push_back(SqlParamIntPtr(new SqlParamInt(request.B())));
query << " AND B = ?";
}
if(request.has_C()) {
params.push_back(SqlParamStringPtr(new SqlParamString(request.C())));
query << " AND C = ?";
}
query << ";";
db.prepare(query.str());
for(int i = 0; i < v_container.size(); i++)
v_container.at(i)->bind(db,i);
}
There is Boost::Any while it is more general than what you ask for and does not prevent the user from storing unsupported types you do not need to worry about creating the according subclasses.
If you want to return results as well from your DB Boost::Any might be the answer as well.
I suggest limiting the types in your bind function rather than in the storage. If you work with a variadic bind function this is necessary anyways.