Калькулятор, который может принимать слова в качестве входных данных - PullRequest
2 голосов
/ 19 июня 2011

Я хочу написать калькулятор, который может принимать слова в качестве входных данных. например, «два плюс пять умножить на 7» должно дать 37 как результат. Я не буду лгать, это домашнее задание, поэтому перед тем, как это сделать, я подумал, можно ли мне указать на что-то, что может пригодиться для такого рода вещей, и я не осознаю этого.

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

Спасибо.

[Редактировать] - Спасибо за ответы. Это вводный курс. Поэтому мы будем благодарны за простоту вещей. Я должен был упомянуть об этом ранее.

[Редактировать 2] - Достигнут этап, на котором я могу вводить цифры и получать правильный вывод с приоритетом и все. Просто хочу посмотреть, как теперь преобразовать слово в число. Спасибо всем, кто пытается помочь. Вот почему ТАК качается.

Ответы [ 3 ]

1 голос
/ 19 июня 2011

Это был один из моих любимых вещей в школе.

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

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

1 голос
/ 19 июня 2011

ПРИМЕЧАНИЕ. Я предполагаю, что это вводный курс, а не курс теории компиляторов. Если вас учат конкретным вещам, относящимся к этому (например, алгоритмам, отличным от того, что я упоминаю), вы почти наверняка будете ожидать применения этих понятий .

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

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

Чтобы понять, как нужно вычислить выражение, используйте алгоритм шунтирующий двор , чтобы проанализировать выражение с надлежащим приоритетом оператора. Скорее всего, вы можете объединить начальный синтаксический анализ слов с этим, просто используя его для предоставления токенов алгоритму.

Чтобы реально вычислить результат, вам нужно оценить проанализированное выражение. Для этого вы можете просто использовать стек для вывода: когда вы обычно нажимаете на оператор, вы вместо этого извлекаете 2 значения, применяете к ним оператор и отправляете результат. После завершения алгоритма маневрового двора в стеке будет одно значение, содержащее конечный результат.

1 голос
/ 19 июня 2011

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

С помощью класса std::istream и оператора извлечения (>>) вы можете легко разбить ввод на отдельные слова.

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

Основное отличие от этого в вашем случае - это разбор чисел. Вместо символов «0-9» на вашем входе будут слова «ноль», «один», «девять», «сотни», «тысячи» и т. Д. Для анализа такого потока слов вы можете сделать что-то вроде это:

  1. разбить слова на группы, вложенные «множителями», такими как «тысячи», «сотни», «миллиарды» и т. Д .; эти группы могут гнездиться. Десятки («десять», «двадцать», «тридцать»), подростки («одиннадцать», «двенадцать», «тринадцать», ...) и единицы («один», «два», «три»,. ..) ничего не вкладывать Вы превращаете что-то вроде «сто три тысячи двести девяносто семь» в нечто вроде этого:

               +--------+---------+-----+
              /         |         |      \
          thousand   hundred   ninety   seven
           /    \       |
       hundred  three  two
          |
         one
    
  2. для каждой группы, рекурсивно суммировать все ее компоненты, а затем умножить на ее «множитель»:

                       103297
               +--------+------+----+
              /         |      |     \
          (* 1000) + (* 100) + 90  +  7
           /    \       |
       (* 100) + 3      2
          |
          1
    
...