код программы калькулятор на c
Пишем «калькулятор» на C#. Часть I. Вычисление значения, производная, упрощение, и другие гуси
Калькулятор у нас почему-то ассоциируется с чем-то, что должен написать каждый новичок. Возможно потому, что исторически компьютеры с той целью и создавались, чтобы считать. Но мы будем писать непростой калькулятор, не sympy конечно, но чтобы умел базовые алгебраические операции, типа дифференциирования, симплификации, а также фичи типа компиляции для ускорения вычислений.
Сборка выражения
Что такое «выражение»?
Конечно, это не строка. Довольно очевидно, что математическая формула — это либо дерево, либо стек, и здесь мы остановимся на первом. То есть каждая нода, каждый узел этого дерева, это какая-то операция, переменная, либо константа.
Операция — это либо функция, либо оператор, в принципе, примерно одно и то же. Ее дети — аргументы функции (оператора).
Иерархия классов в вашем коде
Разумеется, реализация может быть любой. Однако идея в том, что если ваше дерево состоит только из узлов и листьев, то они бывают разными. Поэтому я называю эти «штуки» — сущностями. Поэтому верхним классом у нас будет абстрактный класс Entity.
А также будет четыре класса-наследника: NumberEntity, VariableEntity, OperatorEntity, FunctionEntity.
Как построить выражение?
Для начала мы будем строить выражение в коде, то есть
Если объявить пустой класс VariableEntity, то такой код выкинет вам ошибку, мол не знает как умножать и суммировать.
Переопределение операторов
Очень важная и полезная фича большинства языков, позволяя кастомизировать выполнение арифметических операций. Синтаксически реализуется по-разному в зависимости от языка. Например, реализация в C#
(Не)явное приведение типов
В компилируемых языках типа C# такая штука обычно присутствует и позволяет без дополнительного вызова myvar.ToAnotherType() привести тип, если необходимо. Так, например, было бы удобно писать
Подвешивание
Класс Entity имеет поле Children — это просто список Entity, которые являются аргументами для данной сущности.
Когда у нас вызывается функция или оператор, нам стоит создать новую сущность, и в ее дети положить то, от чего вызывается функция или оператор. К примеру, сумма по идее должна выглядить примерно так:
То есть теперь если у нас есть сущность x и сущность 3, то x+3 вернет сущность оператора суммы с двумя детьми: 3 и x. Так, мы можем строить деревья выражений.
Вызов функции более простой и не такой красивый, как с оператором:
Подвешивание в репе реализовано тут.
Отлично, мы составили дерево выражений.
Подстановка переменной
Здесь все предельно просто. У нас есть Entity — мы проверяем является ли он сам переменной, если да, возвращаем значение, иначе — бежим по детям.
В этом огромном 48-строчном файле реализована столь сложная функция.
Вычисление значения
Собственно то, ради чего все это. Здесь мы по идее должны добавить в Entity какой-то такой метод
Листик без изменений, а для всего остального у нас кастомное вычисление. Опять же, приведу лишь пример:
Если аргумент — число, то произведем численную функцию, иначе — вернем как было.
Number?
Это самая простая единица, число. Над ним можно проводить арифметические операции. По умолчанию оно комплексное. Также у него определены такие операции как Sin, Cos, и некоторые другие.
Если интересно, Number описан тут.
Производная
Численно производную посчитать может кто угодно, и такая функция пишется поистине в одну строку:
Но разумеется нам хочется аналитическую производную. Так как у нас уже есть дерево выражений, мы можем рекурсивно заменить каждый узел в соответствии с правилом дифференциирования. Работать оно должно примерно так:
Вот, к примеру, как реализованна сумма в моем коде:
А вот произведение
А вот сам по себе обход:
Это метод Entity. И как видим, что у листа всего два состояния — либо это переменная, по которой мы дифференциируем, тогда ее производная равна 1, либо это константа (число либо VariableEntity), тогда ее производная 0, либо узел, тогда идет отсылка по имени (InvokeDerive обращается к словарю функций, где и находится нужная (например сумма или синус)).
Заметьте, я здесь не оставляю что-то типа dy/dx и сразу говорю, что производная от переменной не по которой мы дифференциируем равна 0. А вот здесь сделано по-другому.
Все дифференциирование описано в одном файле, а больше и не надо.
Упрощение выражения. Паттерны
Упрощение выражения в общем случае в принципе нетривиально. Ну например, какое выражение проще: или
? Но мы придерживаемся каких-то представлений, и на основе них хотим сделать те правила, которые точно упрощают выражение.
Можно при каждом Eval писать, что если у нас сумма, а дети — произведения, то переберем четыре варианта, и если где-то что-то равно, вынесем множитель… Но так делать конечно же не хочется. Поэтому можно догадаться до системы правил и паттернов. Итак, что мы хотим? Примерно такой синтаксис:
Вот пример дерева, в котором нашлось поддерево (обведено в зеленый), отвечающее паттерну any1 + const1 * any1 (найденное any1 обведено в оранжевый).
Как видим, иногда нам важно, что одна и та же сущность должна повторяться, например чтобы сократить выражение x + a * x нам необходимо, чтобы и там и там был x, ведь x + a * y уже не сокращается. Поэтому нам нужно сделать алгоритм, который не только проверяет, что дерево соответсвует паттерну, но и
А в tree.PaternMakeMatch мы рекурсивно наполняем словарь ключами и их значениями. Вот пример списка самих паттерных Entity:
Когда мы будем писать any1 * const1 — func1 и так далее, у каждой ноды будет номер — это и есть ключ. Иначе говоря, при заполнении словаря, ключами выступят как раз эти номера: 100, 101, 200, 201, 400… А при постройке дерева мы будем смотреть на значение, соответствующее ключу, и подставлять его.
Упрощение. Сортировка дерева
Паттерны не работают?
Вообще, то, что мы сделали до этого, паттерны — чудовищно замечательная штука. Она позволит вам сокращать и разность квадратов, и сумму квадрата синуса и косинуса, и другие сложные штуки. Но элементарную пальму, ((((x + 1) + 1) + 1) + 1), она не сократит, ведь здесь главное правило — коммутативность слагаемых. Поэтому первый шаг — вычленить «линейных детей».
«Линейные дети»
Собственно для каждой ноды суммы или разности (и, кстати, произведения/деления) мы хотим получить список слагаемых (множителей).
Это в принципе несложно. Пусть функция LinearChildren(Entity node) возвращает список, тогда мы смотрим на child in node.Children: если child — это не сумма, то result.Add(child), иначе — result.AddRange(LinearChildren(child)).
Не самым красивым образом реализовано тут.
Группировка детей
Итак, у нас есть список детей, но что дальше? Допустим, у нас есть sin(x) + x + y + sin(x) + 2 * x. Очевидно, что наш алгоритм получит пять слагаемых. Далее мы хотим сгруппировать по похожести, например, x похож на 2 * x больше, чем на sin(x).
Вот хорошая группировка:
Так как в ней паттерны дальше справятся с преобразованием 2*x + x в 3*x.
То есть мы сначала группируем по некоторому хешу, а затем делаем MultiHang — преобразование n-арного суммирования в бираное.
Хеш узла
С одной стороны, и
следует поместить в одну группу. С другой стороны, при наличии
помещать в одну группу с
бессмысленно.
Поэтому мы реализовываем многоуровневую сортировку. Сначала мы делаем вид, что — одно и то же. Посортировали, успокоились. Потом делаем вид, что
можно помещать только с другими
. И вот уже наши
и
наконец объединились. Реализовано достаточно просто:
Как видим, функция по-любому влияет на сортировку (разумеется, ведь с
вообще никак в общем случае не связана). Как и переменная,
с
ну никак не получится смешать. А вот константы и операторы учитываются не на всех уровнях. В таком порядке идет сам процесс упрощения
«Компиляция» функций
В кавычках — так как не в сам IL код, а лишь в очень быстрый набор инструкций. Но зато очень просто.
Проблема Substitute
Чтобы посчитать значение функции, нам достаточно вызвать подстановку переменной и eval, например
Но это работает медленно, около 1.5 микросекунды на синус.
Инструкции
Чтобы ускорить вычисление, мы делаем вычисление функции на стеке, а именно:
1) Придумываем класс FastExpression, у которого будет список инструкций
2) При компиляции инструкции складываются в стек в обратном порядке, то есть если есть функция x * x + sin(x) + 3, то инструкции будут примерно такими:
Далее при вызове мы прогоняем эти инструкции и возвращаем Number.
Пример выполнения инструкции суммы:
Вызов синуса сократился с 1500нс до 60нс (системный Complex.Sin работает за 30нс).
В репе реализовано тут.
Фух, вроде бы пока все. Хотя рассказать еще есть о чем, но мне кажется объем для одной статьи достаточный. Интересно ли кому-нибудь продолжение? А именно: парсинг из строки, форматирование в латех, определенный интеграл, и прочие плюшки.
Ссылка на репозиторий со всем кодом, а также тестами и самплами.
Программирование на C, C# и Java
Уроки программирования, алгоритмы, статьи, исходники, примеры программ и полезные советы
ОСТОРОЖНО МОШЕННИКИ! В последнее время в социальных сетях участились случаи предложения помощи в написании программ от лиц, прикрывающихся сайтом vscode.ru. Мы никогда не пишем первыми и не размещаем никакие материалы в посторонних группах ВК. Для связи с нами используйте исключительно эти контакты: vscoderu@yandex.ru, https://vk.com/vscode
Простенький калькулятор Windows Forms на C#
Создаем исходный код программы-калькулятора в Windows Forms на языке программирования C#.
Также имеется разбор более усовершенствованного калькулятора здесь и простой консольный калькулятор вот здесь.
Для начала нам надо расположить все нужные элементы на форме. Нам понадобятся три TextBox’a и 6 кнопок-Button. Устанавливаем их вот таким образом и переименовываем кнопки в свойствах:
Наш калькулятор основан на взаимодействии двух чисел, поэтому математические операции будут следующие:
Итак, после того, как с графическим оформлением закончено, приступаем к самому коду.
Для всех вышеописанных операций мы создадим отдельные функции. Функции – это, так сказать, подпрограммы в самой программе, выполняющие отдельные задачи. Они помогают сократить и облегчить код.
Вот так у нас будет выглядеть функция сложения:
Разберем этот код по частям:
Для начала мы объявляем программе, что создаем функцию (пишем public static), затем определяем тип функции(double – числовой тип повышенной точности с плавающей запятой, лучший вариант), после даём имя функции(sum) и в скобках записываем то, что, так сказать, получает функция от программы( double a и double b – первое и второе числа, которые мы запишем в первые два TextBox’a). Выражение return возвращает в функцию результат сложения a и b. То есть наша функция получает два числа от пользователя, который введет их в форме и, при помощи return’a, в неё же заносится результат вычисления.
Точно так же создаём функции остальных математических выражений:
Функции созданы, сталось лишь привязать их к кнопкам в форме. Дважды щёлкаем мышью в форме на первую кнопку. Нас переносит в часть кода, которая отвечает за событие, которое произойдет, когда пользователь кликнет на данную кнопку. В теле этого события мы пишем:
Разбор кода начнём, как ни странно, с конца. Мы помним, что при объявлении функции мы писали вот такую часть кода: sum(double a, double b). То есть функция может получить только значения типа double. Также мы помним, что эти значения мы получаем от пользователя, который, в свою очередь, вводит их в первый и второй TextBox’ы. Однако проблема в том, что значения из TextBox’ов воспринимаются программой как строки, то есть типом string. Поэтому их надо конвертировать в нужный нам double, что мы и делаем: sum(Convert.ToDouble(textBox1.Text), Convert.ToDouble(textBox2.Text))
Значения переведены, сумма посчитана. Осталось вывести её в TextBox3. Однако, у нас опять проблемы с типами. Наша посчитанная сумма принадлежит типу double, а TextBox принимает только string. Конвертируем sum в string и записываем её в TextBox3 как строку.
То же самое проделываем с остальными кнопками и функциями:
Создание консольного приложения «Калькулятор» на C++
Обычной отправной точкой для программиста на C++ является приложение «Hello World», выполняемое в командной строке. Вот что вы создадите в Visual Studio в этой статье, и затем мы перейдем к более сложной задаче: приложению калькулятора.
Предварительные требования
Создание проекта приложения
Visual Studio использует проекты, чтобы упорядочить код для приложения, и решения, чтобы упорядочить проекты. Проект содержит все параметры, конфигурации и правила, используемые для сборки приложения. Кроме того, он управляет связью между всеми файлами проекта и любыми внешними файлами. Чтобы создать приложение, сначала создайте проект и решение.
Если вы только запустили Visual Studio, вы увидите диалоговое окно Visual Studio 2019. Выберите Создать проект, чтобы приступить к работе.
Или в строке меню Visual Studio последовательно выберите Файл > Создать > Проект. Откроется окно Создание проекта.
В списке шаблонов проектов выберите Консольное приложение и нажмите Далее.
В диалоговом окне Настроить новый проект выберите поле ввода Имя проекта, назовите новый проект CalculatorTutorial и нажмите Создать.
Будет создано пустое консольное приложение Windows на C++. Консольные приложения используют окно консоли Windows для отображения выходных данных и приема данных, вводимых пользователем. В Visual Studio откроется окно редактора с созданным кодом.
Проверка сборки и выполнения нового приложения
Шаблон для нового консольного приложения Windows создает простое приложение Hello World на C++. На этом этапе вы можете видеть, как Visual Studio создает и запускает созданные вами приложения прямо из интегрированной среды разработки.
Для сборки проекта выберите в меню Сборка пункт Собрать решение. Окно Вывод отображает результаты процесса сборки.
Чтобы запустить этот код, в строке меню выберите Отладка и Запуск без отладки.
Нажмите любую клавишу, чтобы закрыть окно консоли и вернуться в редактор Visual Studio.
Теперь у вас есть средства для сборки и запуска приложения после каждого изменения, чтобы убедиться, что код по-прежнему работает должным образом. Позже мы покажем, как выполнить его отладку при неправильной работе.
Изменение кода
Теперь давайте превратим код в этом шаблоне в приложение калькулятора.
В файле CalculatorTutorial.cpp измените код таким образом, чтобы он соответствовал этому примеру:
Чтобы сохранить файл, нажмите клавиши CTRL+S или выберите элемент Сохранить в верхней части интегрированной среды разработки, выглядящий как значок гибкого диска на панели инструментов в строке меню.
Чтобы запустить приложение, нажмите клавиши CTRL+F5 или перейдите в меню Отладка и выберите Запуск без отладки. Должно отобразится окно консоли с текстом, указанным в коде.
По завершении закройте окно консоли.
Добавление кода для выполнения математических операций
Пора добавить математическую логику.
Добавление класса Calculator
В меню Проект выберите команду Добавить класс. В поле ввода Имя класса введите Calculator. Нажмите кнопку ОК. В проект будут добавлены два новых файла. Чтобы сохранить сразу все измененные файлы, нажмите клавиши CTRL+SHIFT+S. Это сочетание клавиш для команды Файл > Сохранить все. Кроме того, есть кнопка Сохранить все на панели инструментов. Она имеет вид значка с двумя дискетами рядом с кнопкой Сохранить. В общем случае рекомендуется регулярно нажимать кнопку Сохранить все, чтобы не пропустить никакие файлы при сохранении.
Класс подобен схеме для объекта, который выполняет какие-либо действия. В этом случае мы определяем калькулятор и особенности его работы. Использованный ранее мастер Добавить класс создал файлы H и CPP, имя которых совпадает с именем класса. Вы можете просмотреть полный список файлов проекта в окне обозревателя решений, отображаемом в боковой части окна IDE. Если окно не отображается, его можно открыть из строки меню, выбрав Вид > Обозреватель решений.
Теперь у вас в редакторе должно быть открыто три вкладки: CalculatorTutorial.cpp, Calculator.h и Calculator.cpp. Если вы случайно закроете одну из них, то можете повторно открыть эту вкладку, дважды щелкнув ее в окне обозревателя решений.
На вкладке Calculator.h удалите созданные строки Calculator(); и
Под Calculate появится зеленая волнистая линия. Это вызвано тем, что мы еще не определили функцию Calculate в CPP-файле. Наведите указатель на это слово, щелкните по появившейся лампочке (в данном случае отвертке) и выберите Создать определение «Calculate» в Calculator.cpp.
Отображается всплывающее окно, сообщающее об изменении кода, внесенном в другом файле. Код был добавлен в Calculator.cpp.
Сейчас он возвращает просто 0.0. Давайте изменим это. Нажмите клавишу ESC, чтобы закрыть всплывающее окно.
Переключитесь на файл Calculator.cpp в окне редактора. Удалите разделы Calculator() и
Calculator() (как сделали в H-файле) и добавьте в Calculate() следующий код:
Если построить и запустить код еще раз на этом этапе, он по-прежнему завершит работу после запроса операции для выполнения. Далее вам нужно изменить функцию main для выполнения вычислений.
Вызов функций-членов класса Calculator
Теперь давайте изменим функцию main в CalculatorTutorial.cpp:
Повторная сборка и проверка кода
Пришло время снова протестировать программу еще раз, чтобы убедиться в ее правильной работе.
Нажмите клавиши CTRL+F5, чтобы перестроить и запустить приложение.
Введите 5 + 5 и нажмите клавишу ВВОД. Убедитесь, что выводится результат 10.
Отладка приложения
Так как пользователь может ввести в окне консоли что угодно, нужно убедиться, что калькулятор обрабатывает некоторые входные данные правильно. Вместо запуска программы давайте выполним ее отладку, чтобы можно было проверить ее выполнение шаг за шагом.
Запуск приложения в отладчике
Теперь при отладке программа всегда приостанавливает выполнение на этой строке. Мы уже имеем примерное представление о том, что в простых случаях программа работает. Так как нам не нужно приостанавливать выполнение при каждом запуске, создадим условную точку останова.
Теперь выполнение приостанавливается в точке останова, в частности при попытке деления на 0.
Полезные окна в отладчике
Каждый раз при отладке кода вы можете заметить, что появляется несколько новых окон. Они могут оказаться полезными в процессе отладки. Давайте рассмотрим окно Видимые. Окно Видимые содержит текущие значения переменных, используемых по меньшей мере за три строки перед текущей строкой. Чтобы просмотреть все переменные из этой функции, переключитесь в окно Локальные. Вы можете изменять значения этих переменных во время отладки, чтобы оценить их влияние на программу. В данном случае мы оставим их без изменений.
Кроме того, вы можете просто навести указатель на переменные в самом коде, чтобы просмотреть их текущие значения на участке, где приостановлено выполнение. Сначала щелкните окно редактора, чтобы сделать его активным.
Продолжение отладки
Причина такого результата в том, что деление на ноль является неопределенным, поэтому у программы нет числового ответа на запрошенную операцию.
Исправление ошибки деления на ноль
Давайте обеспечим корректную обработку деления на ноль, чтобы пользователь мог осознать проблему.
Внесите следующие изменения в CalculatorTutorial.cpp. (Прерывать выполнение программы при редактировании не требуется благодаря функции отладчика Изменить и продолжить):
При редактировании кода в режиме отладки существует риск того, что код устареет. Это происходит, когда отладчик продолжает выполнять старый код, не учитывающий внесенные вами изменения. В подобной ситуации отладчик выводит диалоговое окно с соответствующим сообщением. В некоторых случаях может потребоваться нажать клавишу F5, чтобы обновить выполняемый код. В частности, если вы вносите изменения внутри функции, когда точка выполнения находится внутри этой же функции, вам потребуется выполнить шаг с выходом из функции, а затем вернуться в нее, чтобы получить обновленный код. Если по какой-либо причине это не работает и вы видите сообщение об ошибке, можно остановить отладку, щелкнув красный квадрат на панели инструментов под меню в верхней части интегрированной среды разработки, а затем перезапустить отладку, нажав клавишу F5 или выбрав зеленую стрелку «воспроизведения» рядом с кнопкой остановки на панели инструментов.
Пояснения по сочетаниям клавиш для выполнения и отладки
Закрытие приложения
Добавление системы управления исходным кодом Git
Теперь, когда вы создали приложение, вы можете добавить его в репозиторий Git. Мы их предоставим. Visual Studio упрощает этот процесс с помощью инструментов Git, которые вы можете использовать непосредственно из IDE.
Git — это наиболее широко используемая современная система контроля версий, поэтому, независимо от того, являетесь ли вы профессиональным разработчиком или учитесь программировать, Git может быть для вас весьма полезным. Если вы новичок в Git, вы можете начать с сайта https://git-scm.com/. Там вы найдете памятки, популярную электронную книгу и видеоматериалы по основам GIT.
Чтобы связать свой код с Git, вы начинаете с создания нового репозитория Git, в котором находится ваш код. Вот как это сделать.
В строке состояния в правом нижнем углу Visual Studio нажмите Добавить в систему управления версиями и выберите Git.
В диалоговом окне Создать репозиторий Git войдите в GitHub.
Имя репозитория заполняется автоматически в зависимости от расположения вашей папки. По умолчанию ваш новый репозиторий является частным. Это означает, что только вы можете получить к нему доступ.
Независимо от того, является ли ваш репозиторий общедоступным или частным, лучше всего иметь удаленную резервную копию кода, надежно хранящуюся на GitHub. Даже если вы не работаете с командой, удаленный репозиторий позволит получать доступ к коду с любого компьютера.
Щелкните Создать и отправить.
После того как вы создали свой репозиторий, вы увидите информацию о статусе в строке состояния.
Первый значок со стрелками показывает, сколько исходящих и входящих фиксаций в вашей текущей ветке. Вы можете использовать этот значок, чтобы получать любые входящие или исходящие фиксации. Вы также можете выбрать отображение этих фиксаций в первую очередь. Для этого щелкните значок и выберите Просмотреть исходящие/входящие.
Второй значок с карандашом показывает количество незафиксированных изменений в вашем коде. Щелкните этот значок, чтобы просмотреть эти изменения в окне Git Changes.
Чтобы узнать больше о том, как использовать Git с вашим приложением, см. документацию по управлению версиями Visual Studio.
Готовое приложение
Поздравляем! Вы завершили написание кода для приложения калькулятора, а также выполнили его сборку и отладку и добавили его в репозиторий — и все это в Visual Studio.
Следующие шаги
Обычной отправной точкой для программиста на C++ является приложение «Hello World», выполняемое в командной строке. Вот что вы создадите в Visual Studio в этой статье, и затем мы перейдем к более сложной задаче: приложению калькулятора.
Предварительные требования
Создание проекта приложения
Visual Studio использует проекты, чтобы упорядочить код для приложения, и решения, чтобы упорядочить проекты. Проект содержит все параметры, конфигурации и правила, используемые для сборки приложения. Кроме того, он управляет связью между всеми файлами проекта и любыми внешними файлами. Чтобы создать приложение, сначала создайте проект и решение.
В строке меню Visual Studio последовательно выберите Файл > Создать > Проект. Открывается окно Новый проект.
В поле ввода Имя внизу введите имя нового проекта CalculatorTutorial, а затем нажмите кнопку ОК.
Будет создано пустое консольное приложение Windows на C++. Консольные приложения используют окно консоли Windows для отображения выходных данных и приема данных, вводимых пользователем. В Visual Studio откроется окно редактора с созданным кодом.
Проверка сборки и выполнения нового приложения
Шаблон для нового консольного приложения Windows создает простое приложение «Hello World» на C++. На этом этапе вы можете видеть, как Visual Studio создает и запускает созданные вами приложения прямо из интегрированной среды разработки.
Для сборки проекта выберите в меню Сборка пункт Собрать решение. Окно Вывод отображает результаты процесса сборки.
Чтобы запустить этот код, в строке меню выберите Отладка и Запуск без отладки.
Нажмите любую клавишу, чтобы закрыть окно консоли и вернуться в редактор Visual Studio.
Теперь у вас есть средства для сборки и запуска приложения после каждого изменения, чтобы убедиться, что код по-прежнему работает должным образом. Позже мы покажем, как выполнить его отладку при неправильной работе.
Изменение кода
Теперь давайте превратим код в этом шаблоне в приложение калькулятора.
В файле CalculatorTutorial.cpp измените код таким образом, чтобы он соответствовал этому примеру:
Чтобы сохранить файл, нажмите клавиши CTRL+S или выберите элемент Сохранить в верхней части интегрированной среды разработки, выглядящий как значок гибкого диска на панели инструментов в строке меню.
Чтобы запустить приложение, нажмите клавиши CTRL+F5 или перейдите в меню Отладка и выберите Запуск без отладки. Если отображается всплывающее окно This project is out of date (Этот проект устарел), можно выбрать Больше не показывать это диалоговое окно, а затем — Да, чтобы создать приложение. Должно отобразится окно консоли с текстом, указанным в коде.
По завершении закройте окно консоли.
Добавление кода для выполнения математических операций
Пора добавить математическую логику.
Добавление класса Calculator
В меню Проект выберите команду Добавить класс. В поле ввода Имя класса введите Calculator. Нажмите кнопку ОК. В проект будут добавлены два новых файла. Чтобы сохранить сразу все измененные файлы, нажмите клавиши CTRL+SHIFT+S. Это сочетание клавиш для команды Файл > Сохранить все. Кроме того, есть кнопка Сохранить все на панели инструментов. Она имеет вид значка с двумя дискетами рядом с кнопкой Сохранить. В общем случае рекомендуется регулярно нажимать кнопку Сохранить все, чтобы не пропустить никакие файлы при сохранении.
Класс подобен схеме для объекта, который выполняет какие-либо действия. В этом случае мы определяем калькулятор и особенности его работы. Использованный ранее мастер Добавить класс создал файлы H и CPP, имя которых совпадает с именем класса. Вы можете просмотреть полный список файлов проекта в окне обозревателя решений, отображаемом в боковой части окна IDE. Если окно не отображается, его можно открыть из строки меню, выбрав Вид > Обозреватель решений.
Теперь у вас в редакторе должно быть открыто три вкладки: CalculatorTutorial.cpp, Calculator.h и Calculator.cpp. Если вы случайно закроете одну из них, то можете повторно открыть эту вкладку, дважды щелкнув ее в окне обозревателя решений.
На вкладке Calculator.h удалите созданные строки Calculator(); и
Под Calculate появится зеленая волнистая линия. Это вызвано тем, что мы еще не определили функцию Calculate в CPP-файле. Наведите указатель на это слово, щелкните появившуюся лампочку и выберите Создать определение «Calculate» в Calculator.cpp. Отображается всплывающее окно, сообщающее об изменении кода, внесенном в другом файле. Код был добавлен в Calculator.cpp.
Сейчас он возвращает просто 0.0. Давайте изменим это. Нажмите клавишу ESC, чтобы закрыть всплывающее окно.
Переключитесь на файл Calculator.cpp в окне редактора. Удалите разделы Calculator() и
Calculator() (как сделали в H-файле) и добавьте в Calculate() следующий код:
Если построить и запустить код еще раз на этом этапе, он по-прежнему завершит работу после запроса операции для выполнения. Далее вам нужно изменить функцию main для выполнения вычислений.
Вызов функций-членов класса Calculator
Теперь давайте изменим функцию main в CalculatorTutorial.cpp:
Повторная сборка и проверка кода
Пришло время снова протестировать программу еще раз, чтобы убедиться в ее правильной работе.
Нажмите клавиши CTRL+F5, чтобы перестроить и запустить приложение.
Введите 5 + 5 и нажмите клавишу ВВОД. Убедитесь, что выводится результат 10.
Отладка приложения
Так как пользователь может ввести в окне консоли что угодно, нужно убедиться, что калькулятор обрабатывает некоторые входные данные правильно. Вместо запуска программы давайте выполним ее отладку, чтобы можно было проверить ее выполнение шаг за шагом.
Запуск приложения в отладчике
Теперь при отладке программа всегда приостанавливает выполнение на этой строке. Мы уже имеем примерное представление о том, что в простых случаях программа работает. Так как нам не нужно приостанавливать выполнение при каждом запуске, создадим условную точку останова.
Теперь выполнение приостанавливается в точке останова, в частности при попытке деления на 0.
Полезные окна в отладчике
Каждый раз при отладке кода вы можете заметить, что появляется несколько новых окон. Они могут оказаться полезными в процессе отладки. Давайте рассмотрим окно Видимые. Окно Видимые содержит текущие значения переменных, используемых по меньшей мере за три строки перед текущей строкой.
Чтобы просмотреть все переменные из этой функции, переключитесь в окно Локальные. Вы можете изменять значения этих переменных во время отладки, чтобы оценить их влияние на программу. В данном случае мы оставим их без изменений.
Кроме того, вы можете просто навести указатель на переменные в самом коде, чтобы просмотреть их текущие значения на участке, где приостановлено выполнение. Сначала щелкните окно редактора, чтобы сделать его активным.
Продолжение отладки
Причина такого результата в том, что деление на ноль является неопределенным, поэтому у программы нет числового ответа на запрошенную операцию.
Исправление ошибки деления на ноль
Давайте обеспечим корректную обработку деления на ноль, чтобы пользователь мог осознать проблему.
Внесите следующие изменения в CalculatorTutorial.cpp. (Прерывать выполнение программы при редактировании не требуется благодаря функции отладчика Изменить и продолжить):
При редактировании кода в режиме отладки существует риск того, что код устареет. Это происходит, когда отладчик продолжает выполнять старый код, не учитывающий внесенные вами изменения. В подобной ситуации отладчик выводит диалоговое окно с соответствующим сообщением. В некоторых случаях может потребоваться нажать клавишу F5, чтобы обновить выполняемый код. В частности, если вы вносите изменения внутри функции, когда точка выполнения находится внутри этой же функции, вам потребуется выполнить шаг с выходом из функции, а затем вернуться в нее, чтобы получить обновленный код. Если по какой-либо причине это не работает и вы видите сообщение об ошибке, можно остановить отладку, щелкнув красный квадрат на панели инструментов под меню в верхней части интегрированной среды разработки, а затем перезапустить отладку, нажав клавишу F5 или выбрав зеленую стрелку «воспроизведения» рядом с кнопкой остановки на панели инструментов.
Пояснения по сочетаниям клавиш для выполнения и отладки
Закрытие приложения
Поздравляем! Вы завершили написание кода для приложения калькулятора, а также выполнили его сборку и отладку в Visual Studio.