Я думаю, это должно быть возможно. Я пытался, но не мог найти хороший ответ. Я в основном хочу сделать динамическую структуру. Я хочу прочитать файл, который сообщает мне типы данных, которые будет содержать моя структура. Основываясь на этих значениях, я хочу построить структуру. Я хочу использовать C ++ для этого. Мы можем рассматривать oracle как пример для этого, где мы даем файл csv, и он распознает, какого типа они должны быть, и создает столбцы с этим конкретным типом данных.
Может кто-нибудь, пожалуйста, помогите мне с этой проблемой?
Обновление: я полагаю, мне следовало добавить немного кода, чтобы объяснить мою проблему. Итак, поехали:
//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;
}
Этот код работает для меня сейчас и решает мою задачу, когда я вызываю GetHeader. Как вы все можете видеть, он ищет точные байты и структуру из ПЛК. Я хочу сделать систему такой, чтобы структура могла быть сделана из файла так, чтобы только файл был заменен, и тогда система должна работать сама по себе. Я думаю, что я могу изучить некоторые вещи в шаблоне фабричного дизайна, чтобы сделать это. Прямо сейчас я могу определить тип файла и его содержимое для моей структуры данных. Кто-нибудь делал что-то похожее на этой стороне?
Маловероятно создавать типы данных C ++ во время выполнения, поскольку C ++ является языком статической типизации. Вам лучше использовать Python или другой динамически типизированный язык. Однако, если вы думаете о проблеме как о задаче поиска значения, связанного с ключом, это выполнимо, но результирующие «структуры» будут нигде не так близки, как статически определенные типы C ++.
Для одноуровневых структур (без подструктур) вы можете использовать любой класс key-> value, который вы хотели бы получить по следующим направлениям: std::map<std::string, std::pair<type, std::uniq_ptr<...>>>
, То есть ключи как строки отображаются в пары, где первый член пары идентифицирует тип значения, а второй содержит общий указатель на само значение. При условии ограниченного числа типов, которые вы хотите поддерживать, вы можете написать динамический диспетчер, который будет сбрасывать ссылки на фактические типы данных для сохраненных значений.
Если входные типы могут содержать подструктуры, все становится более сложным. Но, учитывая, что языки для полуструктурированных данных существуют (см. XML, JSON и т. Д.), Вы можете найти готовое решение для произвольно сложных структурированных данных.
Ну, вы почти всегда можете что-то сделать, но вы можете использовать не тот язык. C ++ строго типизирован, как указывает Макс — другие языки, например, PHP — нет — и может фактически изменить тип. То, что вы могли бы сделать, это похоже на переход на свой собственный язык, это переопределить ваши математические операторы, такие как +, — и т. Д., Чтобы у вас был базовый класс, который принимает данные — и определяет, является ли это float, string, integer и т. Д. Вы используете объект, как будто это был номер. Все они будут объектами в вашей структуре, но переопределяют по математике и т. Д. Много работы для этого — но есть примеры, касающиеся переопределения математических операторов и т. Д.
Как говорили другие, это невозможно сделать, по крайней мере, не так, чтобы вы получили структуру или класс с переменными-членами с правильными типами.
Что вы можете сделать, это проанализировать файл и угадать тип данных из формата значения, затем создать соответствующий тип (вы должны реализовать его для всех типов, которые вы хотите поддерживать), и, наконец, определить структуру данных, которая хранит все значения с их различными типами (например, вектор с позицией в качестве индекса и использованием boost :: any для значений).
Как примечание стороны:
Помните, что вы можете использовать разные типы значений в одной и той же позиции, например, если значение однажды записано как «123» и один раз как «83,45». Первое значение, вероятно, будет храниться как некое целое число, а второе — с плавающей точкой или двойным числом.