Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[54.224.52.210] |
|
Сообщ.
#1
,
|
|
|
Уважаемые форумчане подскажите такой вопрос ,
как создать структуру во время выполнения программы не зная заранее ни количества не тип полей , и после этого загнать в эту структуру байтовый массив типа псевдо код byte[] BytBuf ; // уже заполненный байтовый массив infCol[] // уже заполненный массив структур "информация о колонках " СТРУКТУРА структ = new СТРУКТУРА() // объявили пустую структуру-приемник for(int n=0; n<Кол-воКолонок ; n++) { структ.ДобавитьНовоеПоле.Тип = infCol[n].type ; } структ = BytBuf ; // вот как то так сразу в массив |
Сообщ.
#2
,
|
|
|
Использовать контейнеры, ну например vector<char>, а этот вектор состоящий из количества байт снова можно положить в контейнер
vector< vector<char> > |
Сообщ.
#3
,
|
|
|
например
std::map<std::string, std::variant> |
Сообщ.
#4
,
|
|
|
Да просто делаете:
class СТРУКТУРА { char **data; int *длина; }; Сначала узнаёте кол-во полей: длина = new int[кол_во]; А после - столько данных и создаёте: data = new char*[кол_во]; Ну а дальше уже выделяете под каждое поле столько байт, сколько надо: data[i] = new char[длина[i]]; |
Сообщ.
#5
,
|
|
|
Цитата ter_nk_ @ Использовать контейнеры, ну например vector<char>, но массив и так находится в byte[] BytBuf, т.е. еще раз переложить в char[] , а потом еще раз , по моему то немного не то , Добавлено Цитата ter_nk_ @ а этот вектор состоящий из количества байт снова можно положить в контейнер vector< vector<char> > такая упаковка наврят ли поможет разобрать массив , или возможно я ошибаюсь , давайте попробуем , вот например вот такой у меня массив уже заполненый байтоми byte[] BytBuf ; // уже заполненный байтовый массив как мне его загнать в vector< vector<char> > с учетом infCol[n].type - "иформация о колонках" Добавлено Цитата Алексей_Л @ например std::map<std::string, std::variant> разверните хоть чуть чуть, подробней , потому что контейнер map я плохо знаю возможно там как то можно сделать , но разве он сам сможет определить тип , контейнеру map я так думаю надо самому указывать строку и тип , и тогда он уже ищет я правильно понимаю ? или нет ? Добавлено Славян ок Ваш вариант сейчас пробую |
Сообщ.
#6
,
|
|
|
Славян помоги пожалуйста , вот примерно накидал насколько хватило ума ,
... // pCol - кол-во колонок в результате // pRecSize - длина строки , одной записи в байтах , в результате // pStr - коли int *dlina = new int[pCol]; // Сначала узнаёте кол-во полей: char **data = new char*[pRecSize]; // А после - столько данных и создаёте : for (long i = 0; i < pStr; i++) //проход как бы по строкам { for (int j = 0; j < pCol; j++) //каждую строку перебираем по количеству полей { data[j] = new char[dlina[i]]; // Ну а дальше уже выделяете под каждое поле столько байт, сколько надо std::cout << data[j] << " "; } std::cout << std::endl; } |
Сообщ.
#7
,
|
|
|
kms а откуда этот массив? я что-то уже позабыл что откуда берётся
|
Сообщ.
#8
,
|
|
|
Цитата Cfon @ а откуда этот массив? из леса вестимо , слышишь батя рубит а отважу из HyTech конечно же вот до сих пор верчу по всякому |
Сообщ.
#9
,
|
|
|
struct CField { int m_type; std::vector<char> m_data; }; struct CRecord { std::vector<CField> m_fields; } .............................................. std::list<CRecord> records; for (....) //Пробегаем по всем строкам { const auto err = hcSqlReadResults(pOper, i, bufOut, sizeof(bufOut), &cntOut);// Чтение результатов char *p = bufOut; CRecord rec; rec.m_fields.reserve(Количство колонок); for (....) //По всем колонкам { CField field; field.m_type = infCol[n].type; field.m_data.insert(field.m_data.end(), p, p + infCol[j].len); rec.m_fields.emplace_back(std::move(field)); p += infCol[j].len; } record.emplace_back(std::move(rec)); } |
Сообщ.
#10
,
|
|
|
Цитата Алексей_Л @ например Думаю std::vector<std::any> будет получше, поменьше оверхеда. |
Сообщ.
#11
,
|
|
|
kms, а можно уточняющий вопрос? Как именно описываются поля структуры, и как содержимое байтового массива соотносится с этими полями? Так то очень сильно смахивает на почти типовую задачу десериализации данных на базе дескрипторов.
Добавлено Должно получиться что-то вроде этого: #include <iostream> #include <cstdlib> #include <sstream> #include <boost/property_tree/ptree.hpp> #include <boost/property_tree/json_parser.hpp> namespace pt = boost::property_tree; enum class ColTypes { Int32, String }; class ColInfo { public: ColInfo(const std::string& colName, ColTypes colType) : m_name(colName) , m_type(colType) { } void ReadFromStream(std::istream& is, pt::ptree& data) { switch (m_type) { case ColTypes::Int32: ReadInt32Col(is, data); break; case ColTypes::String: ReadStringCol(is, data); break; } } private: void ReadInt32Col(std::istream& is, pt::ptree& data) { union { uint8_t buff[sizeof(int32_t)]; int32_t value; }; is.read((char*)buff, sizeof(buff)); data.add(m_name, value); } void ReadStringCol(std::istream& is, pt::ptree& data) { union { uint8_t sizeBuff[sizeof(int32_t)]; int32_t size; }; is.read((char*)sizeBuff, sizeof(sizeBuff)); std::string value(size, '\0'); is.read(&value[0], size); data.add(m_name, value); } private: std::string m_name; ColTypes m_type; }; int main() { pt::ptree props1; pt::ptree props2; props1.put("Col1", 10); props1.put("Col2", "Hello, Wandbox!"); ColInfo colsInfo[] = {{"Col1", ColTypes::Int32}, {"Col2", ColTypes::String}}; std::string bin = {'\x0a', 0, 0, 0, '\x0f', 0, 0, 0, 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'a', 'n', 'd', 'b', 'o', 'x', '!'}; std::istringstream raw(bin); for (auto& colInfo : colsInfo) colInfo.ReadFromStream(raw, props2); pt::write_json(std::cout, props1); pt::write_json(std::cout, props2); // std::cout << jsonRes << std::endl; } |
Сообщ.
#12
,
|
|
|
Цитата kms @ такая упаковка наврят ли поможет разобрать массив , или возможно я ошибаюсь , давайте попробуем , вот например вот такой у меня массив уже заполненый байтоми byte[] BytBuf ; // уже заполненный байтовый массив как мне его загнать в vector< vector<char> > с учетом infCol[n].type - "иформация о колонках" Не очень понимаю. Если у тебя vector< vector<char> > то это массив массивов для тебя 0 1 6 0 5 3 2 3 5 7 4 5 2 4 5 6 Ты можешь добавлять удалять вставлять элементы в любом из них, если информацию о них кранить типа это массив о сем, о том, т.е. 0 1 6 0 5 3 2 это массив о том 3 5 7 4 5 это массив о сем 2 4 5 6 это массив не знаю где то тебе написали struct OneArray { std::string sArrInfo; (ну или идинтификатор, что надо) vector<char> arr; } vector<OneArray> myExample; Сюда добавляй удаляй. |
Сообщ.
#13
,
|
|
|
Олег М спасибо , сделал как Вы написали , компилируется ,
в конце пытаюсь добавить вывод на экран вот так std::copy(records.begin(), records.end(), std::ostream_iterator<std::string>(std::cout, " ")); но пишет ошибку СерьезностьКодОписаниеПроектФайлСтрока ОшибкаC2679бинарный "=": не найден оператор, принимающий правый операнд типа "CRecord" (или приемлемое преобразование отсутствует)AdmHyTechc:\program files (x86)\microsoft visual studio 14.0\vc\include\xutility2148 Добавлено Цитата Flex Ferrum @ а можно уточняющий вопрос? Как именно описываются поля структуры, и как содержимое байтового массива соотносится с этими полями? если будет удобней и не затруднит http://hytechdb.ru/index.php?s=docs&ru=V25...SqlDstInfoT.htm вот так выглядит у меня на сегодняшний день #define HYCFG_WIN32 #include "hscli.h" #include <iostream> #include <memory> #include <vector> #include <list> #include <string> #include <algorithm> #include <iterator> using namespace std; #define SIZE_HCSQLDSTINFOT 128 int main() { //setlocale(LC_ALL, "RUS"); // рус локаль hcERR err ; // Код ошибки hcHDB pdb ; // Адрес памяти, куда будет записан идентификатор соединения. hcHSTMT pOper ; // Адрес памяти, куда будет записан идентификатор оператора. hcSqlParmT Init = { sizeof(Init) }; // Адрес структуры с параметрами инициализации int pCol = 0 ; // количество колонок hcRECNO pStr = 0 ; // количество строк unsigned cntOp = 0 ; // Размер считанной информации в байтах, в ф-ции "Получить информацию об операторе". unsigned pRecSize = 0 ; // Размер читаемой записи в байтах, в ф-ции "Открытие результатов для чтения" . unsigned cntOut = 0 ; // для ф-ции "Чтение результатов" Адрес, куда функция запишет количество байтов данных, помещённых в буфер пользователя. Если это количество разделить на длину записи, то получим количество считанных записей. Неполные записи не присылаются. if (err = hcSqlInit(&Init) != 0) {/* Инициализация клиентской части */ std::cout << "Ошибка с параметрами инициализации \n" ; return 0; } if (hcSqlCheckInit() < 0) { /* Проверка завершения инициализации */ std::cout << "Ошибка завершения инициализации \n" ; return 0; } err = hcSqlAllocConnect(&pdb); // Создать соединение err = hcSqlConnect(pdb, "tcpip:/localhost:13000", "HTADMIN", "PASSWORD");//Установить связь с СУБД err = hcSqlAllocStmt(pdb, &pOper); // Создать оператор err = hcSqlExecDirect(pOper, "fix all; select * from CITY;"); // Выполняем SQLзапрос GROUP TAB TABLES USERSPEC UGROUPS err = hcSqlNumResultCols(pOper, &pCol) ; // Получить количество колонок результата err = hcSqlRowCount(pOper, &pStr) ; // Получить количество строк результата hcSqlDstInfoT *infCol = new hcSqlDstInfoT[pCol];// Структура "Информация о колонках результата" err = hcSqlOpenResults(pOper, &pRecSize); // Открытие результатов для чтения err = hcSqlGetStmtAttr(pOper, HSCLI_STMT_DST_INFO, 0, infCol, pCol * SIZE_HCSQLDSTINFOT, &cntOp);// Получить информацию об операторе char *bufOut = new char[pRecSize * pStr]; // Адрес буфера для присылаемых записей. err = hcSqlReadResults(pOper, 0, bufOut, pRecSize * pStr, &cntOut); // Чтение результатов char *p = bufOut; // делаем указатель на массив for (long i = 0; i < pStr; i++)//идем по строкам { for (int j = 0; j < pCol; j++ ) // идем по колонкам { switch (infCol[j].type) { case HSCLI_ET_CHAR: { // 0 Массив символов длиной не более заданной std::string s(p, infCol[j].len) ; std::cout << s.c_str() << " " ; } break; case HSCLI_ET_ARRA: // 1 Массив байтов заданной длины std::cout << *reinterpret_cast<unsigned char *>(p) << " "; break; case HSCLI_ET_BYTE: // 2 Элемент - unsigned char (короткое целое) short std::cout << *reinterpret_cast<unsigned char *>(p) << " "; break; case HSCLI_ET_INTR: // 3 Элемент - signed short std::cout << *reinterpret_cast<signed short *>(p) << " " ; break; case HSCLI_ET_WORD: // 4 Элемент - unsigned short std::cout << *reinterpret_cast<unsigned short *>(p) << " " ; break; case HSCLI_ET_DATE: // 5 Дата - unsigned short std::cout << *reinterpret_cast<unsigned short *>(p) << " " ; break; case HSCLI_ET_NMBR: //6 Номер - 3-х байтовое целое без знака // std::cout << *reinterpret_cast< *>(p); break; case HSCLI_ET_LONG: //7 Элемент - long int std::cout << *reinterpret_cast<long int *>(p) << " " ; break; case HSCLI_ET_DWRD: // 8 Элемент - unsigned long int в БД это dword std::cout << *reinterpret_cast<unsigned long int *>(p) << " "; break; case HSCLI_ET_FLOA: // 9 Элемент - float std::cout << *reinterpret_cast<float *>(p) << " "; break; case HSCLI_ET_CURR: // 10 Деньги (double) std::cout << *reinterpret_cast<double *>(p) << " "; break; case HSCLI_ET_DFLT: // 11 Элемент - double std::cout << *reinterpret_cast<double *>(p) << " "; break; case HSCLI_ET_QINT: // 12 Элемент - signed __int64 std::cout << *reinterpret_cast<signed __int64 *>(p) << " "; break; case HSCLI_ET_QWRD: // 13 Элемент - unsigned __int64 std::cout << *reinterpret_cast<unsigned __int64 *>(p) << " "; break; } p += infCol[j].len; } std::cout << std::endl ; } hcSqlCloseResults(pOper); // Закрытие доступа к результатам hcSqlFreeConnect(pdb); // Освободить соединение hcSqlDone(); // Завершение работы std::system("pause"); } это работает , но мне хочется изучить этот вопрос полностью, т.е. знать как делается в других СУБД , или вообще возможные варианты Добавлено Цитата Flex Ferrum @ Должно получиться что-то вроде этого: да что то в этом есть , пробую , я так понял надо class ColTypes из этого примера сделать не на дватипа а у меня 13 типов поетому мне надо делать класс с 13 полями на каждый тип |
Сообщ.
#14
,
|
|
|
Олег М
вот так сделал for (int i = 0; i < pStr; i++) //Пробегаем по всем строкам { CRecord rec; rec.m_fields.reserve(pCol); for (int j = 0; j < pCol; j++) //По всем колонкам { CField field; field.m_type = infCol[j].type; field.m_data.insert(field.m_data.end(), p, p + infCol[j].len); rec.m_fields.emplace_back(std::move(field)); field.m_data.insert(field.m_data.end(), p, p + infCol[j].len); p += infCol[j].len; for (int n = 0; n < infCol[j].len; n++)// вывожу на экран cout << field.m_data[n] << " "; } records.emplace_back(std::move(rec)); cout << "\r\n "; } вот такой результат Прикреплённая картинка
|
Сообщ.
#15
,
|
|
|
Цитата kms @ но пишет ошибку Надо добавить операторы вывода в поток struct CField { int m_type; std::vector<char> m_data; friend std::ostream &operator<<(std::ostream &out, const CField &field); }; struct CRecord { std::vector<CField> m_fields; friend std::ostream &operator<<(std::ostream &out, const CRecord &rec); }; std::ostream &operator<<(std::ostream &out, const CField &field) { switch (field.m_type) { case HSCLI_ET_CHAR: // 0 Массив символов длиной не более заданной out << std::string(field.m_data.begin(), field.m_data.end()); break; case HSCLI_ET_ARRA: // 1 Массив байтов заданной длины //out << *reinterpret_cast<unsigned char *>(field.m_data.data()); break; case HSCLI_ET_BYTE: // 2 Элемент - unsigned char (короткое целое) short out << *reinterpret_cast<unsigned char *>(field.m_data.data()); break; case HSCLI_ET_INTR: // 3 Элемент - signed short out << *reinterpret_cast<signed short *>(field.m_data.data()); break; case HSCLI_ET_WORD: // 4 Элемент - unsigned short out << *reinterpret_cast<unsigned short *>(field.m_data.data()); break; ......................................................... } return out; } std::ostream &operator<<(std::ostream &out, const CRecord &rec) { for (auto it = rec.m_fields.begin(), end = rec.m_fields.end(); it != end; ++it) out << *it << ", "; return out; } std::list<CRecord> records; for (int i = 0; i < pStr; i++) //Пробегаем по всем строкам { ................... } for (auto it = records.begin(), end = records.end(); it != end; ++it) std::cout << *it << std::endl; |
Сообщ.
#16
,
|
|
|
Цитата Олег М @ Надо добавить операторы вывода в поток ошибка ОшибкаC2440reinterpret_cast: невозможно преобразовать "const char *" в "unsigned char *"AdmHyTechc:\users\admin\desktop\my_soft_hytech\1_hytech_консоль(2)\admhytech\main.cpp39 ругается на все строчки где out << *reinterpret_cast<signed short *>(field.m_data.data()); |
Сообщ.
#17
,
|
|
|
Покажи код
|
Сообщ.
#18
,
|
|
|
Цитата Олег М @ Покажи код Видать у него field.m_data.data() возвращает указатель на const char*. А reinterprest_cast константность снимать не умеет. Вот и ошибки вылазят. |
Сообщ.
#19
,
|
|
|
Цитата Flex Ferrum @ Видать у него field.m_data.data() возвращает указатель на const char*. А reinterprest_cast константность снимать не умеет. Вот и ошибки вылазят. Кстати, да. Надо в std::ostream &operator<<(std::ostream &out, const CField &field) везде сделать *reinterpret_cast<const ..... *>(field.m_data.data()); Например out << *reinterpret_cast<const signed short *>(field.m_data.data()); |
Сообщ.
#20
,
|
|
|
Олег М сделал все как Вы написали , работает но естественно не так , такая схема не пойдет , почему ?
надо по типам раскладывать два раза 1 раз std::ostream &operator<<(std::ostream &out, const CField &field) { switch (field.m_type) { case HSCLI_ET_CHAR: // 0 Массив символов длиной не более заданной out << std::string(field.m_data.begin(), field.m_data.end()); break; 2раз std::list<CRecord> records; for (int i = 0; i < pStr; i++) //Пробегаем по всем строкам { ................... } |
Сообщ.
#21
,
|
|
|
Цитата kms @ надо по типам раскладывать два раза Что–то насчет второго раза не понял. Где там что раскладывается? |
Сообщ.
#22
,
|
|
|
Цитата Олег М @ Кстати, да. Надо в std::ostream &operator<<(std::ostream &out, const CField &field) везде сделать *reinterpret_cast<const ..... *>(field.m_data.data()); Например out << *reinterpret_cast<const signed short *>(field.m_data.data()); ОК сейчас попробую еще раз может че то не до курил |
Сообщ.
#23
,
|
|
|
Цитата Олег М @ Что–то насчет второго раза не понял. Где там что раскладывается? ну как бы второй раз идет преобразование или я не так понял , ок разбираюсь , пробую |
Сообщ.
#24
,
|
|
|
А обновление делали?
|
Сообщ.
#25
,
|
|
|
Извини за запоздалый ответ
проблема не в заполнении массива, а в том что под динамическую структуру lamp0 память выделяется внутри процедуры lampReset если строку Код: |
Сообщ.
#26
,
|
|
|
Завтра пересмотрю
|