Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Польская запись 
:(
    Опции темы
tatu
Дата 15.4.2010, 18:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 15
Регистрация: 13.12.2009

Репутация: нет
Всего: -1



Код

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
   class Program
    {
        static bool checkString(string str)
       {
           bool isCorrect = true;
           int s = 0;
           if ((str[0] == '(' && (str[str.Length - 1] == '('))) s++;
           if ((str[0] == ' ' && (str[str.Length - 1] == ' '))) s--;
           if ((str[0] == '+' || (str[0] == '-' || (str[0] == '*' || (str[0] == '/'))))) isCorrect = false;
           else if ((str[str.Length - 1] == '+' || (str[str.Length - 1] == '-' || (str[str.Length - 1] == '*' || (str[str.Length - 1] == '/'))))) isCorrect = false;
           else if (((!Char.IsDigit(str[0])) || (!Char.IsDigit(str[str.Length - 1]))) && ((str[0] != '(' && (str[str.Length - 1] != ' ')))) isCorrect = false;
           else for (int i = 1; i < str.Length - 2; i++)
               {
                   if ((str[i] == '+' || (str[i] == '-' || (str[i] == '*' || (str[i] == '/')))))
                   {
                       if ((str[i + 1] == '+' || (str[i + 1] == '-' || (str[i + 1] == '*' || (str[i + 1] == '/'))))) isCorrect = false;

                   }
                   else if (!Char.IsDigit(str[i]) && (str[i] != '(' && (str[i] != ' '))) isCorrect = false;
                   if (str[i] == '(') s++;
                   if (str[i] == ' ') s--;
               }
           if (s == 0) isCorrect &= true;
           else isCorrect &= false;
           return isCorrect;
       }

        static void Main(string[] args)
        {

            

            string zn = Console.ReadLine();

            int sum = 0; // тут будет формироваться результат выражения
            char arefm_znak = ' ';
            string str = ""; // строка в которой будет формироваться польская запись
            if (checkString(zn) == false)
            {
                Console.WriteLine("Неверное выражение");
            }
            else
            {

                foreach (char ch in zn)
                {
                    if (ch >= '0' && ch <= '9')
                    {
                        if (arefm_znak == ' ')
                        {
                            sum = int.Parse(ch.ToString());
                            str += sum.ToString() + ' ';
                        }
                        else
                        {
                            if (arefm_znak == '-')
                                sum -= int.Parse(ch.ToString());
                            if (arefm_znak == '+')
                                sum += int.Parse(ch.ToString());
                            if (arefm_znak == '*')
                                sum *= int.Parse(ch.ToString());
                            if (arefm_znak == '/')
                                sum /= int.Parse(ch.ToString());
                            str += ch.ToString() + ' ' + arefm_znak.ToString() + ' ';
                        }
                    }
                    else
                        if (ch == '-' || ch == '+' || ch == '*' || ch == '/')
                            arefm_znak = ch;
                }


                Console.WriteLine("{0} = {1}", str, sum);
            }
            Console.ReadKey();

        }
    }
}


