Perform same operation on different class members without duplicate code - c++

How do I perform the same operation on different class members without duplicating code?
I have a function which creates an object of type Farm, and then performs some kind of a calculation on its members (in this case, it prints the member variable, but the code I am currently working on is too complex to copy here in its entirety):
#include <iostream>
#include <String>
class Farm
{
public:
int cows = 1;
int chickens = 2;
int mules = 3;
};
using namespace std;
void count_animals()
{
Farm* animal_farm = new Farm;
cout << animal_farm->chickens;
}
int main()
{
string animals_to_count = "count my chickens";
if (animals_to_count == "count my chickens")
count_animals();
if (animals_to_count == "count my cows")
count_animals();
if (animals_to_count == "count my mules")
count_animals();
return 0;
}
"Count my chickens" is hard-coded in main(). However, in the problem I am working on right now, animals_to_count will come from another function as an argument.
Is it possible to print cows/chickens/mules of animal_farm without using n if statements in count_animals, where n is the number of member variables?
To further clarify my problem: what I am trying to do is have 1 if statement in count_animals() which will identify which member of Farm is printed (change ->chickens to ->cows or to ->mules).
Is what I am trying possible? If not, are there other ways to work around this?

Putting your variables into a vector or other container may be the right answer.
Alternately, you can make a worker function (that you may wish to be private or protected), and getter functions with almost no code. This lets you write your complicated statistics-extraction once, with slim "getters" that make it visible in your preferred way.
class Farm
{
public:
int cows = 1;
int chickens = 2;
int mules = 3;
int get_cow_stats() {return get_complicated_thing(self.cows);}
int get_chicken_stats() {return get_complicated_thing(self.chickens);}
int get_mule_stats() {return get_complicated_thing(self.mules);}
private:
int get_complicated_thing(int animals);
};

Perhaps a pointer-to-member is what you are looking for?
#include <iostream>
using namespace std;
class Farm
{
public:
int cows = 1;
int chickens = 2;
int mules = 3;
};
int Farm::* getMemberPtr(int whichMember)
{
switch (whichMember)
{
case 0: return &Farm::chickens;
case 1: return &Farm::cows;
case 2: return &Farm::mules;
}
throw invalid_argument("");
}
void count_animals(int Farm::*member)
{
Farm animal_farm;
cout << animal_farm.*member;
}
int main()
{
int animals_to_count = ...; // 0, 1, 2, etc
int Farm::* member = getMemberPtr(animals_to_count);
count_animals(member);
return 0;
}
Online Demo

Use std::vector and constant indices:
class Farm
{
public:
std::vector<int> animal_quantity(3);
const int cow_index = 0;
const int chickens_index = 1;
const int mules_index = 2;
};
When referring to the quantity of cows:
std::cout << animal_quantity[cow_index] << "\n";

Related

Understand pointers

