Подтвердить что ты не робот

C/С++ коммутатор с строкой

Возможный дубликат:
C/С++: переключатель для нецелых чисел

Привет, Мне нужно использовать строку в корпусе коммутатора. Мое решение до сих пор заключалось в том, чтобы вычислить хэш строки с моей хэш-функцией. Проблема в том, что мне приходится вручную предварительно вычислять все мои хэш-значения для строк. Есть ли лучший подход?

h=_myhash (mystring);
switch (h)
{
case 66452:
   .......
case 1342537:
   ........
}
4b9b3361

Ответ 1

Просто используйте цепочку if() { } else if () { }. Использование хеш-значения будет кошмаром для обслуживания. switch предназначен для описания низкого уровня, который не подходит для сравнения строк.

Ответ 2

Вы можете сопоставить строки с указателем функции, используя стандартную коллекцию; выполнение функции при обнаружении совпадения.

РЕДАКТИРОВАТЬ: Используя пример в статье, в которой я дал ссылку в своем комментарии, вы можете объявить тип указателя функции:

typedef void (*funcPointer)(int);

и создайте несколько функций для соответствия сигнатуре:

void String1Action(int arg);
void String2Action(int arg);

Карта будет std::string до funcPointer:

std::map<std::string, funcPointer> stringFunctionMap;

Затем добавьте строки и указатели функций:

stringFunctionMap.add("string1", &String1Action);

Я не тестировал какой-либо из кода, который я только что опубликовал, это с моей головы:)

Ответ 3

Как правило, вы должны использовать хеш-таблицу и функциональный объект, оба доступны в Boost, TR1 и С++ 0x.

void func1() {
}
std::unordered_map<std::string, std::function<void()>> hash_map;
hash_map["Value1"] = &func1;
// .... etc
hash_map[mystring]();

Это немного больше накладных расходов во время выполнения, но в bajillion раз более ремонтопригодным. Таблицы хэшей предлагают O (1) вставку, поиск и т.д., Что делает их такой же сложностью, как таблица перехода в стиле сборки.

Ответ 4

Лучший способ - использовать генерацию источника, чтобы вы могли использовать

if (hash(str) == HASH("some string") ..

в вашем основном источнике, а шаг предварительной сборки преобразует выражение HASH(const char*) в целочисленное значение.

Ответ 5

Вы можете использовать строку для индексирования в хеш-таблицу указателей функций.

Изменить: glib имеет реализацию хеш-таблицы, которая поддерживает строки как ключи и произвольные указатели как значения: http://library.gnome.org/devel/glib/stable/glib-Hash-Tables.html

Ответ 6

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

Ответ 7

Вы можете использовать перечисление и карту, поэтому ваша строка станет ключом, а значение перечисления - значением для этого ключа.

Ответ 8

Если вы выполняете работу и не хотите каждый раз выполнять все предложения if, если их много или нужно хэш-значений, вы можете отправить дополнительную информацию в функцию с помощью enum или просто добавьте тип enum в вашу структуру.

Ответ 9

Нет хорошего решения вашей проблемы, так что это решение okey, -)

Он сохраняет эффективность, когда утверждения отключены, и когда утверждения разрешены, он вызывает ошибку утверждения, если значение хэша неверно.

Я подозреваю, что язык программирования D может вычислять значение хэша во время компиляции, тем самым устраняя необходимость явно записывать хеш-значение.

template <std::size_t h>
struct prehash
{
    const your_string_type str;

    static const std::size_t hash_value = h;

    pre_hash(const your_string_type& s) : str(s)
    {
        assert(_myhash(s) == hash_value);
    }
};

/* ... */

std::size_t h = _myhash(mystring);

static prehash<66452> first_label = "label1";

switch (h) {
case first_label.hash_value:
    // ...
    ;
}

Кстати, рассмотрим удаление начального подчеркивания из объявления _ myhash() (извините, но stackoverflow заставляет меня вставлять пробел между _ и myhash). Реализация С++ позволяет реализовать макросы с именами, начинающимися с подчеркивания и заглавной буквой (пункт 36 "Исключительный стиль С++" от Herb Sutter), поэтому, если вы привыкли давать имена вещей, которые начинают подчеркивать, тогда прекрасный день может появиться, когда вы дадите символ имя, которое начинается с подчеркивания и заглавной буквы, где реализация определила макрос с тем же именем.

Ответ 10

Предложение Ruslik использовать исходное поколение мне кажется хорошим. Тем не менее, я бы не пошел с концепцией "основных" и "сгенерированных" исходных файлов. Я бы предпочел иметь один файл с кодом, почти идентичным вашему:

h=_myhash (mystring);
switch (h)
{
case 66452: // = hash("Vasia")
   .......
case 1342537: // = hash("Petya")
   ........
}

Следующее, что я сделал бы, я бы написал простой script. Perl хорош для таких вещей, но ничто не мешает вам даже писать простую программу на C/С++, если вы не хотите использовать какие-либо другие языки. Этот script или программа возьмет исходный файл, прочитает его по очереди, найдет все эти строки case NUMBERS: // = hash("SOMESTRING") (используйте здесь регулярные выражения), замените NUMBERS на фактическое значение хэша и напишите измененный источник в временный файл. Наконец, он будет поддерживать исходный файл и заменять его временным файлом. Если вы не хотите, чтобы ваш исходный файл имел новую метку времени каждый раз, программа могла проверить, действительно ли что-то было изменено, а если нет, пропустите замену файла.

Последнее, что нужно сделать, - это интегрировать этот script в используемую систему сборки, чтобы вы случайно не запустили ее, прежде чем строить проект.