Access struct variable by its name - c++

im trying to create program which will work with data provided in CSV file.
So far, i've made a structure of this CSV file and able to populate vector with its data.
What im trying to achieve is to allow user to enter Sensor Name and check it with given list of Sensors.
What i want to do is to after user have entered Sensors Name, access already created vector with data and display data of that particular sensor.
Here is the structure i've made:
typedef struct SensorReadings {
int Month;
int Day;
double Dp; // Dew Point Temperature
double Dta; // Wind Direction (10min Avg)
double Dts; // Wind Direction (10min SD)
double EV; // Evaporation (Year to Date)
double QFE; // Barometric Pressure
double QFF; // Barometric Pressure (QFE*Kqff)
double QNH; // Barometric Pressure (Aviation Standard)
double RF; // Rainfall (Year to Date)
} SensorReadings;
And here is the code, where i prompt user to enter Sensor Name:
std::cout << std::endl << std::endl << "Available Sensors: " << std::endl;
std::cout << "Dp Dta Dts EV QFE QFF QNH RF" << std::endl << std::endl;
do {
std::cout << "Please select Sensor you want to work with: ";
std::cin >> selectedSensor;
isSensorValid = std::find(std::begin(availableSensors), std::end(availableSensors), selectedSensor) != std::end(availableSensors);
} while(!isSensorValid);
I also made a method to get Average Daily Value for whole year of data:
double getAverageReadings(int wDay, int wMonth) {
std::vector<SensorReadings> pData = fm.parsedFile;
double DewPointTemperature = 0.0;
for(int r = 0; r < pData.size(); r++) {
if(pData[r].Month == wMonth) {
if(pData[r].Day == wDay) {
if(pData[r].Dp >= 100)
DewPointTemperature = DewPointTemperature + cWTKW(pData[r].Dp);
}
}
}
return DewPointTemperature;
}
This function allows me to get daily average for each day in each month for Dew Point Temperature, what i want to do tho, is to be able do something like this:
double getAverageReadings(int wDay, int wMonth, std::string selectedSensor) {
/*
Magic to convert std::string to actual Structure parameter
Pseudo:
param Sensor = convert(selectedSensor, to SensorReadingsParam);
*/
std::vector<SensorReadings> pData = fm.parsedFile;
double averageReadingsForSensor = 0.0;
for(int r = 0; r < pData.size(); r++) {
if(pData[r].Month == wMonth) {
if(pData[r].Day == wDay) {
if(pData[r].Sensor >= 100)
averageReadingsForSensor = averageReadingsForSensor + cWTKW(pData[r].Sensor);
}
}
}
return averageReadingsForSensor;
}
I've never used to work with 'dynamic' parameters before, so im seeking help on this one.
Thank you for your attention, and for any help on this topic!

You have two basic options:
Instead of declaring an explicit variable for each "sensor", use a std::map.
typedef struct SensorReadings {
int Month;
int Day;
std::map<std::string, double> sensor_value;
} SensorReadings;
And store each sensor value in the map, keyed by sensor name, i.e. sensor_value["Dp"], sensor_value["Dta"], and so on.
Then, given a sensor name std::string sensor_name, you can easily looked up the value of that sensor in the map (after checking that it exists, of course).
The second option is to maintain a separate list of sensor names, and a pointer to the corresponding class member, something like:
static struct {
const char *name;
double SensorReadings::*value;
} sensor_names[]={
{ "Dp", &SensorReadings::Dp },
{ "Dta", &SensorReadings::Dta },
};
And you can use this table to map sensor names to class members. This is a bit more uglier, but it's doable. I would prefer using the first option, myself.

Related

CPP: why is dereferencing a pointer to a template type not populating a variable?

