Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Функция возвращающая ассоциативный массив!?

335
13 апреля 2006 года
enola
379 / / 25.01.2005
Добрый день!
Подскажите могу я такое сделать:

хидер:
 
Код:
typedef struct
    {
        char Name[256];
        char Rest[256];
        char Price[256];
    } MyStruct;

    typedef map<double, MyStruct> MyMap;
   
    MyMap* __fastcall TForm1::FileParcer();


модуль:
 
Код:
MyMap* __fastcall TForm1::FileParcer()
{
    //
}


в модуле ругается:
Цитата:

[C++ Error] Unit1.cpp(69): E2141 Declaration syntax error



В принципе функция может возвращать контейнер или нет? Если да, то что я делаю не так?

1
13 апреля 2006 года
kot_
7.3K / / 20.01.2000
Цитата:
Originally posted by enola
Добрый день!
Подскажите могу я такое сделать:

хидер:
 
Код:
typedef struct
    {
        char Name[256];
        char Rest[256];
        char Price[256];
    } MyStruct;

    typedef map<double, MyStruct> MyMap;
   
    MyMap* __fastcall TForm1::FileParcer();


модуль:
 
Код:
MyMap* __fastcall TForm1::FileParcer()
{
    //
}


в модуле ругается:


В принципе функция может возвращать контейнер или нет? Если да, то что я делаю не так?


В принципе ничто не мешает возвращать контейнер - это такой же тип данных как и все остальные.
Но обычно возращают итератор. :)
Ошибка вероятно не связана с тем что возвращает функция - скорее всего ты не учел область видимости объявления.

335
14 апреля 2006 года
enola
379 / / 25.01.2005
Цитата:
Originally posted by kot_

Ошибка вероятно не связана с тем что возвращает функция - скорее всего ты не учел область видимости объявления.


Ты был прав, с областью видимости намудрил. :)

Цитата:
В принципе ничто не мешает возвращать контейнер - это такой же тип данных как и все остальные. Но обычно возращают итератор.


Я с STL вот только начал знакомиться, поэтому не очень еще понимаю.
Как я понял итератор это тот же указатель, но тогда какой смысл возвращать итератор на контейнер, если можно вернуть сам контейнер или я что-то не так понял?

вот так правильно делать?:

Код:
typedef map<int, string> MyMap;
MyMap Map1;

void function1()
{
    MyMap::iterator pos;

    pos = function2();
   
    // Производим операции с контейнером
}

MyMap::iterator function2()
{
    MyMap::iterator pos;

    // Производим операции с контейнером
    return pos;
}
1
14 апреля 2006 года
kot_
7.3K / / 20.01.2000
Цитата:
Originally posted by enola

Я с STL вот только начал знакомиться, поэтому не очень еще понимаю.
Как я понял итератор это тот же указатель, но тогда какой смысл возвращать итератор на контейнер, если можно вернуть сам контейнер или я что-то не так понял?


Работа с контейнерами достаточно прожорлива по памяти. Поэтому возвращая контейнер(или указатель на него) ты можешь получить немаленькие утечки (и если бы только утечки :) ) за счет создания темп-объектов.

Цитата:
Originally posted by enola

вот так правильно делать?:
Код:
typedef map<int, string> MyMap;
MyMap Map1;

void function1()
{
    MyMap::iterator pos;

    pos = function2();
   
    // Производим операции с контейнером
}

MyMap::iterator function2()
{
    MyMap::iterator pos;

    // Производим операции с контейнером
    return pos;
}


Хм. Я бы предпочел так:

Код:
void function1(MyMap::iterator begin,MyMap::iterator end, const int some)
{
   
    // Производим операции с контейнером
}
//Или
void function1(MyMap::iterator pos)
{
   
    // Производим операции с элементом
}

тогда функцию используешь так:
 
Код:
MyMap List;
...
//Заполнили, инициализировали
//Здесь обрабатываем
function1(List.begin,List.end,1);
//или
...

Это не значит, что мое решение более "правильное" чем твое - все зависит от того что ты хочешь получить на выходе. Кроме того, используя контейнеры, я бы рекомендовал тебе использовать алгоритмы и шаблоны функций из STL в первую очередь. Большинство задач, таких как поиск, сортировки, максимумы, минимумы, в общей сложности ок 70 алгоритмов там решены - потрать некоторое время на ознакомление и возможно ты не создаш себе кучу проблем. :)
335
14 апреля 2006 года
enola
379 / / 25.01.2005
Задача у меня следующая:
есть файлик довольно таки большой 50000 строк (постоянно растет), его необходимо отпарсить и запихать в структуру, причем у каждой строчки есть свои идентификатор т.е. ключ, потом по этому ключу необходимо будет выполнять поиск значений.

Вот что я решил сделать:
1. Создаю структуру вида:
 
Код:
struct
    {
        char Name[256];
        char Price[256]; // Именно char
        char Rest[256];  // нужен
    } MyStruct;

2. Создаю контейнер map<string, MyStruct> (т.к. поиск по ключу самый быстрый, дубликатов нет)
3. Парсю файлик и заполняю контейнер (вот это необходимо оформить в виде функции, т.к. будет многократный вызов)

Так если сделать, чтобы функция возвращала итератор, то контейнер необходимо объявлять на уровне модуля, а не на уровне функции!

Может подскажешь как можно это лучше реализовать?
1
14 апреля 2006 года
kot_
7.3K / / 20.01.2000
Цитата:
Originally posted by enola
Задача у меня следующая:
есть файлик довольно таки большой 50000 строк (постоянно растет), его необходимо отпарсить и запихать в структуру, причем у каждой строчки есть свои идентификатор т.е. ключ, потом по этому ключу необходимо будет выполнять поиск значений.

Вот что я решил сделать:
1. Создаю структуру вида:
 
Код:
struct
    {
        char Name[256];
        char Price[256]; // Именно char
        char Rest[256];  // нужен
    } MyStruct;

2. Создаю контейнер map<string, MyStruct> (т.к. поиск по ключу самый быстрый, дубликатов нет)
3. Парсю файлик и заполняю контейнер (вот это необходимо оформить в виде функции, т.к. будет многократный вызов)

Так если сделать, чтобы функция возвращала итератор, то контейнер необходимо объявлять на уровне модуля, а не на уровне функции!

Может подскажешь как можно это лучше реализовать?


Я честно говоря не вижу особой выгоды в использовании т.н. "локального" контейнера, накладные расходы возможно будут гораздо выше - это раз.
Второе - я создал бы отдельно сингл-класс массива строк и в нем в качестве поля контейнер. Здесь бы реализовал все операции для работы со строками и функцию загрузки данных.
И отдельный класс для чтения данных, объект которого создавался бы в этой функции. Примерно вот так:

Код:
void __fastcall TListDocument::LoatFromFile(const AnsiString& f){
 TLoadDocument loaddoc;//Класс для загрузки
 TInvoiceIn document;//Класс документа
 clearAll(); //Чистим контейнер
 loaddoc.Open(f,ios::in|ios::binary);
   while(loaddoc.size){
   //Вызывается перегруженный оператор чтения из потока
  loaddoc >> document;
//Функция заполнения контейнера.
   insertDocument(document,document.GetCode());
  }
   loaddoc.close();
}
int __fastcall TListDocument::insertDocument(const TInvoiceIn& doc,int recordId)throw(DuplicateId){
 if(recordId ==0)recordId = nextId++;
 else if(recordId >= nextId)nextId = recordId +1;
 else if (documentcode.count(recordId))throw DuplicateId();
 TInvoiceIn *docum = new TInvoiceIn(doc);
 docum->SetCode(recordId);
//documentcode и documentname - два контейнера которые заполняются
// один типа multiset - в него вставляется собственно объект
//второй map - содержит идентификатор и итератор на multiset
 DocumentName::iterator i=documentname.insert(*docum);
 documentcode[recordId] =i;
 return recordId;
}

Идея с двумя контейнерами позаимствована из "STL на примерах".
335
14 апреля 2006 года
enola
379 / / 25.01.2005
Цитата:
Originally posted by kot_
Я честно говоря не вижу особой выгоды в использовании т.н. "локального" контейнера, накладные расходы возможно будут гораздо выше - это раз.
Второе - я создал бы отдельно сингл-класс массива строк и в нем в качестве поля контейнер. Здесь бы реализовал все операции для работы со строками и функцию загрузки данных.
И отдельный класс для чтения данных, объект которого создавался бы в этой функции.


идея понятна.

Цитата:

Примерно вот так:
Код:
void __fastcall TListDocument::LoatFromFile(const AnsiString& f){
 TLoadDocument loaddoc;//Класс для загрузки
 TInvoiceIn document;//Класс документа
 clearAll(); //Чистим контейнер
 loaddoc.Open(f,ios::in|ios::binary);
   while(loaddoc.size){
   //Вызывается перегруженный оператор чтения из потока
  loaddoc >> document;
//Функция заполнения контейнера.
   insertDocument(document,document.GetCode());
  }
   loaddoc.close();
}
int __fastcall TListDocument::insertDocument(const TInvoiceIn& doc,int recordId)throw(DuplicateId){
 if(recordId ==0)recordId = nextId++;
 else if(recordId >= nextId)nextId = recordId +1;
 else if (documentcode.count(recordId))throw DuplicateId();
 TInvoiceIn *docum = new TInvoiceIn(doc);
 docum->SetCode(recordId);
//documentcode и documentname - два контейнера которые заполняются
// один типа multiset - в него вставляется собственно объект
//второй map - содержит идентификатор и итератор на multiset
 DocumentName::iterator i=documentname.insert(*docum);
 documentcode[recordId] =i;
 return recordId;
}

Идея с двумя контейнерами позаимствована из "STL на примерах".


но вот реализация :(

придется похоже копаться в STL и делать по-своему.
спасибо.

585
14 апреля 2006 года
honeybeer
297 / / 06.09.2004
Дабы избежать накладных расходов на копирование при передаче по значению, я бы предложил передавать контейнер по ссылке, что то вроде этого:
 
Код:
bool Compute(MyMap& m_filestore);

возвращать итератор имхо не есть гут, ибо не дай боже содержимое контейнера изменится - получишь невалидный итератор, что чревато последствиями
335
14 апреля 2006 года
enola
379 / / 25.01.2005
Цитата:
Originally posted by honeybeer
Дабы избежать накладных расходов на копирование при передаче по значению, я бы предложил передавать контейнер по ссылке, что то вроде этого:
 
Код:
bool Compute(MyMap& m_filestore);

возвращать итератор имхо не есть гут, ибо не дай боже содержимое контейнера изменится - получишь невалидный итератор, что чревато последствиями



Мне нужно контейнер не передавать в функцию, а возвращать из функции. :)

585
14 апреля 2006 года
honeybeer
297 / / 06.09.2004
Цитата:
Originally posted by enola
Мне нужно контейнер не передавать в функцию, а возвращать из функции. :)


1) А что мешает объявить контейнер вне функции, передать по ссылке и работать дальше.

2) Можно сделать так например:

 
Код:
MyMap& Compute(std::string s_filename)
{
static MyMap m_filestorage;
...
// тута делаешь работу
...
return m_filestorage;
}

хотя по моему вариант 1 - предпочтительней
335
14 апреля 2006 года
enola
379 / / 25.01.2005
Цитата:
Originally posted by honeybeer
1) А что мешает объявить контейнер вне функции, передать по ссылке и работать дальше.

2) Можно сделать так например:
 
Код:
MyMap& Compute(std::string s_filename)
{
static MyMap m_filestorage;
...
// тута делаешь работу
...
return m_filestorage;
}

хотя по моему вариант 1 - предпочтительней



по-первому варианту сделал, все работает, спасибо!

Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог