Привет, я создал калькулятор с помощью MFC (C++), но у меня возникли проблемы с реализацией функции скобок

В настоящее время я реализую научный калькулятор, используя MFC и C++.

Я завершил большую часть функциональности, но все еще работаю над функцией скобок.

Процесс ввода в поле ввода совершенно беспроблемный.

Если я наберу 5+5 без скобок, я получу 10.

Однако когда я помещаю число в круглые скобки, оно рассматривается как ноль. Например, я получаю (5)+5= 5.

Я потратил много времени на размышления об этом, поиск в Google и вопрос GPT, но не могу получить ответ.

Пожалуйста, дайте мне знать, если я что-то пропустил или сделал неправильно, спасибо.

Мой код:

 void CMFCApplication20Dlg::OnBnClickedButtonLeftParen()
{
    CString temp;
    GetDlgItem(IDC_STATIC_VIEW)->GetWindowText(temp);
    temp += _T("("); // 왼쪽 괄호 추가
    SetDlgItemText(IDC_STATIC_VIEW, temp);
    m_LeftParenCount++;
} 
void CMFCApplication20Dlg::OnBnClickedButtonRightParen()
{
    CString temp;
    GetDlgItem(IDC_STATIC_VIEW)->GetWindowText(temp);
    if (m_LeftParenCount > m_RightParenCount)
    {
        temp += _T(")"); // 오른쪽 괄호 추가
        SetDlgItemText(IDC_STATIC_VIEW, temp);
        m_RightParenCount++;
    }
    else
    {
        AfxMessageBox(_T("Cannot add right parenthesis. Mismatched parentheses."));
    }
} 
 void CMFCApplication20Dlg::OnBnClickedButtonEquals()
{
    CString temp;
    GetDlgItem(IDC_STATIC_VIEW)->GetWindowText(temp);
    m_LeftParenCount = 0;
    m_RightParenCount = 0;
    AfterData = _ttof(temp); // 지수값(추가함)

    // CString을 double로 변환 (소수점 지원)
    double result = 0.0;
    double beforeData = _ttof(ViewStrData); // ViewStrData를 CString에서 double로 변환
    double afterData = _ttof(temp); // temp를 CString에서 double로 변환

    // % 코드임 
    int percentPos = temp.Find(_T("%"));
    if (percentPos != -1)
    {
        // `%` 기호가 있을 경우, 해당 기호를 기준으로 문자열 분리
        CString numberStr = temp.Left(percentPos); // '%' 기호 이전 부분
        double number = _ttof(numberStr); // 문자열을 double로 변환
        double result = number / 100.0;

        // 결과를 문자열로 변환하고 IDC_STATIC_VIEW에 표시
        CString resultStr;
        resultStr.Format(_T("%.2f"), result);
        SetDlgItemText(IDC_STATIC_RESULT, resultStr);
        ChangeCheck = true;
        Sign = 0;
        return;
    }

    // 계산 로직
    switch (Sign)
    {
        case 1: result = beforeData + afterData; break;
        case 2: result = beforeData - afterData; break;
        case 3: result = beforeData * afterData; break;
        case 4: 
            if (afterData != 0.0)
                result = beforeData / afterData;
            else
            {
                AfxMessageBox(_T("Zero division error!"));
                return;
            }
            break;
        case 5: 
            if (afterData != 0.0)
                result = fmod(beforeData, afterData);
            else
                AfxMessageBox(_T("Zero division error!"));
            break;
        // 추가적인 연산자 처리...
        default: AfxMessageBox(_T("Invalid operation!")); return;
    } 

    // 결과를 결과 창에 표시
    UpdateResultView(result);
    GetDlgItem(IDC_STATIC_VIEW)->SetWindowText(_T(""));
    ChangeCheck = true;
    Sign = 0;
} 

Мой совет: сначала напишите отдельную библиотеку C++, в которой вы сможете использовать std::string и т. д. для реализации бизнес-логики вашего калькулятора. Затем напишите модульные тесты для отладки синтаксического анализа вашего (5)+5 кода и отладьте его! Добавление пользовательского интерфейса MFC или его отсутствие — это то, что всегда следует делать в последнюю очередь. И мне любопытно, почему CMFC вообще для пользовательского интерфейса? (Это древнее)

Pepijn Kramer 12.08.2024 10:09

Несколько общих советов: (1) Отделите бизнес-логику от графического пользовательского интерфейса, (2) графический интерфейс гораздо проще писать на C#, а интерфейс с движком C++ осуществляется через C++/CLI.

wohlstad 12.08.2024 10:13

Спасибо за совет. Мои клиенты используют MFC, поэтому и мне следует тоже.

Sanghyeon Woo 12.08.2024 10:14

Если строки содержат (5), функция _ttof (или atof) не обработает это. Вместо этого вы получите 0.0 в качестве результата.

BoP 12.08.2024 10:17
youtu.be/unh6aK8WMwM?si=mP2vIo52pNdgLYvC обратите внимание, что в видео он не использует какой-либо набор инструментов графического интерфейса, графический интерфейс — это просто косметические элементы, которые вы добавляете вокруг кода, когда он отлично выполняет свою работу.
Ahmed AEK 12.08.2024 10:21

Кроме того, все эти _T и _t были добавлены, чтобы вы могли скомпилировать одну и ту же базу кода как с Windows 95, так и с Windows NT. Если это не ваша цель, вы можете просто использовать char или wchar_t и пропустить все трюки с макросами.

BoP 12.08.2024 10:25

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

Alessandro Teruzzi 12.08.2024 11:23

Вероятно, вы захотите использовать алгоритм сортировочной станции.

Eljay 12.08.2024 13:21
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
4
8
86
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Основная проблема заключается в этой строке кода:

AfterData = _ttof(temp);

Макрос, похожий на функцию _ttof, расширяется до atof или _wtof (в зависимости от символов препроцессора _MBCS и _UNICODE). Любая функция документирована для выполнения следующей операции:

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

При передаче "5" в качестве входных данных функции точно преобразуют его в значение 5.0. Однако с "(5)" дела обстоят иначе. Хотя люди могут легко увидеть, что круглые скобки избыточны и не влияют на значение, функции преобразования не пытаются (математически) интерпретировать входные данные. Они просто продолжают читать первый символ ('(') и выдают ошибку, поскольку это недопустимый символ в литерале с плавающей запятой.

Вместо этого вам придется написать токенизатор и анализатор, способный интерпретировать математические выражения в (предположительно) инфиксной записи. Алгоритм сортировочной станции — широко известное решение проблемы синтаксического анализа. Как отметил в комментариях , на YouTube есть видео, в котором достаточно подробно объясняется алгоритм: Язык программирования своими руками №1: Алгоритм сортировочной станции.

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

Другие вопросы по теме