На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: Qraizer, Hsilgos
  
> Обработка некорректного ввода , Обработка некорректного ввода выражения
    Здравствуйте, подскажите, написал программу для высчитывания логических выражений в консоли, но не могу реализовать проверку ввода, такие как два логических символа подряд или после скобки сразу логический оператор, чтоб при проверке выражения он написал что, ввели неправильно выражение... Как это реализовать, не могу придумать никак? спасибо

    ExpandedWrap disabled
      #include "stdafx.h"
      #include <iostream>
      #include <conio.h>
      using namespace std;
       
      int test(char x);
       
      bool number()
      {
      bool res = 0;
      for (;;)
      {
       
      char c = cin.get();
      test(c);
      if (c >= '0' && c <= '1')
      res = res * 10 + c - '0';
      else
      {
      cin.putback(c);
      return res;
      }
      }
      }
       
      bool expr();
       
      bool skobki()
      {
      char c = cin.get();
      test(c);
      if (c == '(')
      {
      int x = expr();
      cin.get();
      return x;
      }
      else
      {
      cin.putback(c);
      return number();
      }
      }
       
      bool otric()
      {
      int x = skobki();
      for (;;)
      {
      char c = cin.get();
      test(c);
      switch (c)
      {
      case '!':
      x = !skobki();
      break;
       
      default:
      cin.putback(c);
      return x;
      }
       
      }
       
      }
       
       
      bool vtor()
      {
      int x = otric();
      for (;;)
      {
      char c = cin.get();
      test(c);
      switch (c)
      {
      case '&':
      x = x & skobki();
      break;
       
      default:
      cin.putback(c);
      return x;
      }
      }
      }
       
      bool expr()
      {
      int x = vtor();
      for (;;)
      {
      char c = cin.get();
      test(c);
      switch (c)
      {
      case '^':
      x = x ^ vtor();
      break;
      case '|':
      x = x | vtor();
      break;
      default:
      cin.putback(c);
      return x;
      }
      }
      }
       
      int test(char x) {
      if (x == '1' || x == '0' || x == '(' || x == ')' || x == '&' || x == '^' || x == '|' || x == '!' || x=='2' || x == '\n') {
      return 0;
      }
      else {
      cout << endl << "Некорректный ввод!" << endl;
      system("pause");
      exit(1);
      }
      }
       
      int main()
      {
      setlocale(LC_ALL, "rus");
      char select;
      do {
      cout << "=========================================\n";
      cout << " 1 - Ввести выражение";
      cout << " 2 - Выход из программы.\n";
      cout << "=========================================\n";
       
      cin.clear();
      select = cin.get();
      cin.get();
      switch (select)
      {
      case '1':
      {
      cout << " Введите выражение:" << endl;
      int res = expr();
      cout << "Результат: " << res << endl;
      cout << "Нажмите любую клавишу, чтобы вернуться к меню . . .\n";
      cout << endl;
      system("pause");
      cin.get();
      }
       
      break;
       
      case '2': return 0; break; // exit
      default: cout << "Введены неверные данные!\n"; break;
      }
      } while (select != '2');
      return 0;
       
      }
        Это я читал, я не знаю как в мой код реализовать проверку на ввод, у меня все таки сделано не обратной польской записью
          Цитата ArtemJkee @
          Это я читал, я не знаю как в мой код реализовать проверку на ввод,

          Попробуй сделать автомат состояний.
          На каждом этапе ввода очередного символа
          всегда можно определить, какая совокупность символов
          является допустимой.
          Надо рассмотреть, сколько таких состояний получится.
          Для каждого состояния определить совокупность допустимых
          символов и условия перехода в другие состояния.
            Цитата ArtemJkee @
            я не знаю как в мой код реализовать проверку на ввод, у меня все таки сделано не обратной польской записью

            Проверку ввода можно делать прямо "по ходу" алгоритма. Со скобками - проверять стек (более подробно есть в любом описании алгоритма). Все стальные можно проверить простыми условиями.
            Цитата ЫукпШ @
            Попробуй сделать автомат состояний.

            Конечный автомат не распознает КС-грамматики.
            Сообщение отредактировано: shm -
              Цитата shm @
              Все стальные можно проверить простыми условиями.
              Цитата ЫукпШ @
              Попробуй сделать автомат состояний.

              Конечный автомат не распознает КС-грамматики.

              "Простыми" это какими ?
              ..Можно ли при вводе числа с плавающей точкой ввести точку ? или знак ?
              Это зависит от того, была ли уже введена точка. Или знак. итп итд.
              Значит, автомат.
              В более сложных случаях - совокупность автоматов.
              Сообщение отредактировано: ЫукпШ -
                Цитата ЫукпШ @
                "Простыми" это какими ?

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

                Добавлено
                Цитата ArtemJkee @
                у меня все таки сделано не обратной польской записью

                У тебя есть конкретные требования к алгоритму? Чтобы вычислять скобочные выражения тебе в любом случае нужен стек.
                  Я как то от балды недавно делал что то подобное от скуки, но с польской нотацией. Может пригодится.
                  Вот что получилось:
                  Скрытый текст

                  Operator.h
                  ExpandedWrap disabled
                    //! Operator.h
                     
                    #pragma once
                    #include <memory>
                    namespace core
                    {
                        enum EPriority
                        {
                            E_LOW,
                            E_MIDLE,
                            E_HIGH
                        };
                     
                        class COperator
                        {
                        public:
                            virtual int Calculate(int op1, int op2) = 0;
                            virtual EPriority GetPriority() const = 0;
                            virtual char Name() const = 0;
                            virtual int CountArguments() const = 0;
                            virtual ~COperator() {}
                        };
                        typedef std::shared_ptr<COperator> TOperator;
                     
                        class CPlus : public COperator
                        {
                        public:
                            int Calculate(int op1, int op2) override
                            {
                                return op1 + op2;
                            }
                     
                            EPriority GetPriority() const override
                            {
                                return core::E_MIDLE;
                            }
                     
                            virtual char Name() const override { return '+'; }
                     
                            int CountArguments() const override { return 2; }
                        };
                     
                        class CMinus : public COperator
                        {
                        public:
                            int Calculate(int op1, int op2) override
                            {
                                return op1 - op2;
                            }
                     
                            EPriority GetPriority() const override
                            {
                                return core::E_MIDLE;
                            }
                     
                            virtual char Name() const override { return '-'; }
                     
                            int CountArguments() const override { return 2; }
                        };
                     
                        class CMultiple : public COperator
                        {
                        public:
                            int Calculate(int op1, int op2) override
                            {
                                return op1 * op2;
                            }
                     
                            EPriority GetPriority() const override
                            {
                                return core::E_HIGH;
                            }
                     
                            virtual char Name() const override { return '*'; }
                     
                            int CountArguments() const override { return 2; }
                        };
                     
                        class CDivide : public COperator
                        {
                        public:
                            int Calculate(int op1, int op2) override
                            {
                                return op1 / op2;
                            }
                     
                            EPriority GetPriority() const override
                            {
                                return core::E_HIGH;
                            }
                     
                            virtual char Name() const override { return '/'; }
                     
                            int CountArguments() const override { return 2; }
                        };
                     
                        class CBra : public COperator
                        {
                        public:
                            int Calculate(int op1, int op2) override
                            {
                                return 0;
                            }
                     
                            EPriority GetPriority() const override
                            {
                                return core::E_LOW;
                            }
                            virtual char Name() const override { return Bra; }
                     
                            int CountArguments() const override { return 0; }
                        public:
                            static const char Bra;
                        };
                        const char CBra::Bra = '(';
                     
                        class CSket : public COperator
                        {
                        public:
                            int Calculate(int op1, int op2) override
                            {
                                return 0;
                            }
                     
                            EPriority GetPriority() const override
                            {
                                return core::E_LOW;
                            }
                     
                            virtual char Name() const override { return Sket; }
                     
                            int CountArguments() const override { return 0; }
                        public:
                            static const char Sket;
                        };
                        const char CSket::Sket = ')';
                     
                        struct Token
                        {
                            enum EOPType { E_UNDEF, E_OPERAND, E_OPERATOR } Type;
                            COperator * m_operator;
                            int m_operand;
                     
                            Token()
                                : Type(Token::E_UNDEF),
                                m_operator(NULL),
                                m_operand(0)
                            {
                            }
                     
                            Token(EOPType type, COperator * op, int operand)
                                : Type(type),
                                m_operator(op),
                                m_operand(operand)
                            {
                            }
                     
                            Token& operator=(const Token& r)
                            {
                                Type = r.Type;
                                m_operator = r.m_operator;
                                m_operand = r.m_operand;
                                return *this;
                            }
                        };
                    }


                  main.cpp
                  ExpandedWrap disabled
                    //! main.cpp
                     
                    #include <iostream>
                    #include <string.h>
                    #include <vector>
                    #include <stack>
                    #include <map>
                    #include <string>
                    #include <algorithm>
                    #include "Operator.h"
                    //! (5 * ((13 + 7) * (5-2))) / 10 = 30
                    using namespace core;
                     
                    class ExpressionParser
                    {
                    private:
                     
                        std::stack<Token> m_operators;
                        std::vector<Token> m_output;
                        std::stack<int> m_result;
                        std::map<char, TOperator> m_operatorMaps;
                     
                    public:
                        ExpressionParser()
                        {
                            m_operatorMaps['+'].reset(new CPlus);
                            m_operatorMaps['-'].reset(new CMinus);
                            m_operatorMaps['*'].reset(new CMultiple);
                            m_operatorMaps['/'].reset(new CDivide);
                            m_operatorMaps['('].reset(new CBra);
                            m_operatorMaps[')'].reset(new CSket);
                        }
                        void ClearStack()
                        {
                            for (;m_operators.size() > 0; m_operators.pop())
                                ;
                     
                            m_output.clear();
                     
                            for (;m_result.size() > 0; m_result.pop())
                                ;
                     
                        }
                        void PrintOutput()
                        {
                            for (auto it = m_output.begin(); it != m_output.end(); ++it)
                            {
                                if (it->Type == Token::E_OPERAND)
                                    std::cout << it->m_operand << " ";
                                if (it->Type == Token::E_OPERATOR)
                                    std::cout << it->m_operator->Name() << " ";
                            }
                        }
                     
                        int CalculateExpression()
                        {
                            for (auto it = m_output.begin(); it != m_output.end(); ++it)
                            {
                                if (it->Type == Token::E_OPERAND)
                                {
                                    m_result.push(it->m_operand);
                                }
                                if (it->Type == Token::E_OPERATOR && it->m_operator != nullptr)
                                {
                                    int op1 = m_result.top(); m_result.pop();
                                    int op2 = m_result.top(); m_result.pop();
                                    m_result.push(it->m_operator->Calculate(op2, op1));
                                }
                            }
                            return m_result.top();
                        }
                     
                        void ParseExpression(const std::string& expression)
                        {
                            for (std::string::const_iterator it = expression.begin(); it != expression.end(); ++it)
                            {
                                std::string data;
                                for (; it != expression.end() && isdigit(*it); ++it)
                                {
                                    data.push_back(*it);
                                }
                                if (!data.empty())
                                {
                                    Token tok;
                                    tok.Type = Token::E_OPERAND;
                                    m_output.push_back(Token(Token::E_OPERAND, nullptr, atoi(data.c_str())));
                                    --it;
                                }
                                else if (it != expression.end() && m_operatorMaps.find(*it) != m_operatorMaps.end())
                                {
                                    if (*it == core::CSket::Sket)
                                    {
                                        bool isFoundBra = false;
                                        for (; m_operators.size() > 0;)
                                        {
                                            if (m_operators.top().m_operator->Name() == core::CBra::Bra)
                                            {
                                                isFoundBra = true;
                                                m_operators.pop();
                                                break;
                                            }
                                            m_output.push_back(m_operators.top());
                                            m_operators.pop();
                                        }
                                        if (!isFoundBra)
                                            std::cout << "Error: expression is invalid. Symbol ( not found" << std::endl;
                     
                                    }
                                    else if (m_operators.size() > 0 &&
                                             m_operators.top().Type == Token::E_OPERATOR &&
                                             m_operators.top().m_operator != NULL &&  
                                             *it != core::CBra::Bra &&
                                             m_operators.top().m_operator->GetPriority() >= m_operatorMaps[*it]->GetPriority())
                                    {
                                        if (m_operators.top().m_operator->Name() != core::CBra::Bra)
                                        {
                                            m_output.push_back(m_operators.top());
                                            m_operators.pop();
                                        }
                                        m_operators.push(Token(Token::E_OPERATOR, m_operatorMaps[*it].get(), 0));
                                        
                                    }
                                    else
                                        m_operators.push(Token(Token::E_OPERATOR, m_operatorMaps[*it].get(), 0));
                                }
                            }
                            for (; m_operators.size() > 0;)
                            {
                                m_output.push_back(m_operators.top());
                                m_operators.pop();
                            }
                        }
                    };
                     
                    int main()
                    {
                        ExpressionParser parser;
                        std::string line;
                        while (!std::cin.eof()) {
                            std::getline(std::cin, line);
                     
                            if (line.length() > 0) {
                                try {
                                    parser.ClearStack();
                                    parser.ParseExpression(line);
                                    parser.PrintOutput();
                                    std::cout << std::endl << "Result: " << parser.CalculateExpression() << std::endl;
                     
                                }
                                catch (std::exception &e) {
                                    std::cout << "error: " << e.what() << std::endl;
                                }
                            }
                        }
                     
                        COperator* op1 = new CPlus();
                        COperator* op2 = new CMinus();
                        op1 = op2;
                     
                        std::cout << op1->Calculate(10, 5);
                        
                        
                        std::cin.get();
                        return 0;
                    }
                    Цитата shm @
                    Да, конечный автомат тут можно использовать, но только для разбиения строки на токены, если это кажется более удобным.

                    В этом мире всё является автоматами и их совокупностью.
                    И в потустороннем мире - тоже (если он существует).
                    Даже Всевышний может связно излагать свои мысли, а значит, он тоже автомат состояний.
                    Мыслительный аппарат человека - это работа совокупности автоматов.
                    Ты же не сомневаешься, что можешь решить эту проблему самомтоятельно?
                    ---
                    Любая программа это тоже совокупность автоматов.
                    Описанных либо прямым образом, либо косвенно.
                    "Косвенно" - это когда автомат реализован самой последовательностью
                    операций, флажками, ключами итд итп встречающимися по ходу алгоритма.

                    В случае примитивного алгоритма нет необходимости описывать автомат
                    прямым образом, а в сложном это самый надёжный путь к успеху.
                    Особенно с единственной точкой входа в процедуру, которая
                    должна менять алгоритм в соответствии с условиями..
                    Это по-определению - автомат.
                    Сообщение отредактировано: ЫукпШ -
                      КС-грамматика разбирается конечным автоматом с памятью стекового типа.
                        Цитата KILLER @

                        спасибо, но у тебя через объекты сделано, мне нужно без них

                        Добавлено
                        Цитата ЫукпШ @

                        а можно пример хотя бы для 1 комбинации?
                        0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                        0 пользователей:


                        Рейтинг@Mail.ru
                        [ Script execution time: 0,0464 ]   [ 17 queries used ]   [ Generated: 23.04.24, 14:26 GMT ]