Я хочу прочитать файл CSV, в котором содержится таблица базы данных (TPCH). Каждый файл имеет разное количество столбцов, строк и типов данных.
Например:
file1: Int, double, char[]
file2: double, char[], int, int
Еще одно требование — каждый столбец должен находиться в массиве (для каждого столбца — массив, а не в строке).
Мое решение: В настоящее время я создаю массивы во время выполнения с новыми в зависимости от типа данных и размера файла CSV
e.g. file1: would be int[] , double[]...
Затем я сохраняю начальный адрес моего массива как void * на карте (int, void *).
Когда я хочу прочитать значения из массива, я должен извлечь void * и привести его в соответствие с типом.
Как вы можете видеть, у меня много указателей и кастинга, что непослушно. Есть ли лучший способ хранения таблицы в формате столбца? Я хотел использовать массивы, потому что я часто копирую их и передаю по сети. Кроме того, я не хочу использовать библиотеку наддува.
Да, указатели часто приводят к головным болям. Во-первых, я предлагаю вам использовать контейнеры STL, такие как std::vector
, это сделает вашу жизнь проще. Нет надобности, даже новый компилятор C ++, потому что std::vector
здесь с давних времен.
Но я не понимаю, почему вы хотите сохранить начальный адрес вашего массива. В любом случае, если вы просто хотите сохранить адрес, вы можете использовать заголовочный файл <cstdint>
и использовать типы intptr_t / uintptr_t
гарантированно сможет провести void*
,
Это отличный пример использования variant
, В C ++ 17 мы будем иметь это как часть стандартной библиотеки, но сейчас мы застряли, используя boost
реализация.
Если вы не хотите использовать boost
Есть несколько вариантов для вас, но все они, по крайней мере, немного брутто.
void*
, Это нежелательно по многим причинам. Вы уже знаете это, поэтому я не буду углубляться в это здесь.union
, Это также нежелательно при работе с объектами, которые имеют конструкторы и деструкторы. Вы должны помнить, чтобы вызывать деструкторы, и вы должны знать, чтобы вызывать конструкторы на месте. Лучше чем void*
, но только едва. Предполагая, что вы имеете дело со всеми примитивными типами, std::vector<some_union_type>
может быть, не так уж и плохо, но как только вы внесете динамически изменяемые строки, вы окажетесь в мире боли.char[]
(более конкретно, std::vector<char>
) и храните метаданные о типе данных в некотором типе enum. Используйте это перечисление для приведения байтов к правильному типу. Это довольно волосатое решение, которое можно собрать вручную, но оно похоже на то, как variant
обычно реализуется.std::unique_ptr
) и получить их, делая dynamic_cast
пока вы не получите правильный тип (или сохраните тип данных в enum и приведите на основе этого). Это, пожалуй, самое «высокоуровневое» решение, и, вероятно, его проще понять, чем первые три решения.any
(упоминается в другом ответе). Шон Родитель покрывает это Вот. В вашем случае вы можете реализовать что-то вроде variant::visitor
шаблон, чтобы получить данные, которые вы хотите.Возможно используя boost::variant
не выглядит так плохо в конце концов. 😉