2008-10-28 3 views
1

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

set<int> affected_items; 
while (string code = GetKeyCodeFromSomewhere()) 
{ 
    if (code == "some constant" || code == "some other constant") { 
     affected_items.insert(some_constant_id); 
    } else if (code == "yet another constant" || code == "the constant I didn't mention yet") { 
     affected_items.insert(some_other_constant_id); 
    } // else if etc... 
} 
for (set<int>::iterator it = affected_items.begin(); it != affected_items.end(); it++) 
{ 
    switch(*it) 
    { 
     case some_constant_id: 
      RunSomeFunction(with, these, params); 
     break; 
     case some_other_constant_id: 
      RunSomeOtherFunction(with, these, other, params); 
     break; 
     // etc... 
    } 
} 

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

Это не похоже на лучший способ сделать это. Есть ли более аккуратный способ?

ответ

1

Поскольку вы, похоже, не заботитесь о фактических значениях в наборе, вы можете заменить его установочными битами в int. Вы также можете заменить линейную логику поиска времени логикой поиска времени журнала. Вот окончательный код:

// Ahead of time you build a static map from your strings to bit values. 
std::map< std::string, int > codesToValues; 
codesToValues[ "some constant" ] = 1; 
codesToValues[ "some other constant" ] = 1; 
codesToValues[ "yet another constant" ] = 2; 
codesToValues[ "the constant I didn't mention yet" ] = 2; 

// When you want to do your work 
int affected_items = 0; 
while (string code = GetKeyCodeFromSomewhere()) 
    affected_items |= codesToValues[ code ]; 

if(affected_items & 1) 
    RunSomeFunction(with, these, params); 
if(affected_items & 2) 
    RunSomeOtherFunction(with, these, other, params); 
// etc... 
1

Сво, конечно, не опрятно, но вы можете сохранить набор флагов, которые говорят, находятся ли назвать то, что конкретная функция или нет. Таким образом, вы избегаете сберечь вещи в наборе, у вас просто есть флаги.

Поскольку существует (предположительно, из-за его написания), фиксированное время компиляции различных блоков if/else, вы можете сделать это довольно легко с битетом.

2

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

if(done[code]) 
    continue; 
done[code] = true; 

Затем вы можете выполнить соответствующее действие сразу после определения кода.

Другой подход заключается в том, чтобы сохранить что-то исполняемое (объект, указатель функции, что угодно) в своего рода «список дел». Например:

while (string code = GetKeyCodeFromSomewhere()) 
{ 
    todo[code] = codefor[code]; 
} 

Инициализировать codefor, чтобы содержать соответствующий указатель на функцию или объект подклассы от общего базового класса, для каждого кодового значения. Если один и тот же код появляется более одного раза, соответствующая запись в todo будет просто перезаписана с тем же значением, которое у нее уже было. В конце, перебираем todo и запускаем всех своих членов.

+0

Мне нравится идея списка дел. – 2008-10-28 03:29:34

0

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

Смежные вопросы