C++ Builder
| Главная | Уроки | Статьи | FAQ | Форум | Downloads | Литература | Ссылки | RXLib | Диски |

 
Как возвратить из функции TStringList
MixTr
Отправлено: 25.11.2005, 20:34


Не зарегистрирован







Есть такая функция:
CODE

String OpenData::OData(String FName, int Number)
{
 ifstream file1;
 char FN[100];
 char str[80];
 file1.open(strcpy(FN,FName.c_str()));
 if (!file1) {return ("Error open file");}
 TStringList *MyList = new TStringList;
 int i=0;
 while (!file1.eof())
 {
 file1.getline(str,sizeof(str));
 MyList->Add(str);
 i++;
 }
 return MyList->Strings[Number];
}


Как можно возвратить весь список а не одну строчку:
return MyList->Strings[Number];

Пользуйтесь тэгами [CODE]!

Отредактировано Gedeon — 25/11/2005, 21:13
Admin
Отправлено: 25.11.2005, 21:12


Владимир

Группа: Администратор
Сообщений: 1190



Наверное правильно будет создать
TStringList *MyList = new TStringList;
не в этой функции, а в вызывающей эту функцию программе,
а в функцию передавать указатель на этот TStringList

CODE

TStringList *MyList = new TStringList;
try{

OData( MyList );

// ... выполняем некие действия с этими строчками

}__finally{
delete MyList; // освобождаем память
}


и соответственно OData() будет выглядеть примерно так

CODE

void OpenData::OData(TStringList *MyList)
{
ifstream file1;
char FN[100];
char str[80];
file1.open(strcpy(FN,FName.c_str()));
if (!file1) {return ("Error open file");}

int i=0;
while (!file1.eof())
{
file1.getline(str,sizeof(str));
MyList->Add(str);
i++;
}

}



Только может еще можно упрастить весь этот код ?
Например

CODE

TStringList *MyList = new TStringList;
MyList->LoadFromFile( FName );
// ... Выполняем какие-то действия со строчками
delete MyList; // освобождаем память



Отредактировано Admin — 25/11/2005, 21:13
Gedeon
Отправлено: 25.11.2005, 21:16


Ветеран

Группа: Модератор
Сообщений: 1742



А что мешает возвратить
CODE

MyList->Text;

?
Admin
Отправлено: 25.11.2005, 21:28


Владимир

Группа: Администратор
Сообщений: 1190



Все равно как-то не очень правильно — память
под StringList выделяет в функции, а освобождает
где и в какой момент ? Может в приведенном коде
ошибок это и не вызовет, но уже на грани ...
Gedeon
Отправлено: 25.11.2005, 21:45


Ветеран

Группа: Модератор
Сообщений: 1742



Да, код веселый smile.gif .
Память естественно надо освобождать, да и вообще назначение функции не понятно, создал где нужно StringList, загрузил из файла его же методом и работай.
а вот это что такое?
file1.open(strcpy(FN,FName.c_str()));
а это
file1.getline(str,sizeof(str));

и еще
if (!file1) {return ("Error open file");}
удобнее некуда обрабатывать текст, а не код ошибки

нахрена там i?

я только к коду присмотрелся, весело biggrin.gif
Grigoriy
Отправлено: 25.11.2005, 23:39


Мастер участка

Группа: Участник
Сообщений: 381



QUOTE (MixTr @ 25/11/2005, 20:34)

Как можно возвратить весь список а не одну строчку:
return MyList->Strings[Number];

CODE

TStringList* OpenData::OData(String FName, int Number)
{
ifstream file1;
char FN[100];
char str[80];
file1.open(strcpy(FN,FName.c_str()));
if (!file1) {return ("Error open file");}
TStringList *MyList = new TStringList;
while (!file1.eof())
{
file1.getline(str,sizeof(str));
MyList->Add(str);
i++;
}
return MyList;
}
Konstantine
Отправлено: 28.11.2005, 10:09


Мастер участка

Группа: Модератор
Сообщений: 545



Grigoriy, это неправильно... — обсуждалось выше — выделяется прамять в функции, а освобождается где???
Grigoriy
Отправлено: 28.11.2005, 11:13


Мастер участка

Группа: Участник
Сообщений: 381



QUOTE (Konstantine @ 28/11/2005, 10:09)
Grigoriy, это неправильно... — обсуждалось выше — выделяется прамять в функции, а освобождается где???

А освобождается в другой функции.
То есть память выделяется в одной подпрограмме, а освобождается в той подпрограмме, которая вызвала вышеуказанную. Это так же как например, стандартная функция malloc выделяет память и возвращает указатель, но эта память освобождается другой функцией free.
** Admin
Отправлено: 28.11.2005, 21:05


Не зарегистрирован







Grigory
Это понятно, но вы можете точно сказать — в какой именно момент
будет освобождена эта память ???
Повторюсь — Может в приведенном коде ошибок это и не вызовет, но уже на грани ...

Приведу пример — а если эту функцию я вызову 10000 раз — что будет
с памятью — утечка памяти ? Каждый раз будет выделяться
новая память и не освобождаться ?

Приведу пример:

CODE

//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

TStringList* ml;

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button1Click(TObject *Sender)
{
String FName;
if(OpenDialog1->Execute()){
FName = OpenDialog1->FileName;
for(int i=0; i<10000; i++) ml = OData(FName);
}

ShowMessage(ml->Text);
}
//---------------------------------------------------------------------------

TStringList* TForm1::OData(String FName) // упростим код, оставив все — как в вашем примере — выделение памяти в функции и возврат
указателя из нее
{
TStringList *MyList = new TStringList;
MyList->LoadFromFile(FName);
return MyList;
}
void __fastcall TForm1::Button2Click(TObject *Sender)
{
ShowMessage(ml->Text);
}
//---------------------------------------------------------------------------


Попробуйте — запустите диспетчер задач, переключитесь
на вкладку — загрузка процессора и память и запустив программу
понаблюдайте за памятью ! Очень скоро ее не останется
и получите AV.

Куда проще как я писал выше.

Отредактировано Admin — 28/11/2005, 21:09
Grigoriy
Отправлено: 28.11.2005, 23:21


Мастер участка

Группа: Участник
Сообщений: 381



QUOTE
Это понятно, но вы можете точно сказать — в какой именно момент
будет освобождена эта память ???


Когда эта память будет освобождаться — Это воля MixTr. Он должен решить этот вопрос. А я не задумываюсь об этом хотя бы потому, что незнаю полного содержания проблемы, которую должна решить программа, так как в первом сообщении обсуждалась всего одна из ее подпрограмм.
Могу только предупредить, что память, выделяемая подпрограммой
String OpenData::OData(String FName, int Number)
должна обязательно освобождаться.

QUOTE

TStringList *MyList = new TStringList;
try{

OData( MyList );

// ... выполняем некие действия с этими строчками

}__finally{
delete MyList; // освобождаем память
}

Да, конечно, идея понятная, но :
1. В этом случае нужно постоянно заботится о конструировании объекта типа TStringList перед тем, как вызывать функцию OData.
2. Так можно использовать указатель MyList только в той функции, в которой он объявлен и не в какой другой без передачи указателя в качестве локального параметра.
QUOTE

Повторюсь — Может в приведенном коде ошибок это и не вызовет, но уже на грани ...


Да, согласен, при работе с указателями нужно внимательно составлять алгоритм, например, во избежание того, чтобы во время освобождать ненужные блоки памяти.

QUOTE

Приведу пример — а если эту функцию я вызову 10000 раз — что будет
с памятью — утечка памяти ? Каждый раз будет выделяться
новая память и не освобождаться ?

А зачем так нерационально расходовать память ?
CODE

for(int i=0; i<10000; i++) ml = OData(FName);

ведь в этом случае вместо одного вызова OData(FName) используется аж 10000 вызовов и при том считывается одна и та же информация !
Аналогично я бы написал
CODE

void* p;
for (int i=0;i<100000;i++){p=malloc(100000);};

и добавил, что при выполнении этого кода на персональном компьютере нехватит памяти.
Функцию void __fastcall TForm1::Button1Click(TObject *Sender)
правильно было бы оформить так
CODE

void __fastcall TForm1::Button1Click(TObject *Sender)
{
String FName;
if(OpenDialog1->Execute()){
FName = OpenDialog1->FileName;
for(int i=0; i<10000; i++) {
ml = OData(FName);
ShowMessage(ml->Text);
delete ml;};
}
}


Отредактировано Grigoriy — 29/11/2005, 09:08
Asher
Отправлено: 29.11.2005, 09:46


Мастер участка

Группа: Модератор
Сообщений: 550



Привет всем.
Возвращайте свой лист завернутым в auto_ptr.

Вернуться в Вопросы программирования в C++Builder