ковырялся долго, разными способами пробывал....но не получается реализовать приоритет опраций, и что-то я с защитой на дурака перемудрил...выражения со скобками считает не верным....например:(2+2)/(2*3-3) считает неверным(((

помогите пожайлуста....лаба горит, охото отмазаться от си шарпа и не париться с ним. не силен в общем я в программировании(((
PM MAIL   Вверх
Skalik
Дата 16.4.2010, 10:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 131
Регистрация: 20.3.2008
Где: Харьков

Репутация: нет
Всего: нет



Пол года назад у меня тоже была такая лаба! Написал, вроде нормально работает, если еще надо, то напиши куда скинуть...
PM MAIL ICQ   Вверх
ДобренькийПапаша
Дата 16.4.2010, 17:14 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1278
Регистрация: 14.1.2006
Где: г.Москва

Репутация: 3
Всего: 7



Если вас устроит метод рекурсивного спуска для анализа выражений, то пример есть в книге "Полный справочник по C#" Герберта Шилдта (Глава 26).
Книжку можно скачать с какого-нибудь трекера.

Это сообщение отредактировал(а) ДобренькийПапаша - 16.4.2010, 17:25


--------------------
Меня зовут Себастьян Парейра, торговец чёрным деревом.
PM MAIL   Вверх
SickFxck
Дата 16.4.2010, 22:23 (ссылка)  | (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 107
Регистрация: 16.4.2010

Репутация: нет
Всего: 1



Есть мой калькулятор на C#, там проверка синтаксиса на конечных автоматах, с переводом из инфиксной нотации в постфиксную (читай: "из обычной нотации в польскую") и последующим вычислением. Можно договориться о цене, в ЛС.

Что касается твоей программы: сначала ты пытаешься (вроде как) делать проверку на корректность записи в инфиксной нотации, т.е. типа "(2+2)/(2*3-3)", далее сразу пытаешься вычислить непонятным способом эту запись. То есть нет перевода из инфиксной записи в польскую.
PM MAIL   Вверх
tatu
Дата 28.4.2010, 13:57 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 15
Регистрация: 13.12.2009

Репутация: нет
Всего: -1



Код

using System;
using System.Collections.Generic;
using System.Text;

namespace RPN
{
    class Программа
    {
        static void ОбратнаяПольскаяЗапись(string вход)
        {
            Queue<object> выход = new Queue<object>(); // Либо int'ы - числа, либо char - операторы
            Stack<char> операторы = new Stack<char>();
            // Парсим строку
            StringBuilder построительЧисел = new StringBuilder();
            for (int i = 0; i < вход.Length; i++)
            {
                // Число может закончиться только перед этими операторами
                if ((вход[i] == '+' || вход[i] == '-' || вход[i] == '/' || вход[i] == '*' ||
                     вход[i] == ')' || вход[i] == '^') && построительЧисел.Length > 0)
                {
                    выход.Enqueue(int.Parse(построительЧисел.ToString()));
                    построительЧисел.Length = 0;
                }

                if (вход[i] == ' ') // Пропускаем пробелы
                    continue;
                else if (вход[i] >= '0' && вход[i] <= '9')
                {
                    // Числа могут состоять из нескольких цифр, поэтому помещаем их в построитель чисел
                    // помещение в выход будет производиться при прочтении первого оператора, либо закрывающей скобки
                    построительЧисел.Append(вход[i]);
                }
                else if (вход[i] == '(')
                {
                    // Если символ является открывающей скобкой, помещаем его в стек.
                    операторы.Push('(');
                }
                else if (вход[i] == ')')
                {
                    // Если символ является закрывающей скобкой:
                    //  До тех пор, пока верхним элементом стека не станет открывающаяся скобка, выталкиваем элементы из стека в выходную строку. 
                    //  При этом открывающаяся скобка удаляется из стека, но в выходную строку не добавляется. 
                    //  Если стек закончился раньше, чем мы встретили открывающую скобку, это означает, что в выражении либо неверно 
                    //  поставлен разделитель, либо не согласованы скобки.
                    bool found = false;
                    while (операторы.Count > 0)
                    {
                        char op1 = операторы.Pop();
                        if (op1 == '(')
                        {
                            found = true;
                            break;
                        }
                        else
                        {
                            выход.Enqueue(op1);
                        }
                    }
                    if (!found)
                    {
                        Console.WriteLine("Неверное выражение()");
                        return;
                    }
                }
                else if ((вход[i] == '+' || вход[i] == '-' || вход[i] == '/' || вход[i] == '*' || вход[i] == '^') &&
                (вход[i + 1] != '+' && вход[i + 1] != '-' && вход[i + 1] != '/' && вход[i + 1] != '*' && вход[i + 1] != '^'))
                {
                    // Если символ является оператором, о1, тогда:
                    // 1) пока… 
                    //    … (если оператор o1 ассоциированный, либо лево-ассоциированный) приоритет o1 меньше либо равен приоритету оператора, 
                    //       находящегося на вершине стека…
                    //    … (если оператор o1 право-ассоциированый) приоритет o1 меньше приоритета оператора, находящегося на вершине стека…
                    // … выталкиваем верхние элементы стека c бо́льшим либо равным приоритетом в выходную строку;
                    while (операторы.Count > 0)
                    {
                        char topOp = операторы.Peek();
                        if (вход[i] == '^')
                        {
                            if (topOp == '^')
                                выход.Enqueue(операторы.Pop());
                            else
                                break;
                        }
                        else if (вход[i] == '*' || вход[i] == '/')
                        {
                            if (topOp == '^' || topOp == '*' || topOp == '/')
                                выход.Enqueue(операторы.Pop());
                            else
                                break;
                        }
                        else if (вход[i] == '-' || вход[i] == '+')
                        { // левоассоциативные
                            if (topOp == '^' || topOp == '*' || topOp == '/' || topOp == '+' || topOp == '-')
                                выход.Enqueue(операторы.Pop());
                            else
                                break;
                        }
                        else
                            break;
                    }

                    // 2) помещаем оператор o1 в стек.
                    операторы.Push(вход[i]);
                }
                else
                {
                    Console.WriteLine("Неверное выражение");
                    return;
                }
            }
            // В конце разбора в построителе чисел могло остаться число
            if (построительЧисел.Length > 0)
                выход.Enqueue(int.Parse(построительЧисел.ToString()));

            // Когда входная строка закончилась, вытолкнуть все символы из стека в выходную строку. 
            // В стеке должны были остаться только символы операторов; если это не так, значит в выражении не согласованы скобки.
            char op2;
            while (операторы.Count > 0)
            {
                op2 = операторы.Pop();
                if (op2 == '(' || op2 == ')')
                {
                    //Console.WriteLine("Ошибка ввода! Не согласованы скобки!");
                    return;
                }
                else
                    выход.Enqueue(op2);
            }
            // Печатаем выражение в польской нотации и вычисляем результат
            Stack<object> calculations = new Stack<object>();
            
                while (выход.Count > 0)
                {

                    object obj = выход.Dequeue();
                    if (obj is int || obj is double) // Число
                        calculations.Push(obj);
                    else
                    { // Операция
                        double left, right;
                        object oRight = calculations.Pop(); // Глупый C#, не может привести выражения вида "double x = (double)(object)1;"
                        if (oRight is int)
                            right = (double)(int)oRight;
                        else
                            right = (double)oRight;
                        object oLeft = calculations.Pop();
                        if (oLeft is int)
                            left = (double)(int)oLeft;
                        else
                            left = (double)oLeft;

                        switch ((char)obj)
                        {
                            case '+':
                                calculations.Push(left + right);
                                break;
                            case '-':
                                calculations.Push(left - right);
                                break;
                            
                            case '/':
                                try
                                {
                                calculations.Push(left / right);
                               
                                }
                                catch(DivideByZeroException)
                                {
                                   Console.WriteLine("Деление на ноль");
                                }
                                break;
                            case '*':
                                calculations.Push(left * right);
                                break;
                            case '^':
                                calculations.Push(Math.Pow(left, right));
                                break;
                        }
                    }
                    Console.Write(obj + " ");
                }
                Console.WriteLine();
                // Печатаем результат выражения
                Console.WriteLine("Результат: " + calculations.Pop());
                Console.ReadKey();

        }

        static bool checkString(string str)
        {
            bool isCorrect = true;
            int s = 0;
            //защита от неверного количества скобок
        for (int i = 0; i < str.Length; i++) 
        {
        if (str[i] == '(')
        {
        s = s + 1;
        }
         if (str[i] == ')')
        {
        s = s - 1;
        }
        }
        if (s != 0)
        {
            Console.WriteLine(" Неверное выражение");
        }
            if (s == 0) isCorrect &= true;
            else isCorrect &= false;
            return isCorrect;
        }
        static bool check (string вход)
        {
            bool isCorrect = true;
           
            if ((вход[0] == '+' || (вход[0] == '-' || (вход[0] == '*' || (вход[0] == '/'))))) isCorrect = false;
            else if ((вход[вход.Length - 1] == '+' || (вход[вход.Length - 1] == '-' || (вход[вход.Length - 1] == '*' || (вход[вход.Length - 1] == '/'))))) isCorrect = false;
            else if (((!Char.IsDigit(вход[0])) || (!Char.IsDigit(вход[вход.Length - 1]))) && ((вход[0] != '(' && (вход[вход.Length - 1] != ' ')))) isCorrect = false;
            else for (int i = 1; i < вход.Length - 2; i++)
                {
                    if ((вход[i] == '+' || (вход[i] == '-' || (вход[i] == '*' || (вход[i] == '/')))))
                    {
                        if ((вход[i + 1] == '+' || (вход[i + 1] == '-' || (вход[i + 1] == '*' || (вход[i + 1] == '/'))))) isCorrect = false;
                    }
                }
           
            return isCorrect;
        }

        static void Main(string[] args)
        {
            Console.WriteLine("Введите вычислимое выражение (пустая строка - выход):");
            string вход = Console.ReadLine();
            if ((checkString(вход) == false) || (вход.IndexOf("()")!=-1) || (check(вход) == false))
            {
                Console.WriteLine("Неверное выражение");
            }
            else
            {
                if (true)
                {
                    if (вход.Length == 0)
                        return;
                    ОбратнаяПольскаяЗапись(вход);
                    //Console.WriteLine("Введите следующее выражение (пустая строка - выход):");
                    //вход = Console.ReadLine();
                }
            }
        }
    }
}



в общем если сильно не придираться то сделал так;) надеюсь сдам

вопрос.....почему не получается с помощью try вывести ошибку при делении на 0...а то выводит бесконечность
PM MAIL   Вверх
SickFxck
Дата 28.4.2010, 14:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 107
Регистрация: 16.4.2010

Репутация: нет
Всего: 1



Цитата(tatu @  28.4.2010,  13:57 Найти цитируемый пост)
почему не получается с помощью try вывести ошибку при делении на 0...а то выводит бесконечность 

Потому что используешь double. Проверяй операнды просто, либо проверяй результат через double.IsInfinity(), double.IsNaN() (0 / 0).
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
Partizan
PashaPash

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, Partizan, PashaPash.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | .NET для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0537 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.