#include <iostream>
using namespace std;
class idk{
public:
int x;
int y;
};
void obj(idk* obj[]){
obj[0]-> x = 1000;
obj[0]-> y = 30;
}
int main(){
idk *z[5];
obj(z);
cout << z[0]->x;
return 0;
}
I am just trying out how to use pointers. The problem is when I set my array 'z' size to 5 or any number it doesn't do anything, however when I make it 10 it then prints out the correct output. Ive tried pasting the code into an online compiler and it also plays up there but with other numbers. Is my code wrong or missing some things?
In this
idk *z[5];
you declare 5 idk pointers. These are only pointers that you can assign to point at idks, but you have not created any actual idks. When you later dereference the first pointer you get undefined behavior since it's not actually pointing at an idk:
void obj(idk* obj[]){
obj[0]-> x = 1000; // BOOM
Making the array of pointers actually point at idk instances can be made in many different ways. Here's one:
#include <iostream>
class idk{
public:
int x;
int y;
};
void obj(idk* obj[]){
obj[0]-> x = 1000;
obj[0]-> y = 30;
}
int main(){
idk instances[5];
idk *z[5]{
&instances[0],
&instances[1],
&instances[2],
&instances[3],
&instances[4],
}; // now all five point at one idk instance each
obj(z);
std::cout << z[0]->x;
}
Another option would be to skip the pointer array completely:
#include <iostream>
class idk {
public:
int x;
int y;
};
void obj(idk obj[]) {
obj[0].x = 1000;
obj[0].y = 30;
}
int main() {
idk z[5];
obj(z);
std::cout << z[0].x;
}

Segmentation Fault in memcpy operation of a struct

I am adding the header file and cpp file (it has main fucntion).
AuctionPrices.h
#ifndef AuctionPrices_h
#define AuctionPrices_h
/*
*
* class AuctionPrices - maintains Buy Order, Sell Order books
*/
#include <bits/stdc++.h>
#include <map>
//#pragma pack(1)
struct Order
{
char * itemId;
char * auctionId;
int Side;
};
class AuctionPrices
{
public:
virtual int AddNewOrder(char *itemId, char *auctionId, int Side, int Price) = 0;
virtual int DeleteOrder(char *itemId, char *auctionId) = 0;
virtual int Print() = 0;
};
class AuctionPrice_Imp : public AuctionPrices
{
public:
AuctionPrice_Imp();
~AuctionPrice_Imp();
std::map <int, Order, std::greater< int >> BuyMap;
std::map <int, Order, std::less< int >> SellMap;
int AddNewOrder(char *itemId, char *auctionId, int Side, int Price);
int DeleteOrder(char *itemId, char *auctionId);
int Print();
};
#endif
AuctionPrices_Imp.cpp
/**
* Auction Price Class implementation
* Constructor, AddNewOrder, DeleteOrder, Print
*
*/
#include <bits/stdc++.h>
#include <map>
#include "AuctionPrices.h"
using namespace std;
AuctionPrice_Imp::AuctionPrice_Imp()
{
}
AuctionPrice_Imp::~AuctionPrice_Imp()
{
}
int AuctionPrice_Imp::AddNewOrder(char *itemId, char *auctionId, int Side, int Price)
{
Order order;
memcpy(order.itemId, itemId, strlen(itemId)+1);
memcpy(order.auctionId, auctionId, strlen(auctionId)+1);
order.Side = Side;
if (Side == 1)
{
BuyMap.insert (std::pair<int,Order>(Price,order));
//buyLevels_.insert( std::pair< OfPrice, Level< OrderEntry > >( price, buyLevel ) );
}
else if (Side == 2)
{
SellMap.insert (std::pair<int,Order>(Price,order));
}
else
{
return 0;
}
return 1;
}
int AuctionPrice_Imp::DeleteOrder(char *itemId, char *auctionId)
{
return 0;
}
int AuctionPrice_Imp::Print()
{
std::map <int,Order,std::greater< int >>::iterator buy_it;
std::map <int,Order,std::less< int >>::iterator sell_it;
// Print Sell Map
for ( sell_it = SellMap.begin();sell_it != SellMap.end(); sell_it++)
{
std::cout << sell_it->first << '\t' << std::endl;
}
// Print Buy Map
for ( buy_it = BuyMap.begin();buy_it != BuyMap.end(); buy_it++)
{
std::cout << buy_it->first << '\t' << std::endl;
}
return 1;
}
int main()
{
AuctionPrice_Imp * auctionPrice_Imp = new AuctionPrice_Imp();
/*
AddNewOrder(“item1”, “auction1”, 1, 100)
AddNewOrder(“item1”, “auction2”, 1, 101)
AddNewOrder(“item2”, “order3”, 1, 99)
AddNewOrder(“item2”, “order4”, 2, 100)
*/
auctionPrice_Imp->AddNewOrder("item1", "auction1", 1, 100);
auctionPrice_Imp->AddNewOrder("item1", "auction2", 1, 101);
auctionPrice_Imp->AddNewOrder("item2", "order3", 1, 99);
auctionPrice_Imp->AddNewOrder("item2", "order4", 2, 100);
auctionPrice_Imp->Print();
}
When I am running the code its giving segmentation fault at the line:
memcpy(order.auctionId, auctionId, strlen(auctionId)+1);
Please anyone can help or correct the code.
The functions I am calling are supposed to add the orders to the Maps: BuyMap and SellMap. Once they have added to those map, I am using a print function to print the values.
Order order;
This creates a new Order object. Order does not have a constructor, so none of its class members, itemId, and auctionId, get initialized to point to anything. These pointers are uninitialized, random garbage. Immediately afterwards:
memcpy(order.itemId, itemId, strlen(itemId)+1);
memcpy(order.auctionId, auctionId, strlen(auctionId)+1);
Since neither itemId, nor auctionId, point to sufficient memory that are at least strlen(itemId)+1 or strlen(auctionId)+1 in size, respectively, this results in undefined behavior, and your crash.
In C++, before using a pointer, it is your responsibility to make sure that the pointer is valid, and points to the correct object, objects, or sufficiently-sized memory buffers. C++ will not do that for you, you have to do all that work yourself.
But if your intent is to write modern C++ code, it is much simpler just to use C++ classes, like std::strings instead of plain char * pointers. std::strings automatically handle all these low-level details, manage memory properly, without making it your responsibility to do so. You will find a complete description of std::string and many examples of using it in your C++ textbook.
You should use std::string to avoid having to deal with low level issues of pointers and memory allocation. These are the issues that you are getting wrong in your code. Here's your code rewritten to use std::string
struct Order
{
std::string itemId;
std::string auctionId;
int Side;
};
int AuctionPrice_Imp::AddNewOrder(std::string itemId, std::string auctionId, int Side, int Price)
{
Order order;
order.itemId = itemId;
order.auctionId = auctionId;
order.Side = Side;
See how easy that is? The code to use std::string is no different to the code that handles int.

function parameters that are writeable only by the function itself - recursion counter

So I'm trying to write a recursive function that keeps track of how often it got called. Because of its recursive nature I won't be able to define an iterator inside of it (or maybe it's possible via a pointer?), since it would be redefined whenever the function gets called. So i figured I could use a param of the function itself:
int countRecursive(int cancelCondition, int counter = 0)
{
if(cancelCondition > 0)
{
return countRecursive(--cancelCondition, ++counter);
}
else
{
return counter;
}
}
Now the problem I'm facing is, that the counter would be writeable by the caller of the function, and I want to avoid that.
Then again, it wouldn't help to declare the counter as a const, right?
Is there a way to restrict the variable's manipulation to the function itself?
Or maybe my approach is deeply flawed in the first place?
The only way I can think of solving this, is to use a kind of "wrapper-function" that keeps track of how often the recursive function got called.
An example of what I want to avoid:
//inside main()
int foo {5};
int countToZero = countRecursive(foo, 10);
//countToZero would be 15 instead of 5
The user using my function should not be able to initially set the counter (in this case to 10).
You can take you function as is, and wrap it. One way I have in mind, which completely encapsulates the wrapping is by making your function a static member of a local class. To demonstrate:
int countRecursive(int cancelCondition)
{
struct hidden {
static int countRecursive(int cancelCondition, int counter = 0) {
if(cancelCondition > 0)
{
return countRecursive(--cancelCondition, ++counter);
}
else
{
return counter;
}
}
};
return hidden::countRecursive(cancelCondition);
}
Local classes are a nifty but rarely seen feature of C++. They possess some limitations, but fortunately can have static member functions. No code from outside can ever pass hidden::countRecursive an invalid counter. It's entirely under the control of the countRecursive.
If you can use something else than a free function, I would suggest to use some kind of functor to hold the count, but in case you cant, you may try to use something like this using friendship to do the trick:
#include <memory>
class Counter;
int countRecursive(int cancelCondition, std::unique_ptr<Counter> counter = nullptr);
class Counter {
int count = 0;
private:
friend int countRecursive(int, std::unique_ptr<Counter>);
Counter() = default; // the constructor can only be call within the function
// thus nobody can provide one
};
int countRecursive(int cancelCondition, std::unique_ptr<Counter> c)
{
if (c == nullptr)
c = std::unique_ptr<Counter>(new Counter());
if(cancelCondition > 0)
{
c->count++;
return countRecursive(--cancelCondition, std::move(c));
}
else
{
return c->count;
}
}
int main() {
return countRecursive(12);
}
You can encapsulate the counter:
struct counterRecParam {
counterRecParam(int c) : cancelCondition(c),counter(0) {}
private:
int cancelCondition;
int counter;
friend int countRecursive(counterRecParam);
};
Now the caller cannot modify the counter, and you only need to modify the function slightly:
int countRecursive(counterRecParam crp)
{
if(crp.cancelCondition > 0)
{
--crp.cancelCondition;
++crp.counter;
return countRecursive(crp);
}
else
{
return crp.counter;
}
}
And the implicit conversion lets you call it with an int
counterRecursive(5);
One way to do this is to use a functor. Here's a simple example:
#include <iostream>
class counter
{
public:
unsigned operator()(unsigned m, unsigned n)
{
// increment the count on every iteration
++count;
// rest of the function
if (m == 0)
{
return n + 1;
}
if (n == 0)
{
return operator()(m - 1, 1);
}
return operator()(m - 1, operator()(m, n - 1));
}
std::size_t get_count() const
{
return count;
}
private:
// call count
std::size_t count = 0;
};
int main()
{
auto f = counter();
auto res = f(4, 0);
std::cout << "Result: " << res << "\nNumber of calls: " << f.get_count() << std::endl;
return 0;
}
Output:
Result: 13
Number of calls: 107
Since the count is stored in the object itself, the user cannot overwrite it.
Have you tried using "static" counter variable. Static variables gets initialized just once, and are best candidates to be used as counter variables.

C++, Weird behavior of cout when trying to print integers

Im trying to write a class that stores an id and a value in an container class.
Im using an nested class as my data structure.
When im compiling the code sometimes it prints perfectly, sometimes it prints nothing and sometimes it prints half of the data then stops.
When i debug the code the same weird behavior occours, when it fails during debug it throws an error "Map.exe has triggered a breakpoint.", the Error occours in the print method when im using cout.
cmap.h
#pragma once
class CMap
{
public:
CMap();
~CMap();
CMap& Add(int id, int value);
void print() const;
private:
class container
{
public:
~container();
int container_id = 0;
int container_value = 0;
};
container* p_komp_;
int dim_ = -1;
void resize();
};
cmap.cpp
#include "cmap.h"
#include <iostream>
using namespace std;
CMap::CMap()
{
p_komp_ = new container[0];
}
CMap::~CMap()
{
p_komp_ = nullptr;
cout << "destroy cmap";
}
CMap& CMap::Add(int id, int value)
{
resize();
p_komp_[dim_].container_id = id;
p_komp_[dim_].container_value = value;
return *this;
}
void CMap::resize()
{
container* temp_array = new container[++dim_];
if (dim_ == 0)
{
temp_array[0].container_id = p_komp_[0].container_id;
temp_array[0].container_value = p_komp_[0].container_value;
}
for (unsigned i = 0; i < dim_; i++)
{
temp_array[i].container_id = p_komp_[i].container_id;
temp_array[i].container_value = p_komp_[i].container_value;
}
p_komp_ = temp_array;
}
void CMap::print() const
{
for (unsigned i = 0; i <= dim_; i++)
{
cout << p_komp_[i].container_id;
cout << p_komp_[i].container_value;
}
}
CMap::container::~container()
{
cout << "destruct container";
}
Map.cpp
#include "cmap.h"
#include <iostream>
using namespace std;
void main(void)
{
CMap m2;
m2.Add(1, 7);
m2.Add(3, 5);
m2.print();
}
These two things are a possible reason for your problem:
int dim_ = -1;
and
container* temp_array = new container[++dim_];
When you allocate, you increase dim_ from -1 to 0. That is you create a zero-sized "array", where every indexing into it will be out of bounds and lead to undefined behavior.
You also have memory leaks since you never delete[] what you new[]. I didn't look for more problems, but there probably a more.
And an "array" (created at compile-time or through new[]) will have indexes from 0 to size - 1 (inclusive). You seem to think that the "size" you provide is the top index. It's not, it's the number of elements.
It seems to me that you might need to take a few steps back, get a couple of good books to read, and almost start over.

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