结构成员访问 - 命令行

时间:2010-10-22 03:51:47

标签: c++ data-structures


这可能是一个简单的问题,但我无法弄清楚。我有这样的结构。


struct emp 
{
  int empid;
  string fname;
}
emp e[10];

我在e [10]中有一些数据。


e[0].empid = 1 , e[0].fname = "tanenbaum"
e[1].empid = 2 , e[1].fname = "knuth"
.....

现在,如果我已经给出了这样的输入命令行:


emp , empid

现在我需要访问结构emp.empid。如果我有10个其他结构,我需要访问它们,当输入给出类似结构标记和结构成员。在这里,我无法弄清楚如何将字符串变量(emp,empid)附加到结构成员(emp.empid)。提前致谢。 修改的 这是我的计划。


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 ; }

3 个答案:

答案 0 :(得分:1)

基本上,您必须在代码中创建关联。将输入解析为结构/字段值(例如inputstringstream>>结构>>分隔符>>字段),然后具有如下内容:

if (structure == "emp")
    if (field == "empid")
        ...do something with emp[which_one].empid...
...

如果您需要将使用这些值的代码解析引用的这些步骤分开,那么您可能希望让上面的代码(即“做某事”)设置一个函子,以后可以在需要时调用实际值。

要为基本相同的方法提供更多结构,您可以使用知道其字段的API来增强每个结构:

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;
};

然后,您可以将不同的访问者放入一个地图......

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");

可能性非常大,而且你的问题不够具体,无法提供非常有针对性的建议。

答案 1 :(得分:1)

  1. 为结构处理创建基类。称之为QueryHandlerBase。

  2. 为您希望能够查询的每种类型的结构派生类。对于'emp',它可能被称为EmpQueryHandler。

  3. 在结构名称和处理程序之间创建一个映射:

  4. std::map<std::string, QueryHandlerBase *>

    1. 将请求的结构名称传递给地图以获取指向处理程序的指针。

    2. 将请求的字段名称传递给处理程序。它将被设计为知道该特定结构的字段并对其做一些有用的事情(即显示记录等)。

    3. 编辑:好的,这里......

      #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;
      }
      

答案 2 :(得分:1)

编辑:使用指向成员操作符的指针,您可以实现您想要的效果。 您需要使用std :: map创建小型数据库。

以下是工作计划。

#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;
}

输入:

  

emp薪水2

输出:

  

要求的员工详细信息是:   工资3000

我希望你能用我写的评论来理解这个程序。

输入:我提供tagName,fieldName和recordId。

输出:我从请求的记录ID中获取请求的字段值。