I do a lot of modeling and simulation and I am writing a sim_logger in CPP. The basics of it are this: a user constructs the class with a logging frequency and an output path. They can then "register" any number of variables which gives the logger a reference to the desired variable (its not incredibly safe right now but I'll work on that later, focused on the issue at hand). I've created a template type called "variable" which contains three things, T *var, T last_val, and string ID. My problem is this, whenever I set the last_val equivalent to the var, the last_val inside the variable does not actually change. I am setting this value in line 180 of sim_logger.h. I feel like this is a silly problem, probably due to some misunderstanding I have of pointers. However, I've tried several different things and cannot seem to solve this problem.
sim_logger.h
#include <iostream>
#include <iomanip>
#include <fstream>
#include <vector>
#include <variant>
#include <type_traits>
#include <math.h>
pragma once
// a class to log simulation data
// specifically for logging time dependent differential functions
class sim_logger
{
private:
// a type that represents a variable
/*
meant to contain anything, but limited by the variadic type
"poly_var_types" below
*/
template <typename T>
struct variable
{
T *var; // pointer to the variable itself
T last_val; // the last value of the variable
std::string ident; // the identity of the variable
};
// a variadic type
template <typename ... T>
using poly_var_types = std::variant<T...>;
// defined variable types
// these are the typical types that are logged, feel free to add more
using var_types = poly_var_types<
variable<double>,
variable<float>
// variable<int>,
// variable<bool>,
// variable<std::string>
>;
// class members
std::vector<var_types> registered_variables; // container of all variables
std::ofstream file; // output file stream
double dt; // the logging time step in seconds
double clock = 0.0; // the logging clock in seconds
double last_sim_time = clock; // the last sim time for interp
bool is_time_to_log = false; // flag for log function
const double EPSILON = 0.000000001; // rounding error
// a linear interpolation method
// only returns floating point values
double lin_interp(double x, double x1, double x2, double y1, double y2)
{
return (y1+(x-x1)*((y2-y1)/(x2-x1)));
}
public:
// constructor which sets the logging frequency and output path
// log_dt is a floating point value in units of seconds
// path_to_file is a string representation of the desired output path
sim_logger(double log_dt, std::string path_to_file)
{
dt = log_dt;
file.open(path_to_file);
file << std::setprecision(16) << std::fixed;
}
// method to register a variable with the logger
template <typename T>
void register_variable(std::string ident, T *aVar)
{
variable<T> v;
v.ident = ident;
v.var = aVar;
registered_variables.push_back(v);
};
// a method to write the log file header and log sim time 0.0 data
void write_header_and_log_init_data()
{
// write header
file << "sim_time" << " ";
for (int i = 0; i < registered_variables.size(); i++)
{
std::visit([&](auto rv)
{
if (i == registered_variables.size()-1)
file << rv.ident << "\n";
else
file << rv.ident << " ";
}, registered_variables[i]);
}
// log all registered variables
file << clock << " ";
for (int i = 0; i < registered_variables.size(); i++)
{
std::visit([&](auto rv)
{
if (i == registered_variables.size()-1)
file << *rv.var << "\n";
else
file << *rv.var << " ";
}, registered_variables[i]);
}
}
// method to log all registered variables
void log_data(double sim_time)
{
// check the timing
if (sim_time > (clock + dt))
{
is_time_to_log = true;
}
// check if its time to log
if (is_time_to_log)
{
// update the clock
clock += dt;
// debug
std::cout << "\n";
// log all registered variables
file << clock << " ";
for (int i = 0; i < registered_variables.size(); i++)
{
std::visit([&](auto rv)
{
// instantiate the value to be logged
double log_val;
// debug
std::cout << rv.last_val << " " << *rv.var << std::endl;
// if sim time is even with clock time, log at time
if (fabs(sim_time - clock) < EPSILON)
// if (true)
{
log_val = *rv.var;
}
// if sim time is past clock time, interpolate
else
{
log_val = lin_interp(sim_time, last_sim_time,
clock, rv.last_val, *rv.var);
}
// if last variable in vector create new line
if (i == registered_variables.size()-1)
file << log_val << "\n";
// otherwise just whitespace
else
file << log_val << " ";
}, registered_variables[i]);
}
// debug
std::cout << "\n";
// reset flag
is_time_to_log = false;
}
// get all the last values
for (int i = 0; i < registered_variables.size(); i++)
{
std::visit([&](auto rv)
{
// have to get last value at every update call
// This works in scope but the memory does not actually change?
// I am very confuse.
rv.last_val = *rv.var;
// debug
std::cout << rv.last_val << " " << *rv.var << std::endl;
}, registered_variables[i]);
}
// set the last sim time
last_sim_time = sim_time;
}
};
main.cpp
include <iostream>
include "sim_logger.h"
int main()
{
sim_logger logger(0.1, "sim_logger/log.dat");
double test1 = 100.0;
double test2 = 100.0;
double test3 = 100.0;
logger.register_variable("test1", &test1);
logger.register_variable("test2", &test2);
logger.register_variable("test3", &test3);
logger.write_header_and_log_init_data();
double simTime = 0.0;
double simDt = 1.0 / 20.0;
for (int i = 0; i < 3; i++)
{
simTime += simDt;
test1 += 1.0;
test2 += 2.0;
test3 += 3.0;
logger.log_data(simTime);
}
return 0;
};
output
101 101
102 102
103 103
102 102
104 104
106 106
1.88705e-26 103
1.88705e-26 106
1.88705e-26 109
103 103
106 106
109 109
std::visit([&](auto rv)
rv is, effectively, a parameter to this function (the closure, for the purposes of this answer, is effectively a function).
As you know: in C++ function parameters get passed by value. For example, using a simple function:
void func(int x)
{
x=5;
}
This func can set x to 5 as often as it wants. Whatever actually gets passed in, by anyone that calls func(), will remain unaffected:
int z=7;
func(z);
z is still 7. Even though func set its parameter to 5. This is fundamental to C++:
std::visit([&](auto rv)
{
rv.last_val = *rv.var;
So, this sets rv.last_val. Great. But this has no effect on whatever gets passed into here.
}, registered_variables[i]);
The visited instance of this variant is still what it is. It hasn't changed. Why would it change? C++ does not work this way.
So, if your intent, here, is to modify registered_variables[i], it should be passed by reference:
std::visit([&](auto &rv)
Now, the object referenced by rv gets modified.

c++ Problem sorting struct array, probably issue with pointers [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 months ago.
Improve this question
I am learning c++. I got a struct array that has an attribute that is also a struct.
typedef struct Date
{
int day, month, year;
}Date;
typedef struct {
int order_num;
Date order_day; //Sort
string client;
string tech_type;
int serial_key;
char problem[50];
string technician_name;
char tech_fix[500];
int price;
int days_spent;
string status;
string order_type;
string urgency;
int problems_num;
faults problems[10];
}tech_info;
The question is that I need to sort it via date, that is the second attribute on tech_info.
Here is my attempt:
bool compare_date(const tech_info *a, const tech_info *b)
{
if (a->order_day.year < b->order_day.year)
return true;
if (a->order_day.year == b->order_day.year &&
a->order_day.month < b->order_day.month)
return true;
if (a->order_day.year == b->order_day.year &&
a->order_day.month == b->order_day.month &&
a->order_day.day < b->order_day.day)
return true;
// If none of the above cases satisfy, return false
return false;
}
static void sort_date(tech_info* all_orders[]) {
sort(all_orders, all_orders + counter, compare_date);
cout << "Sorted by date. " << "\n";
}
In this case counter is the amount of entries the user has submitted.
I submit two entries. For the first one I read the information correctly, but for the second one I don't. I'll attach two screenshots to show. Where is my mistake?
Update: Given that I am accessing bad memory I'll post a bit more of my code, all the parts that have to do with this logic.
Here is where I declare my array:
print_menu_initial();
int user_input;
cin >> user_input;
tech_info* orders[100]; //Empty by default
switch (user_input) {
case 1:
do_work_technician_mode(orders);
break;
case 2:
do_work_customer_mode(orders);
break;
}
Then the user does some operations to add orders from here:
static void do_work_customer_mode(tech_info* all_orders[]) {
while (true) {
cin >> user_input;
switch (user_input) {
case 0:
do_work_technician_mode(all_orders);
break;
case 1:
order[counter] = add_order();
all_orders[counter] = &order[counter];
counter++;
break;
case 2:
cout << "How many orders would you like to add? ";
cin >> many_orders;
for (int i = 0; i < many_orders; i++) {
cout << "Information for next order: " << "\n";
order[counter + i] = add_order();
all_orders[counter + 1] = &order[counter + 1];
}
counter = counter + many_orders;
break;
case 6:
sort_date(all_orders);
break;
}
The other cases are irrelevant, I believe. This is the sorting part. Counter is an int variable, declared 0 at start. Whenever the customer adds new entries I increase the value of counter with the number of entries he adds.
Funny enough - for my screenshot - variable a gets read correctly, just b is not being read correctly.
It appears that you have come to C++ from a C background. That is not a bad thing, but I would recommend learning to use as much of the standard library as you can. C++20 in particular has added many features that make it easier to work with collections of objects. This requires a (somewhat) up to date compiler, but is definitely worth it. Here is how I would prefer to approach a problem like this in C++.
There are two choices: keeping the collection of orders sorted at all times, or sorting only when needed. The former can be achieved using an ordered container such as std::set, the latter is what you are currently doing using std::sort. However, you could make your life a lot easier by storing the orders in a container like std::vector. Adding a new order is then as simple as
orders.emplace_back(add_order());
Tracking the number of orders in a counter variable is not necessary, since the vector has a size() function.
Further, if there is a natural choice of ordering among values of a type, as is the case with dates, then the recommendation in C++ is to overload comparison operators. This allows for uniform expression syntax like a != b and x < y when this makes sense for your class. By carefully ordering the members of your Date struct, this can be achieved with almost no code in modern C++:
#include <compare>
struct Date {
int year, month, day;
friend auto operator<=>(Date const&, Date const&) = default;
};
static_assert(Date{2000, 1, 1} < Date{2000, 1, 2});
A more sophisticated approach would also prohibit the construction of invalid dates. Classes designed this way were introduced to the std::chrono namespace with C++20; you should now be able to use a class like year_month_day that provides what you need out of the box.
Either way, C++20's range-based std::ranges::sort algorithm then allows you to specify both a comparison and a projection function; the projected values are compared to determine the sorting order. Therefore, once you have a date class with comparison operators, you can also sort the orders like this:
#include <algorithm>
auto order_date = [](auto const& order) -> auto& { return order.order_date; };
std::ranges::sort(orders, std::ranges::less{}, order_date);
The answer to your problem was a type in all_orders[counter + i] = &order[counter + i];
But since we're here let me clean your code up a bit. I can see you've most likely come from C as most of your syntax is C like. So here are some rules (some may be controvertial but wtvr
typedef struct Date //for structs -> struct NAME. typedef not needed
{
int day, month, year;
}Date; //you're declaring globabl object which isnt that good you want to have as little variables globally
typedef struct { //same here
int order_num; //struct has a lot of variables, i assume all of them are needed
Date order_day; //Sort
string client;
string tech_type;
int serial_key;
char problem[50]; //if this can have many sizes better use string
string technician_name;
char tech_fix[500]; //same here. string. you can always change string to char using function someStringName.c_str() other way round is also possible with minimal effort
int price;
int days_spent;
string status;
string order_type;
string urgency;
int problems_num;
faults problems[10];
}tech_info; //same here
What you'd prefer to see in a cpp program is the following:
struct Date
{
int day, month, year;
};
struct tech_info{
int order_num;
Date order_day; //Sort
string client;
string tech_type;
int serial_key;
string problem;
string technician_name;
string tech_fix;
int price;
int days_spent;
string status;
string order_type;
string urgency;
int problems_num;
faults problems[10];
};
And then your actual objects created in eg main function or some other function.
Next your sorting:
bool compare_date(const tech_info &a, const tech_info &b) //pointers to references
{
if (a.order_day.year < b.order_day.year) //id do it similar but a bit differently
return true;
if (a.order_day.year == b.order_day.year &&
a.order_day.month < b.order_day.month)
return true;
if (a.order_day.year == b.order_day.year &&
a.order_day.month == b.order_day.month &&
a.order_day.day < b.order_day.day)
return true;
// If none of the above cases satisfy, return false
return false;
}
static void sort_date(tech_info* all_orders[]) { //here you have double pointer *name[]. [] also acts as * so you have **all_orders
sort(all_orders, all_orders + counter, compare_date); //sort, assuming its sort() from #include <algorithms> uses i think single pointer to beginning of array, end array then type of sorting
cout << "Sorted by date. " << "\n"; //endl instead of "\n"
}
I'd do it like this:
#include<iostream>
#include<vector>
#include <algorithm>
using namespace std;
struct Date
{
int day, month, year;
Date(int d, int m, int y) : day(d), month(m), year(y) {}
Date() {}
};
struct tech_info{
int order_num;
Date order_day; //Sort
string client;
string tech_type;
int serial_key;
string problem;
string technician_name;
string tech_fix;
int price;
int days_spent;
string status;
string order_type;
string urgency;
int problems_num;
//faults problems[10]; you didnt define what this faults structure was
//making contructor for this class would be perfect
tech_info(int orderNum, int dateDay, int dateMonth, int dateYear, string cl, string techType, int serial, ...)
: order_num(orderNum), Date(dateDay, dateMonth, dateYear), client(cl), tech_type(techType), serial_key(serial), ... {}
tech_info() {}
};
bool compare_date(const tech_info &a, const tech_info &b) //pointers to references
{
if (a.order_day.year == b.order_day.year) //if year is the same
{
if (a.order_day.month == b.order_day.month) //if month is same
{
if (a.order_day.day < b.order_day.day) return true; //if day is different
else return false;
}
else //if month is different
{
if (a.order_day.month < b.order_day.month) return true;
else return false;
}
}
else //if year is different
{
if (a.order_day.year < b.order_day.year) return true;
else return false;
}
}
void sort_date(vector<tech_info> &all_orders) { //i suggest all your tech_info put into vector + no static function
sort(all_orders.begin(), all_orders.end(), compare_date);
cout << "Sorted by date." << endl;
}
int main()
{
vector<tech_info> techInfo;
//to add:
techInfo.emplace_back(tech_info(1,2,3,4,"client","sometech", 1234));
//to remove:
techInfo.erase(techInfo.begin() + 0); //where 0 is the index of the item you want to delete from vector
sort_date(techInfo);
}
Hope this helps!!!

Condensing functions to go two ways in C++

Apparently, I should be able to condense these six functions into three simpler functions that go two ways, using bool logic, but I have no idea where to start!
void footToMeter(int inputfeet) {
double outputMeter = ((inputfeet) / (3.281));
cout << outputMeter;
}
void meterToFoot(int inputmeter) {
double outputFoot = ((inputmeter)*(3.281));
cout << outputFoot;
}
void CtoF(int inputC) {
double outputF = 32 + (inputC*(9.0 / 5.0));
cout << outputF;
}
void FtoC(int inputF) {
double outputC = (5.0 / 9)*(inputF - 32);
cout << outputC;
}
void cMtocF(int inputcM) {
double outputcF = ((inputcM)*(35.315));
cout << outputcF;
}
void cFtocM(int inputcF) {
double outputcM = ((inputcF) / (35.315));
cout << outputcM;
}
One approach would be to add an extra parameter for each function to determine which direction you want to convert.
Example:
void lengthConversion(int inputLength, bool toFeet)
{
double output;
if (toFeet)
output = inputLength * 3.281;
else
output = inputLength / 3.281
cout << output;
}
#forthe has a point though - enum would make it a bit nicer.
To make it into 3 simpler functions. First try and bundle up the similarities between the current functions:
// Put the foot to meter and meter to foot functions into one, with 2 extra boolean values.
void fAndMConversion(int measurement , bool footToMeter , bool meterToFoot) {
if(footToMeter){
double fTm = ((measurement) / (3.281));
cout << fTm;
}
if(meterToFoot){
double mTf = ((measurement)*(3.281));
cout << mTf;
}
}
These are the first two functions. This also allows us to get foot to meter and meter to foot conversion in one call to the function: fAndMConversion(11 , true , true). You can bundle it up even further into a conversions() function with 7 args in total, 6 being booleans.

C++ Graph data Structure

I am writing a graph implementation in c++ where the cities are vertices, flights from one city to another city represent an edge, and the weights are the distances between those cities. The vertices,edges, and weights are stored in a file and when the program runs it would load the vertices, edges, and weights into the program. I am using an adjacency matrix where it represents the edges.
Now when the program runs it will prompt the user to either:
Choose Departure city
Exit. Option two just terminates the program.
If the user chooses option one, then it will list all the cities from the file. There a seven cities I chose. So it will look like 1.)Los Angeles 2.) New York 3.) Miami and so on until option 7. When the user chooses an option it will then list all the destination cities except the departure city the user chose. There would be three possibilities once the user chooses his destination city.
Now the first possibility would be there would be no direct or through connection between city A and city B and the program will output, No destination between [departure city] and [destination city] , press any key to return. Once the user presses any key, the menu will display again. The Second possibility would be if there is a direct connection between the city then the program would output the direct connection between [departure city]-[destination city] = [miles] and the miles between the city, or if there isn't a direct connection it will say no direct connection and the user can go back to the menu.
The third possibility would be that there would be a through connection and it will show the departure city and destination city with all the cities between them and the total miles it covers between them and the user can press any key to return to the menu.
Now the problem I"m having is getting the info from the file, I can't figure out how to get the info from the file or how to write the file so the program knows which are the vertices,edges,and weights. Also, how to display the cities and which have the direct connection, through connection, or no connection at all.
include <iostream>
#include <fstream>
#pragma once
const int NULL_EDGE = 0;
typedef std::string String;
class GraphType
{
private:
int edges[50][50];
int m_numVertices;
int m_maxVertices;
int m_distance;
String* m_vertices;
bool* marks; // marks[i] is the mark for vertices[i]
int IndexIs(String*, String);
public:
GraphType();
~GraphType();
bool isEmpty() const;
bool isFull(); //to do
int GetWeight(String, String); // to do
void ClearMarks(); // to do
void MarkVertex(String) // to do
bool isMarked(String) // to do
void addVertex(String);
void addEdge(String, String, int);
void displayCities();
};
#include "GraphType.h"
GraphType::GraphType()
{
m_maxVertices = 50;
m_distance = 0;
m_vertices = new String[m_maxVertices];
marks = new bool[50];
std::ifstream loadFile;
loadFile.open("load.txt");
if (loadFile.fail())
std::cout << " Error opening load.txt\n";
else
{
//stuck here
}
loadFile.close();
}
GraphType::~GraphType()
{
delete[] m_vertices;
delete[] marks;
}
int GraphType::IndexIs(String* vertices, String vertex)
{
int index = 0;
while (!(vertex == m_vertices[index]) == 0)
index++;
return index;
}
void GraphType::addVertex(String vertex)
{
m_vertices[m_numVertices] = vertex;
for (int i = 0; i < m_numVertices; i++)
{
edges[m_numVertices][i] = NULL_EDGE;
edges[i][m_numVertices] = NULL_EDGE;
}
m_numVertices++;
}
void GraphType::addEdge(String startVertex, String destVertex, int weight)
{
int row;
int col;
row = IndexIs(m_vertices, startVertex);
col = IndexIs(m_vertices, destVertex);
edges[row][col] = weight;
}
void GraphType::displayCities()
{
//stuck here
}
bool GraphType::isEmpty() const
{
return (m_numVertices == 0);
}
#include "GraphType.h"
int FlyMenu();
void CitiesMenu(GraphType&);
int main()
{
int choose;
GraphType gt;
do
{
choose = FlyMenu();
switch (choose)
{
case 1: CitiesMenu(gt);
break;
case 2:
break;
default: std::cout << " Invalid Input\n";
break;
}
} while (choose != 2);
return 0;
}
int FlyMenu()
{
int option;
std::cout << " 1.) Choose Depature City\n";
std::cout << " 2.) Exit\n";
std::cout << " Enter option: ";
std::cin >> option;
return option;
}
void CitiesMenu(GraphType& gt)
{
gt.displayCities();
}
I know about the depth Traversal and breadth Traversal algorithms to see if there is a connection between a city or not, but I don't know how to implement them for this scenario. I can't use the Standard Template Library, only std::vector. I was thinking about writing another class, but I don't know what what that class will help me with.
From what I got you have two questions:
read / write from file: the simplest solution would be freopen.
freopen("input","r",stdin)
freopen("output","w",stdout)
now every cin & cout operation will be done on the files you defined on freopen
implementing DFS / BFS: I will code the simplest type of DFS for you and you have to edit it to suite you program.
bool visit[MAX_CITY + 10];
void DFS(int x){
visit[x] = 1;
for (int i=1;i<=MAX_CITY;i++){
int nx = i;
if (adj[x][i] == -1) continue; // a cost of -1 means no flight
if (visit[nx]) continue;
DFS(nx);
}
}

Declaring my member function parameters/arguments

class Seller
{
private:
float salestotal; // run total of sales in dollars
int lapTopSold; // running total of lap top computers sold
int deskTopSold; // running total of desk top computers sold
int tabletSold; // running total of tablet computers sold
string name; // name of the seller
Seller::Seller(string newname)
{
name = newname;
salestotal = 0.0;
lapTopSold = 0;
deskTopSold = 0;
tabletSold = 0;
}
bool Seller::SellerHasName ( string nameToSearch )
{
if(name == nameToSearch)
return true;
else
return false;
}
class SellerList
{
private:
int num; // current number of salespeople in the list
Seller salespeople[MAX_SELLERS];
public:
// default constructor to make an empty list
SellerList()
{
num = 0;
}
// member functions
// If a salesperson with thisname is in the SellerList, this
// function returns the associated index; otherwise, return NOT_FOUND.
// Params: in
int Find ( string thisName );
void Add(string sellerName);
void Output(string sellerName);
};
int SellerList::Find(string thisName)
{
for(int i = 0; i < MAX_SELLERS; i++)
if(salespeople[i].SellerHasName(thisName))
return i;
return NOT_FOUND;
}
// Add a salesperson to the salespeople list IF the list is not full
// and if the list doesn't already contain the same name.
void SellerList::Add(string sellerName)
{
Seller(sellerName);
num++;
}
I have some issues with the parameters in my functions in my SellerList class. I want to add someone to the salespeople array so I have a record of all my sellers... Bob, Pam, Tim, etc... My constructor Seller(sellerName) creates a Seller with name sellerName.
How do I add this Seller to the Salespeople array and have capability of a way to pull the data back out and use it in more functions such as a Update function, or an output function?
MAX_SELLERS = 10.... I guess my issue is not knowing whether to use parameters of only
Add(string) or Add(Seller, string). Any help would be appreciated.
Not reinvent the wheel. Choose the container appropiate to your problem. In this case, because you are referencing/searching Sellers by a std::string, I suggest you to use a hash table like std::unordered_map (Or std::map search tree if you don't have access to C++11):
int main()
{
std::unordered_map<Seller> sellers;
//Add example:
sellers["seller name string here"] = /* put a seller here */;
//Search example:
std::unordered_map<Seller>::iterator it_result = sellers.find( "seller name string here" );
if( it_result != std::end( sellers ) )
std::cout << "Seller found!" << std::endl;
else
std::cout << "Seller not found :(" << std::endl;
}
How about using STD vector inside of SellerList instead of the array.
vector<Seller> x;
you can do x.push_back(Seller(...)) or x[0].SellerHasName() and x.size() will give you the number of sellers.
maybe something like this?
// Add a salesperson to the salespeople list IF the list is not full
// and if the list doesn't already contain the same name.
void SellerList::Add(string sellerName)
{
if(num < MAX_SELLERS)
salespeople[num++] = new Seller(sellerName);
}