Разделение входной строки для калькулятора - PullRequest
5 голосов
/ 09 января 2012

Я пытаюсь разделить данные, введенные пользователем для моего калькулятора.Например, если пользователь вводит «23 + 45 * (1 + 1)», я хочу, чтобы это было разбито на [23, +, 45, *, (, 1, +, 1,)].

Ответы [ 3 ]

7 голосов
/ 09 января 2012

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

К счастью, ваш лексер довольно прост и может быть написан вручную.Для более сложных лексеров вы можете использовать flex (как в «Быстром лексическом анализаторе» - не Adobe Flex) или (поскольку вы используете Java) ANTLR (обратите внимание, что ANTLR - это гораздо больше, чем просто лексер).

Просто придумайте список регулярных выражений, по одному для каждого токена, который нужно сопоставить (обратите внимание, что поскольку ваш ввод очень прост, вы, вероятно, можете покончить сэтот список и объединить их все в одно регулярное выражение. Однако для более продвинутых лексеров это помогает сделать одно регулярное выражение для каждого токена), например

\d+
\+
-
*
/
\(
\)

Затем запустите цикл: пока есть еще символыпроанализировал, просмотрите каждое из ваших регулярных выражений и попытайтесь сопоставить их с началом строки.Если они совпадают, добавьте первую найденную группу в список ввода.В противном случае продолжайте сопоставление (если ни одно из них не соответствует, сообщите пользователю, что у него есть синтаксическая ошибка).

Псевдокод:

List<String>input = new LinkedList<String>();
while(userInputString.length()>0){
    for (final Pattern p : myRegexes){
        final Matcher m = p.matcher(userInputString);
        if(m.find()) {
            input.add(m.group());
            //Remove the token we found from the user's input string so that we
            //can match the rest of the string against our regular expressions.
            userInputString=userInputString.substring(m.group().length());
            break;
        }
    }
}

Замечания по реализации:

  • Возможно, вы захотите добавить символ ^ ко всем своим регулярным выражениям.Это гарантирует, что вы привязываете свои совпадения к началу строки.Мой псевдокод предполагает, что вы сделали это.
1 голос
/ 28 ноября 2012

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

Operand1 op Operand2

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

0 голосов
/ 09 января 2012

Это может быть немного неаккуратно, потому что я все еще учусь, но он разбивает их на строки.

открытый класс TestClass {

public static void main(String[] args)
{
    Scanner sc = new Scanner(System.in);
    ArrayList<String> separatedInput = new ArrayList<String>();
    String input = "";

    System.out.print("Values: ");
    input = sc.next();

    if (input.length() != 0)
    {
        boolean numberValue = true;
        String numbers = "";

        for (int i = 0; i < input.length(); i++)
        {
            char ch = input.charAt(i);
            String value = input.substring(i, i+1);

            if (Character.isDigit(ch))
            { numberValue = true; numbers = numbers + value; }

            if (!numberValue)
            { separatedInput.add(numbers); separatedInput.add(value); numbers = ""; }
            numberValue = false;

            if (i == input.length() - 1)
            {
                if (Character.isDigit(ch))
                { separatedInput.add(numbers); }
            }
        }

    }
    System.out.println(separatedInput);
 }

}

...