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

Это фактически дополняет ответ, данный @Boann. У этого есть небольшая ошибка, которая вызывает «-2 ^ 2», чтобы дать ошибочный результат -4.0. Проблема для этого - точка, в которой в его оценке оценивается степень возведения в степень. Просто переместите экспоненцию в блок parseTerm (), и все будет хорошо. Посмотрите ниже, что @ Ответ Боанна слегка изменен. Модификация содержится в комментариях.

public static double eval(final String str) {
    return new Object() {
        int pos = -1, ch;

        void nextChar() {
            ch = (++pos < str.length()) ? str.charAt(pos) : -1;
        }

        boolean eat(int charToEat) {
            while (ch == ' ') nextChar();
            if (ch == charToEat) {
                nextChar();
                return true;
            }
            return false;
        }

        double parse() {
            nextChar();
            double x = parseExpression();
            if (pos < str.length()) throw new RuntimeException("Unexpected: " + (char)ch);
            return x;
        }

        // Grammar:
        // expression = term | expression `+` term | expression `-` term
        // term = factor | term `*` factor | term `/` factor
        // factor = `+` factor | `-` factor | `(` expression `)`
        //        | number | functionName factor | factor `^` factor

        double parseExpression() {
            double x = parseTerm();
            for (;;) {
                if      (eat('+')) x += parseTerm(); // addition
                else if (eat('-')) x -= parseTerm(); // subtraction
                else return x;
            }
        }

        double parseTerm() {
            double x = parseFactor();
            for (;;) {
                if      (eat('*')) x *= parseFactor(); // multiplication
                else if (eat('/')) x /= parseFactor(); // division
                else if (eat('^')) x = Math.pow(x, parseFactor()); //exponentiation -> Moved in to here. So the problem is fixed
                else return x;
            }
        }

        double parseFactor() {
            if (eat('+')) return parseFactor(); // unary plus
            if (eat('-')) return -parseFactor(); // unary minus

            double x;
            int startPos = this.pos;
            if (eat('(')) { // parentheses
                x = parseExpression();
                eat(')');
            } else if ((ch >= '0' && ch <= '9') || ch == '.') { // numbers
                while ((ch >= '0' && ch <= '9') || ch == '.') nextChar();
                x = Double.parseDouble(str.substring(startPos, this.pos));
            } else if (ch >= 'a' && ch <= 'z') { // functions
                while (ch >= 'a' && ch <= 'z') nextChar();
                String func = str.substring(startPos, this.pos);
                x = parseFactor();
                if (func.equals("sqrt")) x = Math.sqrt(x);
                else if (func.equals("sin")) x = Math.sin(Math.toRadians(x));
                else if (func.equals("cos")) x = Math.cos(Math.toRadians(x));
                else if (func.equals("tan")) x = Math.tan(Math.toRadians(x));
                else throw new RuntimeException("Unknown function: " + func);
            } else {
                throw new RuntimeException("Unexpected: " + (char)ch);
            }

            //if (eat('^')) x = Math.pow(x, parseFactor()); // exponentiation -> This is causing a bit of problem

            return x;
        }
    }.parse();
}

35
задан Guge 14 December 2008 в 01:54
поделиться

8 ответов

Статический класс со статическими элементами данных? Но кто заботится. Статические элементы данных являются просто глобальными переменными с большим количеством политкорректной упаковки.

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

Принятие Вы используете C/C++, я рекомендовал бы не иметь глобальные переменные, которые являются экземплярами класса, которые выделяют память от "кучи". Они сделают его тяжелее для Вас для использования инструментов та проверка на утечки памяти. Объявите глобальное как указатель, новый это в начале основного (), удалите его в конце.

РЕДАКТИРОВАНИЕ ПОСЛЕ 6 КОММЕНТАРИЕВ: Думайте о входе. Разве Вы не хотели бы записать строку в свой журнал откуда-либо в Вашем приложении? Как конкретно Вы выполняете это, там не будучи чем-то глобально видимым, чтобы сделать тот вход? Если Вы хотите что-то глобально видимое, то идете вперед и делаете его глобально видимым.

34
ответ дан Corey Trager 27 August 2019 в 15:52
поделиться

Ответ зависит от языка. Я недавно встретил парня, компания которого разрабатывает стек USB, который работает на многих популярных сотовых телефонах (например, таким образом, Ваш телефон может говорить с Вашим компьютером). У них есть правило в их магазине, что все процедуры C должны быть повторно используемы. На практике то, что это означает, - то, что вместо глобальных переменных, они используют дополнительный параметр для каждой стандартной программы; параметр указывает на состояние, которое должно сохраниться между стандартными программами.

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

typedef struct Pnmrdr_T *Pnmrdr_T;

struct Pnmrdr_T *Pnmrdr_new(FILE *);
pixel Pnmrdr_get(Pnmrdr_T);
void Pnmrdr_close(Pnmrdr_T);
void Pnmrdr_free(Pnmrdr_T *rp); // frees memory and sets *rp = NULL

Этот стиль программирования очень похож на методы OO.

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

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

14
ответ дан Norman Ramsey 27 August 2019 в 15:52
поделиться

Это полностью зависит от проблемы, которую Вы пытаетесь решить. Этот ключевой бит информации был не учтен Вами. При поиске всеобъемлющего решения нет того. Существуют просто шаблоны, которые мы применяем, когда применимо.

2
ответ дан TheSoftwareJedi 27 August 2019 в 15:52
поделиться

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

И альтернатива, конечно, к не имеют глобальные данные. Вместо Вашего класса, получающего доступ к некоторой статической (глобальной) переменной где-нибудь, передайте данные его конструктору. Да, это означает, что необходимо добавить несколько аргументов конструктору, но это - плохая вещь? Это делает зависимости для класса явными. Я могу протестировать класс просто путем обеспечения различных объектов ему в конструкторе, тогда как, если это полагается на глобальные данные, те globals должны существовать в моем тесте, который грязен.

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

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

8
ответ дан jalf 27 August 2019 в 15:52
поделиться

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

3
ответ дан Naveen 27 August 2019 в 15:52
поделиться

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

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

Это решение отчасти сосет, потому что Вы не можете предотвратить людей от instanciating Ваш класс (не одиночный элемент), таким образом, это должен быть внутренний класс.

я не заботился бы слишком много о весь религиозные войны о шаблоне "одиночка", хотя - Если я думаю, что он удовлетворяет моим потребностям, я обычно использую его.

0
ответ дан JohnIdol 27 August 2019 в 15:52
поделиться

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

0
ответ дан EddieD 27 August 2019 в 15:52
поделиться

Наиболее распространенное беспокойство, которое я видел и с globals и с одиночными элементами, - то, что Вы рискуете плохим поведением при использовании потоков. В этом случае необходимо всегда использовать объем выполнения в качестве основной единицы. Это - одни из преимуществ программирования OO - можно использовать элементы объекта для содержания всех соответствующих данных с очень небольшим количеством страха перед случайным погромом потока. Это стоит в отличие от non-OO-capable языка программирования, куда необходимо было бы передать данные через параметры.

другое общее беспокойство имеет тенденцию быть организационным - трудно понять точно, куда данные прибывают из в большой системе, когда это может читаться/писаться в в любое время. Это - по моему опыту, больше проблема с разработчиком, а не кодом по сути. Если Вы не работаете над одной из тех ста миллионов мегасистем строки, которые, кажется, неожиданно возникают главным образом в программировании книг как примеры трудных проблем, Вы собираетесь быть способными искать Вашу всю кодовую базу конкретный объект за довольно короткий период времени. Необходимый следующий шаг должен регулярно контролировать кодовую базу, чтобы гарантировать, что globals/static переменным не присваивают наугад. Это - анафема на большое количество подходов к разработке, но для систем под определенным размером и сложностью это - совершенно осуществимое решение.

1
ответ дан Mike Burton 27 August 2019 в 15:52
поделиться
Другие вопросы по тегам:

Похожие вопросы: