Reputation: 119
this may be a simple problem, but i am not able to figure it out. I have structure like this.
struct emp
{
int empid;
string fname;
}
emp e[10];
I have some data in e[10].
e[0].empid = 1 , e[0].fname = "tanenbaum"
e[1].empid = 2 , e[1].fname = "knuth"
.....
Now if i have given input command line like this:
emp , empid
Now i need to access the structure emp.empid. If i have 10 other structures, i need to access them, when the input gives like structure tag and structure member. Here i am not able to figure out how to attach string variables(emp, empid) to structure members(emp.empid). thanks in advance. EDIT Here is my program.
int main(int argc, char *argv[])
{
char *tag_name = argv[1]; //emp (structure tag name)
char *member_name = argv[2]; // empid (structure member name)
int data = argv[3]; //value: 2
/* I need some mechanism that will convert those tag_name.member_name
to original structure memmber access
tag_name(emp).member_name(empid) == value (2)
Is there any way to map like this
*/
return ;
}
Upvotes: 0
Views: 712
Reputation: 19044
Create a base class for your structure handling. Call it QueryHandlerBase.
Derive classes for each type of structure you want to be able to query. For 'emp' it might be called EmpQueryHandler.
Create a map between structure names and the handlers:
std::map<std::string, QueryHandlerBase *>
Pass the requested structure name to the map to get the pointer to the handler.
Pass the requested field name to the handler. It will be designed to know the fields of that particular structure and do something useful with it (i.e. display the records, etc.).
EDIT: Okay here goes...
#include <iostream>
#include <map>
#include <vector>
#include <string>
struct emp
{
int empid;
std::string fname;
};
class QueryHandlerBase
{
public:
virtual void FieldQuery(std::string const &FieldName,
std::string const &FieldVal) = 0;
};
class EmpQueryHandler : public QueryHandlerBase
{
public:
void AddRecord(int empid, std::string const &fname)
{
emp x;
x.empid = empid;
x.fname = fname;
m_DataVec.push_back(x);
}
virtual void FieldQuery(std::string const &FieldName,
std::string const &FieldVal)
{
std::vector<emp>::iterator i;
i = m_DataVec.begin();
while (i != m_DataVec.end())
{
if (FieldName == "empid")
{
// do something useful
}
if (FieldName == "fname")
{
// do something useful
if ((*i).fname == FieldVal)
{
std::cout << (*i).empid << " " << (*i).fname << std::endl;
}
}
++i;
}
}
private:
std::vector<emp> m_DataVec;
};
int main()
{
std::map<std::string, QueryHandlerBase *> tables;
EmpQueryHandler *pEmp = new EmpQueryHandler;
// make a map entry for your database table
tables["emp"] = pEmp;
// populate some records
pEmp->AddRecord(1, "Bob");
pEmp->AddRecord(2, "Shiela");
pEmp->AddRecord(3, "Elroy");
pEmp->AddRecord(4, "Victoria");
// perform a query
tables["emp"]->FieldQuery("fname", "Shiela");
return 0;
}
Upvotes: 1
Reputation: 6342
EDIT: Using pointer to member operator you can achieve what you wanted. You need to create small database using std::map.
Below is the working program.
#include <iostream>
#include <string>
#include <map>
using namespace std;
struct emp
{
int empid;
int salary;
};
int main(int argc, char *argv[])
{
//member map stores member varialbe names and corresponding offsets.
map<string, int emp::*> memberMap; //It can store offsets of only integer members.
//tagMap stores tag names and object pointer
map<string, emp *> tagMap;
//Allocate for 10 records
emp *e = new emp[10];
//Store sample data in those records.
for(int i = 0; i < 10; i++)
{
e[i].empid = (i+1) * 10;
e[i].salary = (i+1) * 1000;
}
//Populate tag map with tag names and corresponding object pointers
//As of now, we have only emp structure.
//You can add more structures similar to below.
tagMap.insert(pair<string, emp *>("emp", e));
//Get the offsets of member variables of emp structure.
int emp::*offset_empid = &emp::empid;
int emp::*offset_salary = &emp::salary;
//Populate member map with member names and corresponding offsets
memberMap.insert(pair<string, int emp::*>("empid", offset_empid));
memberMap.insert(pair<string, int emp::*>("salary", offset_salary));
//Am passing tag name in argv[1], member name in argv[2] and record id in argv[3] from
//command line
string tagName = argv[1]; //tag name
string memberName = argv[2]; //member name
int recordId = atoi(argv[3]);//record id
//Access member specified like below.
cout<<"Employee details requested are : "<<endl;
cout<<memberName<<"\t"<<(tagMap[tagName]+recordId)->*memberMap[memberName];
//Free the allocated memory.
delete []e;
}
Input:
emp salary 2
Output:
Employee details requested are : salary 3000
I hope you can understand the program using comments i wrote.
Input: i am providing tagName, fieldName and recordId.
Output: i am getting the requested field value from requested record id.
Upvotes: 1
Reputation: 106116
Basically, you have to create the associations in your code. Parse the input into the structure / field values (e.g. inputstringstream >> structure >> separator >> field), then have something like:
if (structure == "emp")
if (field == "empid")
...do something with emp[which_one].empid...
...
If you need to separate these steps of resolving the reference from the code that uses the values, then you may wish to have the above code (i.e. the "do something") set a functor that you can call later when you want the actual value.
To provide more structure to essentially the same approach, you could potentially enhance each structure with an API that knows about its fields:
struct Emp
{
// boost::any can directly return an int, string, double etc...
// you could hack your own union to do this if you needed, or provide
// some common base class around these types
boost::any get(const std::string& identifier) const;
// this one might use std::ostringstream to convert any non-string fields
// into a textual representation, but e.g. you can loose precision
// from floating point values
std::string get(const std::string& identifier) const;
};
You could then put the different accessors into one map...
struct Field_Access
{
virtual boost::any get(const std::string& identifier) const = 0;
virtual bool set(const std::string& identifier, const std::string& value) = 0;
virtual bool set(const std::string& identifier, const int& value) = 0;
};
struct Emp : Field_Access
{
...
};
std::map<std::string, Field_Access*> accessors;
... populate accessors ...
accessors["emp"] = emp;
accessors["emp"][which_one].get("empid");
The possibilities are pretty endless, and your question not specific enough to provide very targetted advice.
Upvotes: 1