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

Ваш аккаунт

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

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

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

Передача константы как агрумента

19K
26 сентября 2006 года
Mihalina
6 / / 14.09.2006
Есть набор констант, определенных в отдельном h-файле.
static const CONST_NAME = 1;
В другом модуле подключаю этот h-файл, и в функцию необходимо передать константу
private void Function(int)
....
Function(CONST_NAME);

так как имя константы получаю в процессе работы приложения в виде строки, то получаю вызов
Function("CONST_NAME");
Подскажите плиз, а то что-то туплю:rolleyes: , как получить из AnsiString имя константы?
315
26 сентября 2006 года
Nick_M
399 / / 29.05.2003
Не-е-е, так: Function("CONST_NAME"); не прокатит. Получается что передаешь в функцию не int, а AnsiString.
19K
26 сентября 2006 года
Mihalina
6 / / 14.09.2006
в это собственно и проблема!
т.е. к какому типу мне привести AnsiString или как еще мне передать константу, если имя передаваемой константы может быть известно только в контексте работы приложения (и возвращается как AnsiString)
395
26 сентября 2006 года
RelB
367 / / 09.11.2002
std::map<AnsiString, int>
13K
26 сентября 2006 года
poland
34 / / 16.01.2006
[QUOTE=Mihalina]так как имя константы получаю в процессе работы приложения в виде строки[/QUOTE]
И как тебе это удается? Покажи код.
3.0K
26 сентября 2006 года
Мerlin
267 / / 25.07.2006
Лучше всего сделать так, как советовал RelB. Но если не знаешь STL, то можно и с помощью TStringList.

Сперва заполнить его
Код:
const int CONST_NAME1 = 1;
  const int CONST_NAME2 = 2;
  const int CONST_NAME3 = 3;

  TStringList *st;
  st = new TStringList();
  AnsiString Item = Format("CONST_NAME1=%d", ARRAYOFCONST((CONST_NAME1)));
  st->Add(Item);
  Item = Format("CONST_NAME2=%d", ARRAYOFCONST((CONST_NAME2)));
  st->Add(Item);
  Item = Format("CONST_NAME3=%d", ARRAYOFCONST((CONST_NAME3)));
  st->Add(Item);
  st->Sorted = true;
А при вызве ф-ии
 
Код:
int value = StrToInt(st->Values["CONST_NAME"]);
  Function(value);
19K
26 сентября 2006 года
Mihalina
6 / / 14.09.2006
Получение значений этих констант неплохой вариант, а нету ничего попроще?
А если вдруг констант будет около 100 или больше?
3.0K
26 сентября 2006 года
Мerlin
267 / / 25.07.2006
как-то нужно поставить в соответствие имя константы и его значение. Наверно проще всего определить структуру:
Код:
const int CONST_NAME1 = 1;
const int CONST_NAME2 = 2;
const int CONST_NAME3 = 3;

struct CONSTS
{
  char name[28];
  int value;
};

CONSTS consts[] =
{
  "CONST_NAME1", CONST_NAME1,
  "CONST_NAME2", CONST_NAME2,
  "CONST_NAME3", CONST_NAME3
};
И если элементы массива идут в альфавитном порядке, то конкретную запись можно найти бинарным поиском.
309
27 сентября 2006 года
el scorpio
1.1K / / 19.09.2006
[QUOTE=Мerlin]struct CONSTS
{
char name[28];
int value;
};
[/QUOTE]
Лучше будет использовать
 
Код:
struct Const_Int
{
    AnsiString Name;
    int Value;
};

Во-первых, если будет много функций, использующих AnsiString, то многократные приведения char* к AnsiString замедлят программу.
Во-вторых, если имя константы будет короче 27 символов - то будет напрасное использование оставшейся памяти. А если длиннее - то.....
3.0K
27 сентября 2006 года
Мerlin
267 / / 25.07.2006
[QUOTE=el scorpio]Лучше будет использовать
 
Код:
struct Const_Int
{
    AnsiString Name;
    int Value;
};

Во-первых, если будет много функций, использующих AnsiString, то многократные приведения char* к AnsiString замедлят программу.
Во-вторых, если имя константы будет короче 27 символов - то будет напрасное использование оставшейся памяти. А если длиннее - то.....[/QUOTE]Разница между программой с char name[], и Ansistring name - один оператор c_str(). Это врятли может замедлить программу. Особенно, что не исключено, что этот оператор выполняется во время компиляции.
Длину строки нужно выбрать таким, чтоб вместил строку с макс. длиной, и чтоб длина структуры была степенью двойки. Незаполненные пару байт - это не статья расхода.
И каким образом инициализируется матрица при AnsiString Name?. Если для этого нужно писать код, тогда этот вариант явно проигрывает по всем трем параметрам. Быстродействие, память и удобство использования. Ведь при типе char[], если появится новая константа напр. CONST23=23, то, чтоб это обработать нужно только поместить соответствующую строку в список инициализации массива consts.
309
27 сентября 2006 года
el scorpio
1.1K / / 19.09.2006
[QUOTE=Мerlin]Разница между программой с char name[], и Ansistring name - один оператор c_str(). Это врятли может замедлить программу. Особенно, что не исключено, что этот оператор выполняется во время компиляции.
[/quote]
Приведение AnsiString к char* приводится просто. А вот если функция требует AnsiString, а ей суют char* - всё будет медленнее и дороже :(
И вообще, использовать char* нежелательно - просто потому что никто сейчас не знает всех "подводных камней" этого типа данных :(

Цитата:
И каким образом инициализируется матрица при AnsiString Name?. Если для этого нужно писать код, тогда этот вариант явно проигрывает по всем трем параметрам. Быстродействие, память и удобство использования. Ведь при типе char[], если появится новая константа напр. CONST23=23, то, чтоб это обработать нужно только поместить соответствующую строку в список инициализации массива consts.


Точно также, как и в вашем решении. Пишем "имя константы", и компилятор для инициализации поля автоматически вызовет конструктор AnsiString (const char*). Кстати, коды деструктора, оператора "=", и конструкторов (дефолтного и копирования) компилируются автоматически, даже если разработчик класса/структуры их не объявлял.

Тем более, что список констант будет инициализироваться один раз - при запуске программы. Зато затраты на запуск окупятся сторицей во время выполнения программы.

3.0K
27 сентября 2006 года
Мerlin
267 / / 25.07.2006
[QUOTE=el scorpio]Приведение AnsiString к char* приводится просто. А вот если функция требует AnsiString, а ей суют char* - всё будет медленнее и дороже :(
И вообще, использовать char* нежелательно - просто потому что никто сейчас не знает всех "подводных камней" этого типа данных :(
[/QUOTE]Мда, на форуме появился второй Green. Тихий ужас. :) В данном конкретном случае, нет "А вот если функция требует AnsiString,...", так как нет такой ф-ии. Должна быть написанна ОДНА ф-ия бинарного поиска, которая получая имя константы, возвращает его значение.

Программисты напр. Visual Basic не упадут от смеха, когда узнают, что якобы никто из C++ программистов грамотно работать с архи сложным типом char* не умеет? Поэтому им, от греха подальше, советуют вообще не использовать этот тип? :)
Цитата:
Точно также, как и в вашем решении. Пишем "имя константы", и компилятор для инициализации поля автоматически вызовет конструктор AnsiString (const char*). Кстати, коды деструктора, оператора "=", и конструкторов (дефолтного и копирования) компилируются автоматически, даже если разработчик класса/структуры их не объявлял.

Тем более, что список констант будет инициализироваться один раз - при запуске программы. Зато затраты на запуск окупятся сторицей во время выполнения программы.

Я спрашывал, каким образом инициализируется массив? В случае с char[], достаточно

 
Код:
CONSTS consts[] =
{
  "CONST_NAME1", CONST_NAME1,
  "CONST_NAME2", CONST_NAME2,
  "CONST_NAME3", CONST_NAME3
};
Но в случае с AnsiString, не нужно писать отдельный код для каждой констаны?
309
27 сентября 2006 года
el scorpio
1.1K / / 19.09.2006
[QUOTE=Мerlin]В данном конкретном случае, нет "А вот если функция требует AnsiString,...", так как нет такой ф-ии. Должна быть написанна ОДНА ф-ия бинарного поиска, которая получая имя константы, возвращает его значение.
[/quote]
А что мешает использовать одну функцию, которая использует AnsiString? Или обязательно нужно char*

Цитата:
Программисты напр. Visual Basic не упадут от смеха, когда узнают, что якобы никто из C++ программистов грамотно работать с архи сложным типом char* не умеет? Поэтому им, от греха подальше, советуют вообще не использовать этот тип? :)


А падать от удивления, при виде "алгоритмов" работы с char* не приходилось? Если бы все программисты на C++ умели грамотно использовать char[], мир бы никогда не узнал, что такое "переполнение буфера" :) .
Если вы зубры кодинга старой закалки, то примите мои поздравления :) . Если вы считаете себя таковыми - флаг в руки и Access Violation навстречу ;)

Цитата:
Я спрашывал, каким образом инициализируется массив? В случае с char[], достаточно
 
Код:
CONSTS consts[] =
{
  "CONST_NAME1", CONST_NAME1,
  "CONST_NAME2", CONST_NAME2,
  "CONST_NAME3", CONST_NAME3
};

Но в случае с AnsiString, не нужно писать отдельный код для каждой констаны?


Повторяю - точно также.
Во избежание двусмысленности, можно вручную реализовать алгоритм инициализации объекта

 
Код:
struct TConsts
{[INDENT]AnsiString Name;
int Value;

inline TConsts (const char *iName, int iValue): Name (iName), Value (iValue)
     {} // Вызов конструктора с параметрами[/INDENT]};

Вот и вся разница. А код конструктора при создании объекта, выполняется даже если программист не писал его текст.
240
27 сентября 2006 года
aks
2.5K / / 14.07.2006
el scorpio.
А почему такое странно предложение использовать именно AnsiString вместо char *. зачем вобще исспользовать без необходимости нестандартные типы. Понятно если проект полностью построен с исспользованием борландовских библиотек - это еще оправданно. Но если же пишется универсальный код, никак не привязанный к билдеру? а какой код пишется здесь - ни слова не сказанно.
Понятно, что char * - это C-way =))) Но все же если вам нужем строковый класс, что вполне логично в c++, есть же вполне стандартный std::string.

Ато странный аргумент, если в функциях часто исспользуется AnsiString.
А если std::string, если CString или CAtlString, если QString и т.д. =))
3
27 сентября 2006 года
Green
4.8K / / 20.01.2000
[QUOTE=Mihalina]в это собственно и проблема!
т.е. к какому типу мне привести AnsiString или как еще мне передать константу, если имя передаваемой константы может быть известно только в контексте работы приложения (и возвращается как AnsiString)[/QUOTE]
Как уже говорили,нужен ассоциативный массив.
Если таких констант много и время поиска ассоциации критично, можно использовать уже предлженный std::map и std::hash_map.
Если констант немного, то можно использовать способ, предложенный Мerlin, но с рядом замечаний:
1) массив следует поместить в спец. функцию, возращающую значение константы по её имени, переданному, как строка;
2) сам массив надо объявить статическим и константным;
3) вместо char name[28], следует использовать const char*;
4) необходимо предусмотреть вариант, когда ассоциации не существует

Т. о. код будет примерно следующим:
Код:
int getConstantByName(const char* name)
{
    struct Token  {
        const char* name;
        int value;
    };

    static const Token consts[] = {
        {"CONST_NAME1", CONST_NAME1},
        {"CONST_NAME2", CONST_NAME2},
        {"CONST_NAME3", CONST_NAME3}
    };

    for(int i=0; i < sizeof(consts)/sizeof(consts[0]); i++) {
        if( !strcmp(name, consts.name) )
            return consts.value;
    }

    return -1;    // случай когда имя не найдено
}


для упрощения перечисления ассоциаций можно ввести вспомогательный макрос:
 
Код:
#define TOKEN(name) { #name, name }

    static const Token consts[] =
    {
        TOKEN(CONST_NAME1),
        TOKEN(CONST_NAME2),
        TOKEN(CONST_NAME3)
    };
3
27 сентября 2006 года
Green
4.8K / / 20.01.2000
Что касается char*, то сложность лишь в том, то строковые литералы и символьные массивы неявно приводятся к этому типу.
Правило простое: не допускать такого приведения НИКОГДА.
309
27 сентября 2006 года
el scorpio
1.1K / / 19.09.2006
[QUOTE=Green]
для упрощения перечисления ассоциаций можно ввести вспомогательный макрос:
[/QUOTE]
Эстетично, дёшево, надёжно и практично :)

[QUOTE=ask]зачем вобще исспользовать без необходимости нестандартные типы. Понятно если проект полностью построен с исспользованием борландовских библиотек - это еще оправданно. Но если же пишется универсальный код, никак не привязанный к билдеру? а какой код пишется здесь - ни слова не сказанно.
[/QUOTE]
А в какой ветке тема создана - тоже не сказано ;).
Если человек пишет на билдере, более чем вероятно, что используется VCL - следовательно, для работы со всеми экранными компонентами "стандартом" является AnsiString.
В конце концов, что может быть странне чем
 
Код:
char *Text = Edit1->Text;
// Куча функций по обработке строковых массивов,
// которые могут быть заменены методами AnsiString
Memo1->Strings->Add (Text);


Кстати, прошу прощения, но в приведённом в прошлом моём посте есть ошибка кода. Писал "по памяти", компилировал в уме :)
Писать правильно так - работает на все сто.
 
Код:
TMyStruct Consts[] = {
    TMyStruct ("Value1", 1),
    TMyStruct ("Value2", 2),
    TMyStruct ("Value3", 3)};

Естественно, конструктор TMyStuct (const char *iName, int iValue) должен существовать :)
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог