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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Обратная польская запись 
:(
    Опции темы
AHgpeu
Дата 30.6.2009, 12:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



Для тех, кто в теме.

Есть ли стандартный способ в ОПЗ для проверки на корректность исходной строки с формулой?
Т.е. чтобы исходная строка не была, например такая:
2+/5--*
--------------------
ᆉᆈǀƿᆇᆆᆅᆂᆁᆇᆆ
PM MAIL   Вверх
PashaPash
Дата 30.6.2009, 12:40 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1233
Регистрация: 3.1.2008

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



AHgpeu, да, есть - выполнить. Если после выполнения стек пуст, и не было попыток pop-а из пустого стека - то запись корректна.


--------------------
PM MAIL WWW   Вверх
luxadevianta
Дата 4.7.2009, 22:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


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

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



А кто может подсказать хороший алгоритм создания ОПЗ из обычной записи выражения?
PM   Вверх
Partizan
Дата 4.7.2009, 22:24 (ссылка) |   (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Let's do some .NET
****


Профиль
Группа: Модератор
Сообщений: 2828
Регистрация: 19.12.2005
Где: Санкт-Петербург

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



luxadevianta, в педивикии наверняка всё расписано.


--------------------
СУВ,
       Partizan.
PM MAIL WWW ICQ Skype GTalk Jabber   Вверх
diadiavova
Дата 5.7.2009, 14:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Доктор Зло(диагност, настоящий, с лицензией и полномочиями)
****


Профиль
Группа: Модератор
Сообщений: 5821
Регистрация: 14.8.2008
Где: В Коньфпольте

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



По сабжу
Я не очень понимаю, зачем это может понадобиться, на сколько я знаю, ОПЗ - это промежуточная запись и она обычно генерится машиной(если не считать языков программирования, в которых она является основной), так что проверять её незачем. Возможно поэтому найти "стандартный" алгоритм непросто. Но вопрос меня заинтересовал, и я, немного покумекав, вот какое решение нашёл:
В записи присутствуют два типа элементов - операторы и операнды. Для простоты рассмотрим классическую ОПЗ только с бинарными операторами(идею можно распространить и на расширенную форму). Будет ли запись корректной зависит исключительно от того, в какой последовательности идут разные типы элементов, например если второй элемент - оператор, то запись некорректна. 
Разбор записи осуществляется с лева на право и как только будет найден оператор вычисляется операция с ним и двумя предшествующими операндами, в результате получается элемент, который можно в дальнейшем использовать как операнд.
Для реализации алгоритма создадим скелет выражения. Скелет будет представлять из себя коллекцию List<int>, которую мы сформируем следующим образом: 
пройдёмся по исходному выражению и всякий раз, когда мы встретим операдн будем добавлять в коллекцию 0, а когда встретим оператор - 1. 
Проверить правильность последовательности теперь просто - движемся по коллекции и как только находим 1 (оператор) заменяем его и два предшествующих нуля на 0 (заменяем операцию операндом). На практике, что бы заменить последовательность 001 на 0 надо из неё убрать два последних элемента - 01. То есть обходить обходя коллекцию при обнаружении единицы удалять её и предшествующий ноль. Так до тех пор, пока в ней не останется один ноль. В этом случае запись корректна, в ином случае - нет.

Пример реализовал для записи, в которой все элементы разделены пробелами, в качестве операторов использовал  = - * / ^. Для сложных выражений не проверял, может что и накосячил, но надеюсь идея понятна
Код

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

namespace RPNSmpl
{
    class Program
    {
        static void Main(string[] args)
        {
            string[] operators = @"+ - * / ^".Split(' ');
            var sceleton = new List<int>();
            var input = "Введите выражение";
            Console.WriteLine(input);
            while (true)
            {
                input = Console.ReadLine();
                if (input == ".") return;
                string[] items = input.Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
                foreach (string it in items)
                {
                    if (operators.Contains(it)) sceleton.Add(1);
                    else sceleton.Add(0);
                }
                Console.WriteLine(IsCorrectForm(sceleton));
                sceleton.Clear();
            }
        }


        static bool IsCorrectForm(List<int> sceleton)
        {
            if (sceleton.Count == 0) return false;
            if (sceleton.Count == 1 && sceleton[0] == 0) return false;
            while (sceleton.Count > 1)
            {
                var opIndex = sceleton.IndexOf(sceleton.First(n => n > 0));
                if (opIndex < 2) return false;
                sceleton.RemoveAt(opIndex);
                sceleton.RemoveAt(opIndex - 1);
                
            }
            return true;
        }
    }
}



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



--------------------
Хочешь получить мудрый совет - читай подписи участников форумов.
Злой доктор Щасзаболит smile
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

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


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

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


 




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


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

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