简体   繁体   中英

How to read a file and build a Data Structure based on the input file using C++?

I guess this should be possible. I tried but could not find a good answer. I basically want to make a dynamic structure. I want to read a file which tells me the datatypes that my structure will contain. Based on that values I want to build a structure. I want to use C++ for this. We can think of oracle as an example for this where we give a csv file and it recognizes what type they should be and makes columns of that particular datatype.

Can anyone please help me with this problem ?

An Update: I guess I should have added little bit of code to explain my problem statement. So here we go:

//PLC Data Block Sturcture.
//Todo: try to construct this structure from a file or something
struct MMSDataHeader{
    bool          bHeader_Trigger;      //2
    unsigned char MachineTimeStamp[8];  //8
    std::string   Header_MachineID;     //12
    std::string   Header_Station;       //12
    int           Header_MessageID;     //2
    int           Header_MessageSequenceNo; //2
    int           Header_NumberOfProperties; //2
    int           MeasurementType;          //2
    bool          Response_Acknowledge;     //2
};
typedef struct MMSDataHeader MMSDataHeader;

int PLCBox::GetHeader(){

   MMSDataHeader local_PLCData = { 0 };
  int res = -1;

  std::cout << "Reading Head :";
  if ((p_s7Client_ == NULL))  {
    std::cerr << "TSnap7Client is not connected.\n";
  }

  res = p_s7Client_->DBRead(nb_db_num_, 0, k_header_size, (void *)(&buffer_));    
  //synchronous mode: default mode
  //inFile.read(buffer_, sizeof(buffer_));
  memcpy(&local_PLCData.bHeader_Trigger, buffer_, 1);
  memcpy(local_PLCData.MachineTimeStamp, buffer_ + 2, 8);
  memcpy(&local_PLCData.Header_MachineID, buffer_ + 10, 12);
  memcpy(&local_PLCData.Header_Station, buffer_ + 22, 12);
  memcpy(&local_PLCData.Header_MessageID, buffer_ + 34, 2);
  memcpy(&local_PLCData.Header_MessageSequenceNo, buffer_ + 36, 2);
  memcpy(&local_PLCData.Header_NumberOfProperties, buffer_ + 39, 2);
  memcpy(&local_PLCData.MeasurementType, buffer_ + 40, 2);
  memcpy(&local_PLCData.Response_Acknowledge, buffer_ + 42, 1);

  nb_props = local_PLCData.Header_NumberOfProperties;
  _b_read_trigger = local_PLCData.bHeader_Trigger;

  return local_PLCData.Header_NumberOfProperties;
}

This code works for me now and solves my purpose when I call GetHeader . As you all can see it is looking for exact bytes and structure from the PLCs. I want to make a system such that the structure can be made from a file such that onle a file should be replaced and then the system should work on its own. I think I can explore some things about factory Design pattern to do this. Right now I can determine the type of file and content of the file for my Data structure Construction. Has anyone done something similar on there side.

It is unlikely to be possible to build C++ data types at runtime because C++ is a statically typed language. You'd better use Python or another dynamically typed language. However, if you think about the problem as about a task of finding a value associated with a key, it is doable, but the resulting "structures" will be nowhere close as fast as statically defined C++ types.

For single-level structures (no sub-structures) you can use a whatever sort of key->value class you would want something along these lines: std::map<std::string, std::pair<type, std::uniq_ptr<...>>> . That is, keys as strings are mapped to pairs where the first pair member identifies the value's type, and the second holds a generic pointer to value itself. Provided that there is limited number of types you want to support, you can write a dynamic dispatcher that casts references to actual data types for stored values.

If the input types are allowed to contain sub-structures, things become more complicated. But given that languages for semi-structured data exist (see XML, JSON etc.), you can find a ready solution for arbitrarily complex structured data.

Well, you can almost always do something - but you might be using the wrong language. C++ is strongly typed, as Max is pointing out - other languages, for example, PHP are not - and can actually change type. What you could do, which is like rolling your own language, is to override your math operators like +, -, etc so that you have a base class which takes data - and determines if it is float,string, integer, etc and then you use the object like it was a number. They will all be objects in your structure, but overrides for math, etc. A lot of work to do this - but there are examples out there regarding overriding math operators, etc.

As the others said, it cannot be done, at least not in the way that you end up with a structure or class with the member variables with the correct types.

What you can do is parse the file and guess the data type from the format of the value, then create the corresponding type (you have to implement that for all the types you want to support), and finally define a data structure that stores all values with their different types (eg a vector with the position as index and using boost::any for the values).

As a side note:
Be aware that you can end up with different types for values at the same position, eg if a value is once written as '123' and once as '83.45'. The first value would probably stored as some kind of integer, while the second would result in a float or double.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM