оператор сравнения - PullRequest
       7

оператор сравнения

3 голосов
/ 21 октября 2010

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

<code>
vector < int > salary;
Input:
salary[i] != /* ==,>,<,>=,<= (any comparison operator)) */ 9000.

Входные данные приведены выше.Я храню оператор сравнения в строке str.str = (любой оператор сравнения).Есть ли способ проверить как это без if и switch.

<code>
salary str 9000

Ответы [ 8 ]

15 голосов
/ 21 октября 2010

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


Создание карты:

std::map<std::string, boost::function<bool(int, int)> > ops;
ops["=="] = std::equal_to<int>();
ops["!="] = std::not_equal_to<int>();
ops[">"]  = std::greater<int>();
ops["<"]  = std::less<int>();
ops[">="] = std::greater_equal<int>();
ops["<="] = std::less_equal<int>(); 

Используя его:

bool resultOfComparison = ops[str](salary[i], 9000);

(см. эту ссылку для полного рабочего примера.)


EDIT:

Как сказал @sbi в комментариях ниже, доступ к карте с помощью map[key] создаст запись, если ключ не существует. Поэтому используйте it = map.find(key) вместо этого. Если результат равен map.end(), ключ не найден, в противном случае значение равно it->second. Примите это к сведению, адаптируя это решение к вашим потребностям.

1 голос
/ 21 октября 2010

Тем не менее, у вас может быть std::map с отображением между содержимым ваших строк и указателями на ваших операторов.

0 голосов
/ 21 октября 2010

В этой конкретной ситуации ветвь if-else является вашим самым простым решением.Это просто потому, что существует слишком много альтернатив для сравнения, и вы можете быть уверены, что больше никогда не будет.По сути, ваш код должен соответствовать строчкам

if( in == "==" )
    cond = salary[i] == 9000;
else if( in == "!=" )
    cond = salary[i] != 9000;
// ...
else
  // throw, return -1, raise a flag or burst out in laughter

Это на самом деле безопаснее, чем динамическое eval(), потому что здесь вы дезинфицируете ввод.Вы убедитесь, что там нет вредоносного кода, по типу атаки Little Bobby Tables.

Конечно, вы могли бы использовать здесь полиморфизм, но смысл полиморфизма - поддержка open-альтернативы законченного типа.Когда вы хотите добавить случай, полиморфизм позволяет вам сделать это с легкостью.Но вам нужно проделать определенную работу, чтобы поднять основы, и здесь есть ровно 6 вариантов сравнения.Или 7, если вы хотите добавить поддержку произвольного предиката.

0 голосов
/ 21 октября 2010

Тебе придется взломать этот обязательный eval! ;) то есть

template <typename T>
bool eval_op(const string& op, const T& lhs, const T& rhs)
{
  switch(op.size())
  {
    case 2:
    {
      switch(op[1])
      {
        case '=':
        {
          switch(op[0])
          {
            case '=': return lhs == rhs;
            case '!': return lhs != rhs;
            case '>': return lhs >= rhs;
            case '<': return lhs <= rhs;
          }
        }
        default: throw("crazy fool!");
      };
    }
    case 1:
    {
      switch(op[0])
      {
        case '>': return lhs > rhs;
        case '<': return lhs < rhs;
        default: throw ("crazy fool!");
      }
    }
    default: throw ("crazy fool!");
  }

  return false;
}

ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: Я не проверял это ... но это идея ...

0 голосов
/ 21 октября 2010

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

Так что-то вроде:

: Input Compcmp = Comp (str);

if (cpm (зарплата [i], 9000)) {cout << "wow";} </p>

0 голосов
/ 21 октября 2010

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

0 голосов
/ 21 октября 2010

На вашем языке программирования должно быть что-то вроде EVAL, которое оценивает ваши строки.

РЕДАКТИРОВАТЬ: C ++ не имеет EVAL для поддержки вашего дела.

0 голосов
/ 21 октября 2010

Нет.Невозможно.Если вы не проанализируете данный вход и не вызовете соответствующую операцию.В любом случае вам понадобится оператор if - else.

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