Guest |
Отправлено: 30.03.2004, 17:37 |
|
Не зарегистрирован
|
Привет. Есть ListBox с заранее неизвестным количеством элементов в нем. После заполнения юзером данного ListBox-а, нужно динамически создать структуру и заполнить её данными из ListBox-а.
Т.е. я пытаюсь сделать что-то типа:
CODE |
struct Parameters {
AnsiString Pattern[];
int a;
bool flag;
};
Parameters &Params = *new Parameters;
for(int i = 0; i < ListBox1->Items->Count; i++)
{
Params.Pattern[i] = ListBox1->Items->Strings[i];
}
|
При этом вылетает Access Violation, оно то и понятно, т.к. неизвестен размер AnsiString Pattern[]; и к тому же он не проинициализирован...
Но в том то и все дело что я ж заранее не знаю сколько элементов будет в ListBox1 ??? И как же мне создать тогда структуру в подобной ситуации???
А если я пытаюсь объявить так:
CODE |
struct Parameters {
AnsiString Pattern[ListBox1->Items->Count];
int a;
bool flag;
};
|
То тоже ругается, мол должно быть константное выражение...
Как быть?
|
|
Asher |
Отправлено: 30.03.2004, 17:46 |
|
Мастер участка
Группа: Модератор
Сообщений: 550
|
использовать STL
например std::vector
Или вместо массива AnsiString используйте тот-же StringList
или заведите указатель на массив AnsiString *Pattern
а в нужном месте Pattern = new AnsiString [Size];
главное потом не забыть delete [ ] Pattern;
Способов масса.
|
|
Guest |
Отправлено: 30.03.2004, 18:38 |
|
Не зарегистрирован
|
А можете привести примерчик, как это сделать через TstringList к примеру????
И что такое STL? |
|
Guest |
Отправлено: 30.03.2004, 19:02 |
|
Не зарегистрирован
|
И еще такой вопрос: к примеру у меня получилось, делал так
CODE |
struct Parameters {
AnsiString *Pattern;
int a;
bool flag;
};
Parameters &Params = *new Parameters;
Params.Pattern = new AnsiString[ListBox1->Items->Count];
for(int i = 0; i < ListBox1->Items->Count; i++)
{
Params.Pattern[i] = ListBox1->Items->Strings[i];
}
delete &Params;
|
А если нужно сделать то же самое, только для двухмерного массива AnsiString, т.е. как объявить двухмерный массив AnsiString в данной структуре и выделить под него память??? . Как это все тогда будет выглядеть??? Привидите пожалуйста пример...
|
|
exp |
Отправлено: 30.03.2004, 23:50 |
|
Мастер участка
Группа: Участник
Сообщений: 304
|
Допустим ьебе надо выделить массивчик двумерненький размером
ListBox1->Items->Count*N
Тады Вместо *Pattern — указателя на массив пишешь **Pattern — указатель на МАССИВ УКАЗАТЕЛЙ на AnsiString
Затем пробегаешься по массивчику и так же как и раньше выделяешь память под каждый из них.
CODE |
struct Parameters {
AnsiString **Pattern;
int a;
bool flag;
};
Parameters *Params = new Parameters;
Params->Pattern = new AnsiString*[ListBox1->Items->Count];
for(int i=0; i<ListBox1->Items->Count;i++)
Params.Pattern[i] = new AnsiString[N]; //можем обращатся по индексу, т. к. массив уже существует в памяти.
/*
for(int i = 0; i < ListBox1->Items->Count; i++)
{
Params->Pattern[i] = ListBox1->Items->Strings[i];
}
*/
// Удаление:
for(int i=0; i<ListBox1->Items->Count;i++)
delete[] Params->Pattern[i];
delete[] Params;
// Удалили
|
STL — стандартная библиотека шаблонов.
В ней описан класс vector — полезная штука. очень удобный в использовании контейнер (читай — динамический массив с контролем количества элементов, возможностью динамически менять его длину без всякого гемора, связанного в выделением памяти).
Поюзай — тебе понравится.
Зачаток кода с использованием vector
CODE |
include "vector.h"
//........
vector<AnsiString> MojPervijVector(0) // 0 означает, что первоначально в векторе 0 элементов.
|
Эта тема про вектор уже была. поищи по форуму. Просто впадлу один и тот же код писать.
Отредактировано exp — 04/04/2004, 00:00
|
|
Asher |
Отправлено: 31.03.2004, 08:08 |
|
Мастер участка
Группа: Модератор
Сообщений: 550
|
Привет.
Я ж говорил, не забывай делать delete.
если ты сделал
Params.Pattern = new AnsiString[ListBox1->Items->Count];
то где
delete [] Params.Pattern; ???
|
|
Snake |
Отправлено: 31.03.2004, 09:45 |
|
Ученик-кочегар
Группа: Участник
Сообщений: 22
|
QUOTE (Guest @ 30/03/2004, 18:39) | Привет. Есть ListBox с заранее неизвестным количеством элементов в нем. После заполнения юзером данного ListBox-а, нужно динамически создать структуру и заполнить её данными из ListBox-а.
|
В Builder есть встроенный класс TList, в таких случаях я им всегда пользуюсь.
CODE |
struct Parameters {
AnsiString Pattern[];
int a;
bool flag;
};
TList *Params = new TList();
for(int i = 0; i < ListBox1->Items->Count; i++)
{
Params->Add( new Parameters(ListBox1->Items->Strings[i]) );
}
|
A извлекать данные из Params следующим образом:
Parameters *p = (Parameters*) Params->Items[i];
Если функциональности TList недостаточно, можно создать свой класс списка, породив его от TList.
|
|
xTrim |
Отправлено: 31.03.2004, 11:05 |
|
Машинист паровоза
Группа: Участник
Сообщений: 208
|
CODE |
#include <vector>
using std::vector;
struct Parameters
{
vector<AnsiString> Pattern;
int a;
bool flag;
};
Parameters Params;
for(int i = 0; i < ListBox1->Items->Count; i++)
{
Params.Pattern.push_back(ListBox1->Items->Strings[i]);
}
|
|
|
olegenty |
Отправлено: 31.03.2004, 11:36 |
|
Ветеран
Группа: Модератор
Сообщений: 2412
|
если навороченая функциональность не нужна, а нужен чисто массив, рекомендую (цитата из справки Builder):
QUOTE |
Multidimensional dynamic arrays
Dynamic arrays can be multidimensional. Multidimensional dynamic arrays don't have to be rectangular. The Length property can be used to set each dimension. The following example illustrates.
typedef DynamicArray< DynamicArray < AnsiString>> T2DStringArray;
void foo(T2DStringArray &s_array)
{
SetLength(s_array, 10);
for (int i=0; i
{ // Set lengths of second dimensions.(NOTE: non-rectangular)
SetLength(s_array[i], i+1);
for (int j=0; j
/* */ s_array[i][j] = itoa(i*10+j);
}
}
|
|
|
Guest |
Отправлено: 31.03.2004, 14:06 |
|
Не зарегистрирован
|
Ребята, огромное спасибо что поделились соображениями, но реально попробовав те варианты которые вы предложили, 80% из них не рабочими оказались. Напимер код, который выложил exp не срабатывает и компилер матерится, тот же случай и с кодом, который предложил Snake, особенно мне, и компилятору тоже, непонятно выражение Params->Add( new Parameters(ListBox1->Items->Strings[i]) ); ??? Как оно относится к моей структуре?!
Плиз. Попробую поконкретнее объяснить свою задачу, может все-таки нарисуете код, который бы отработал и если можно с пояснениями...
Значит есть две формы: главная (основная форма проги) и дополнительная (форма для разных настроек). Дык вот в той форме которая отвечает за настройки, мне нужно организовать сохранение всех опций и потом записать их в реестр. Чтобы хранить опции, я и решил воспользоваться структурой. Но поскольку в опциях, среди CheckBox-ов и RadioButton-ов используется ListBox, в которм юзер может добавлять сколько угодно строк (кол-во заранее не известно) , то
структуру наверное нужно делать динамической, ну по крайней мере тот элемент структуры, в котором для ListBox-а нужно место отводить.
И еще нужно сделать так, чтобы доступ к этой структуре можно было получить как из основной формы, так и из дополнительной, а это наверное означает что в структуре нужно делать не указатель на AnsiString в который запихивать данные из ListBox-а, а именно массив AnsiString?? Ведь ListBox существует только в дополнительной форме и после выхода из нее (форма ведь уничтожается) указатель будет указывать в никуда и я в основной фроме не смогу получить доступ непосредственно к данным в структуре?? ..... Помогите разобраться...
Может кто-нибудь конкретно, на примере (рабочем) показать как это сделать??? а?? плиз....
Допустим есть:
CODE |
TMain *Main; //главная форма
TOptions *Options; //дополнительная форма
//и структура
struct Parameters {
AnsiString Pattern[]; //сюда должны запихиваться данные из ListBox-а, но не знаю что лучше использовать: указатель или массив?!
int a;
bool flag;
};
|
И как это все будет в рабочем виде? |
|
Георгий |
Отправлено: 31.03.2004, 23:13 |
|
Почетный железнодорожник
Группа: Модератор
Сообщений: 874
|
Лекарство в данном случае одно — купить книжку по BCB и по STL. Также есть подозрение что книга просто о c++ не помешает.
PS. вариант предложенный xTrim`ом полностью рабочий
PPS. указатель на форму после её закрытия не теряет своей актуальности
|
|
olegenty |
Отправлено: 01.04.2004, 08:33 |
|
Ветеран
Группа: Модератор
Сообщений: 2412
|
Тут запахло коллекцией, вынесенной в отдельный компонент. Для этого надо создать наследника от TCollectionItem, и наследника от TCollection. Получится универсальное решение, если в компонент включить коллекции элементов разных типов: и строк, и целых чисел и т.д...
|
|
Snake |
Отправлено: 01.04.2004, 10:37 |
|
Ученик-кочегар
Группа: Участник
Сообщений: 22
|
QUOTE (Guest @ 31/03/2004, 15:08) | и с кодом, который предложил Snake, особенно мне, и компилятору тоже, непонятно выражение Params->Add( new Parameters(ListBox1->Items->Strings[i]) ); ??? Как оно относится к моей структуре?!
|
Cори, лажанулся, невнимательно прочитал, что нужно.
Вот, сделал рабочий пример (в принципе, то же самое, что и в варианте xTrim)
CODE |
struct Parameters
{
public:
Parameters() { Pattern = new TStringList(); }
TStrings* Pattern;
int a;
bool flag;
};
Parameters p;
//Запись
for (int i=0; i < 10; i++ )
p.Pattern->Add( AnsiString("значение")+IntToStr(i) );
//Чтение
for ( int i=0; i < 10; i++ )
ShowMessage( p.Pattern->Strings[i] );
|
В общем случае, вместо TStrings можно использовать TList.
|
|
xTrim |
Отправлено: 01.04.2004, 10:56 |
|
Машинист паровоза
Группа: Участник
Сообщений: 208
|
CODE |
struct Parameters
{
public:
Parameters() { Pattern = new TStringList(); }
// не забыть
Parameters() { delete Pattern; }
//
TStrings* Pattern;
int a;
bool flag;
};
|
|
|
Guest |
Отправлено: 01.04.2004, 13:22 |
|
Не зарегистрирован
|
Всем еще раз спасибо за помощь. Со структурой разобрался
Возник другой вопрос. Тут Георгий говорил:
QUOTE | указатель на форму после её закрытия не теряет своей актуальности |
И действительно так. Значит для эксперемента в хэдере главной формы написал:
CODE |
struct Parameters {
AnsiString *Pattern;
}*Params;
|
В cpp главной формы:
CODE |
Params = new Parameters;
TOptions *Options = new TOptions(this);
Options->ShowModal(); //Вызвал дополнительную форму
|
В cpp дополнительной формы:
CODE |
Main->Params->Pattern = new AnsiString[ListBox1->Items->Count];
for(int i = 0; i < ListBox1->Items->Count; i++)
Main->Params->Pattern[i] = ListBox1->Items->Strings[i];
|
Теперь, по идее Params->Pattern указывает на ListBox1->Strings[]
Но даже после того как в главной форме я зачудил
CODE |
delete Options;
// то потом смог добратся до значений ListBox1
for(int i = 0; i < n; i++)
ShowMessage(Params->Pattern[i]);
|
Но каким образом? если я убил дополнительную форму со всеми её компонентами, указательParams->Pattern[] указывает на значения? откуда они берутся, если убита форма и ListBox1 в частности? куда же тогда указывает Params->Pattern[] ??
Объясните плиз этот момент...... |
|
Георгий |
Отправлено: 01.04.2004, 21:57 |
|
Почетный железнодорожник
Группа: Модератор
Сообщений: 874
|
QUOTE (Guest @ 01/04/2004, 14:24) | Но каким образом? если я убил дополнительную форму со всеми её компонентами, указательParams->Pattern[] указывает на значения? откуда они берутся, если убита форма и ListBox1 в частности? куда же тогда указывает Params->Pattern[] ??
Объясните плиз этот момент...... |
Ничего ты не убил — при закрытии форма только прячется. Отсюда и факт живости всех указателей. |
|
Guest |
Отправлено: 02.04.2004, 13:26 |
|
Не зарегистрирован
|
Хм...... всегда думал что delete высвобождает выделенную память?! Дык что это получается, что память все таки используется? Какже тогда окончательно её высвободить, если я форму создавал с помощью new ?? |
|
Asher |
Отправлено: 02.04.2004, 13:50 |
|
Мастер участка
Группа: Модератор
Сообщений: 550
|
Привет.
Не... если сделал delete Options; то форму ты конечно прибил.
Но если никто память не попортил, то так все на месте и лежит.
Ты лезешь не в свою память (хакеры или вирусы как думаешь работают ? ) и получаешь свои данные. И до поры до времени все нормально.
Если ты между delete Options; и своим циклом вставишь создание — подходящих по размеру объектов, чтобы память забили — получишь Аксесс Вуаля.
|
|
Guest |
Отправлено: 02.04.2004, 15:01 |
|
Не зарегистрирован
|
Всем огромное спасибо за лекцию. ) |
|
exp |
Отправлено: 03.04.2004, 22:59 |
|
Мастер участка
Группа: Участник
Сообщений: 304
|
Прошу прощения за серость. Код исправлен.
З.Ы. Еслы компилер выдает ошибки типа
[C++ Error] Unit1.cpp(45): E2206 Illegal character ' ' (0xa0)
То нада была подредактировать код и поудалять непечатные символы.
|
|