Многомерный динамический массив
Мне нуна сделать массив типа:
=
А[0][1][0] - имя1
A[0][1][1] - псевдоним1
=
А[1][1][0] - имя2
A[1][1][1] - псевдоним2
=
Вобщем в таком стиле...
а лучше
{
string[2];
};
vector< vector<Tuple> >
а ещё лучше давать полям имена, а не индексы
{
string name;
string alias;
};
vector< vector<Tuple> >
Сенкс, дома проверю...если че - отпишусь :)
P.S. Это сугубо личное мнение, подкрепленное работой с Builder :D
1.1 AnsiString является стандартным строковым типом для всех компонентов VCL, посему переводить введённый AnsiString для обработки в string, чтобы потом перевести обратно в выводимый AnsiString - мысль на грани бреда.
1.2. AnsiString имеет множество методов для обработки самого себя, а также на него завязано ещё больше отдельных функций.
1.3. Конечно, использовать char[] всяко быстрее, но дело это сложное, как следствие, чревато множеством багов.
2.1. DynamicArray - стандартный класс Builder для работы с массивами изменяемого размера. Его методы позволяют не только изменять объём выделенной памяти, но и вызывать конструкторы/деструкторы для элементов.
2.2. Как я уже сказал, это сугубо личное мнение, по которому "Holy war" устраивать я не собираюсь ;)
1. Лучше использовать стандартные типы данных языка там, где это возможно, если это не несет дополнительных рассходов.
2. Каждая отдельная библиотека должна выполнять свои отдельные функции. Универсализация библиотек приводит к большему уровню связанности и сложностям с оптимизицией и переносимостью.
VCL, MFC воспринимаются мной в первую очередь, как оконные библиотеки; во вторую - как врапперы над различными системными объектами. Контейнеры и пр. вещи, связанные с организацией данных в программе я бы использовал в последнюю очередь.
3. Надо по возможности обеспечивать как можно меньшее количество взаимосвязей между блоками программы.
Писали - в другой теме.
Но приемлемо (с точки зрения быстродействия и памяти) работающего способа реализации переопределиния оператора [] не нашли :(
а лучше
{
string[2];
};
vector< vector<Tuple> >
а ещё лучше давать полям имена, а не индексы
{
string name;
string alias;
};
vector< vector<Tuple> >
Прошу прощения за то что я такой ламер :) но у мну чето не получается...
Напиши плиз работающий пример с Билдера, как создать и записать чето в этот массив.
Сенкс...
Напиши плиз работающий пример с Билдера, как создать и записать чето в этот массив.
Сенкс...
#include <vector>
using namespace std;
struct Tuple
{
string name;
string alias;
};
int main()
{
vector< vector<Tuple> > arr(10, vector<Tuple>(10));
arr[0][0].name = "name1";
arr[0][0].alias = "alias1";
return 0;
}
А зачем?
Создать то можно, но это геморой будет ещё тот...
Ради аккадемического интереса набросал вот это:
#include <vector>
using namespace std;
template<typename T, int N>
class HyperCube
{
private:
template<typename T, int N>
struct _ContainerType
{
typedef typename _ContainerType<T,N-1>::Type ElemType;
typedef vector<ElemType> Type;
static Type init(const int* dims, const T& val) {
return Type(dims[0], _ContainerType<T,N-1>::init(dims+1, val));
}
};
template<typename T>
struct _ContainerType<T,1>
{
typedef T ElemType;
typedef vector<T> Type;
static Type init(const int* dims, const T& val) {
return Type(dims[0], val);
}
};
typename _ContainerType<T,N>::Type data;
public:
typedef typename _ContainerType<T,N>::ElemType ElemType;
HyperCube(const int* dims, const T& val = T(0))
:data( typename _ContainerType<T,N>::init(dims, val) )
{}
ElemType& operator[](int index) {
return data[index];
}
};
int main()
{
const int dims[] = {2,2};
HyperCube<int, 2> a(dims, 10);
cout << a[1][1] << endl;
return 0;
}
HyperCube<T, N>
T - это тип элемента (в примере int),
N - это количество пространств (в примере 2х мерный массив),
dims - это массив задающий размерность каждого пространства (в примере 2х2).
Создать то можно, но это геморой будет ещё тот...
Ради аккадемического интереса набросал вот это...
Вот, вот. Примерно это я и хотел реализовать, только без вспомогательного массива dims (кстати, нафига он?). Постораюсь разобраться в написанном ;-)
Компилятор выдает ошибку на строке struct _ContainerType<T,1>: Invalid template declaration list. Разве так классы можно объявлять?
P.S. Кстати, почему до сих пор подобный класс не реализован в STL? Неоптимален с точки зрения времени исполнения?
Ну а как задавать размерности?
Допустим есть трехмерный массив 5х3х8, так вот dims и будет задавать размеры каждого пространства, т.е. в данном случае:
const int dims[] = {5,3,8};
Компилятор выдает ошибку на строке struct _ContainerType<T,1>: Invalid template declaration list. Разве так классы можно объявлять?
Видимо, старенький компилятор.
struct _ContainerType<T,1> - это частичная специализация, вполне валидный в C++ прием, главное, чтоб компилятор поддерживал стандарт на таком уровне (я использовал MSVC 7.1).
P.S. Кстати, почему до сих пор подобный класс не реализован в STL? Неоптимален с точки зрения времени исполнения?
Да он в принципе не нужен...
Проще просо написать vector <vector> >, как показал в предыдущем примере.
Хотя, можно глянуть boost, там может и есть нечто подобное.
Мне кажется удобнее задавать размер многомерного массива через конструктор или специальные свойства/методы класса.
Эту ошибку выдавал C++ Builder 6. A Borland Developer Studio 2006 говорит: E2404 Dependent type qualifier 'HyperCube<T,2>::_ContainerType<int>' has no member type named 'Type'.
Так что может это сделано не по стандарту С++?
Проще просо написать vector <vector> >, как показал в предыдущем примере.
Напсать-то проще, а вот пользоваться может быть нет. Нет фунций удаления строк/столбцов, замены их местами, изменения их кол-ва с сохранением значений и т.д. и т.п.
Так он и задается в конструкторе:
HyperCube<int, 2> a(dims, 10); - это и есть вызов конструктора
Эту ошибку выдавал C++ Builder 6. A Borland Developer Studio 2006 говорит: E2404 Dependent type qualifier 'HyperCube<T,2>::_ContainerType<int>' has no member type named 'Type'.
Так что может это сделано не по стандарту С++?
Нет. Всё сделано по стандарту.
Это значит, что этот компилятор не поддерживает стандарт в той мере, в которой это надо для компиляции примера. Либо ты его неправильно скопировал.
Напсать-то проще, а вот пользоваться может быть нет.
И написать и использовать проще. В данном случае "написать" = "использовать".
Нет фунций удаления строк/столбцов, замены их местами, изменения их кол-ва с сохранением значений и т.д. и т.п.
почемуже нет? :)
arr[2].clear(); - удаление 2-го столбца,
arr[2] = arr[3]; - копирование
arr[2].resize() - изменение размера.
значительно проще обернуть конкретный набор векторов (т.е. например два вектора, один вложенный в другой, как в примере), чем делать всеразмерный контейнер. Универсальное - враг хорошего.