Помощь - Поиск - Пользователи - Календарь
Полная версия: Вычисление выражения в постфиксной форме.
Форум «Всё о Паскале» > Современный Паскаль и другие языки > Ада и другие языки
Krjuger

#include <iostream>
#include <conio.h>

struct stek
{
int d;
struct stek *next; //указатель на следующий элемент списка (стека)
};

void push(stek **netx, int d); //функция будет помещать элемент в стек
// next – указатель на вершину стека
int pop(stek **netx); //функция будет извлекать элемент их стека
//вершина которого - next

void push(stek **next, int d)
{ stek *pv = new stek; //объявляем новую динамическую переменную типа stek
pv->d=d; //записываем значение, которое помещается в стек
pv->next=*next; //связываем новый элемент стека с предыдущим
*next=pv; //новый элемент стека становится его вершиной
}

int pop(stek **next)
{ int temp=(*next)->d; //извлекаем в переменную temp значение в вершине стека
stek *pv=*next; //запоминаем указатель на вершину стека, чтобы затем
//освободить выделенную под него память
*next=(*next)->next; //вершиной становится предшествующий top элемент
delete pv; //освобождаем память, тем самым удалили вершину
return temp; //возвращаем значение, которое было в вершине
}


int main()
{
char v[25]="5 9 8 + 4 6 * * 7 + * ";
stek *next=0;
int a,b;
int i=0;
while (v[i]!='\0')
{
if (v[i] == '+') push(&next,pop(&next)+pop(&next));
if (v[i] == '*') push(&next,pop(&next)*pop(&next));
if (v[i] == '-') push(&next,-(pop(&next)-pop(&next)));
if ((v[i]>='0') && (v[i]<='9')) push(&next,0);
while ((v[i]>='0')&&(v[i]<='9')) push(&next,10*pop(&next)+(v[i++]-'0'));
i++;
}
printf("\n %i \n",pop(&next));
return 0;
}


Проблема в том,что я не знаю как реализовать операцию деления,потому что стек построен таким образом что
1 2 \ выдаст мне не 0.5,как должно а выдаст 2,потому что будет поделено не 1 на 2,а 2 на 1 изза того что двойка будет выше по стеку.С + и * не имеет значение положение,с - просто беру обратное число,а вот что с делением сделать ума не приложу.Еще мне не очень нравится,как выглядить эта прога,поэтому хотелось бы чтобы дали советы как это реализовать по другому,чтобы поэффективнее было.
volvo
У тебя стек построен таким образом, что физически не может хранить вещественые числа. Переведи его на работу с float, и будет тебе счастье...

А насчет обратного порядка - не страшно, есть операция "запятая". Кстати, если у тебя С++ (а у тебя-таки С++, потому как new и подключен iostream) - то можно избавиться от указателя на указатель, заменив его ссылкой:

#include <iostream>
#include <conio.h>

struct stek
{
int d;
struct stek *next; // указатель на следующий элемент списка (стека)
};

void push(stek* &next, int d); // функция будет помещать элемент в стек
// next – указатель на вершину стека
int pop(stek* &next); // функция будет извлекать элемент их стека
// вершина которого - next

void push(stek* &next, int d)
{
stek *pv = new stek; // объявляем новую динамическую переменную типа stek
pv->d = d; // записываем значение, которое помещается в стек
pv->next = next; // связываем новый элемент стека с предыдущим
next = pv; // новый элемент стека становится его вершиной
}

int pop(stek* &next)
{
int temp = next->d; // извлекаем в переменную temp значение в вершине стека
stek *pv = next; // запоминаем указатель на вершину стека, чтобы затем
// освободить выделенную под него память
next = next->next; // вершиной становится предшествующий top элемент
delete pv; // освобождаем память, тем самым удалили вершину
return temp; // возвращаем значение, которое было в вершине
}


int main()
{
// char v[25]="5 9 8 + 4 6 * * 7 + * ";
char v[]="1 2 -";
stek *next=0;
int a, b;
for(int i = 0; v[i] != '\0'; i++)
{
switch(v[i])
{
case '+': push(next, pop(next) + pop(next)); break;
case '-': push(next, ((a = pop(next)), (b = pop(next)), b - a)); break;
case '*': push(next, pop(next) * pop(next)); break;
case '/': push(next, ((a = pop(next)), (b = pop(next)), b / a)); break;
default:
if(isdigit(v[i])) push(next, 0);
while(isdigit(v[i]))
push(next, 10*pop(next) + (v[i++]-'0'));
}
}
printf("\n %i \n",pop(next));
return 0;
}
Krjuger
Я переделал это все в класс и теперь надо добавлять поддержку функций,это лучше делать через функцию класса или продолжить в самом конструкторе воротить?

#include <iostream>
#include <conio.h>

class PostAr
{
private:
struct stek
{
int d;
struct stek *next; // указатель на следующий элемент списка (стека)
};
public:
PostAr(char *input);
struct stek *push (struct stek* &next, int p); // функция будет помещать элемент в стек
// next – указатель на вершину стека
int pop(struct stek* &next); // функция будет извлекать элемент их стека
// вершина которого - next
};

PostAr::stek *PostAr::push(struct stek* &next, int p)
{
stek *pv = new stek; // объявляем новую динамическую переменную типа stek
pv->next = next; // связываем новый элемент стека с предыдущим
pv->d = p; // записываем значение, которое помещается в стек
return pv; // новый элемент стека становится его вершиной
}

int PostAr::pop(struct stek* &next)
{
int temp = next->d; // извлекаем в переменную temp значение в вершине стека
stek *pv = next; // запоминаем указатель на вершину стека, чтобы затем
// освободить выделенную под него память
next = next->next; // вершиной становится предшествующий top элемент
delete pv; // освобождаем память, тем самым удалили вершину
return temp; // возвращаем значение, которое было в вершине
}


PostAr::PostAr(char *input)
{
char *v;
struct stek *opers=NULL;
int a, b;
float result;
v=input;
for(int i = 0; v[i] != '\0'; i++)
{
switch(v[i])
{
case '+': opers=push(opers, pop(opers) + pop(opers)); break;
case '-': opers=push(opers, ((a = pop(opers)), (b = pop(opers)), b - a)); break;
case '*': opers=push(opers, pop(opers) * pop(opers)); break;
case '/': opers=push(opers, ((a = pop(opers)), (b = pop(opers)), b / a)); break;
default:
if(isdigit(v[i])) opers=push(opers, 0);
while(isdigit(v[i]))
opers=push(opers, 10*pop(opers) + (v[i++]-'0'));
}
}
result=opers->d;
}
void main()
{
PostAr m1("11 22 /");
}

volvo
Вообще-то СНАЧАЛА надо смотреть на задание, и решать, что и как делать, и что должно получиться в результате, и как с этим результатом потом работать. Второй этап - это словесное описание алгоритма. Выразишь словами - сможешь объяснить компьютеру. Не выразишь - даже не пытайся запускать компилятор, у тебя ничего не получится... Третий этап - написание программы. Да, да... Все еще на листе бумаги. И ее "прогон". Угу, на бумаге и "в уме". И только потом можно включать компьютер и набирать программу... Продолжай "воротить" дальше. Я предпочитаю заниматься нормальным проектированием и программированием, а не "наворачиванием" одного, потом другого, потом третьего, изначально не имея на руках ПОЛНОГО Т.З. У тебя в результате получится "спагетти", и ты в нем опять не сможешь разобраться, не говоря уже, чтоб добавить что-нибудь...

Но это уже без меня. Я в этом участия не принимаю.
Krjuger
Четкое задание есть и алгоритм его решения я прекрасно представляю.Почему я сделал сначала программу,а потом переделал в класс....Да потому что на мой взгляд так проще отлаживать и находить ошибки.Делаю я ,как ты выразился с "наварачиванием" потому что я не обладаю таким уровнем программирования,чтобы сделать все и сразу,а потом отлавливать ошибки,они у меня могут наложится одна а другую и тогда будет полный хаос в котором я вовек не разберусь,более того,как выяслилось полный свой проект скидывать мне не имеет смысла, потому что в mfc мне помоч никто не может,а занчит не имеет смысла скидывать все в одну кучу,поэтому я свою главную задачу разбил на некоторое количество независымых подзадач.Насчет моего вопроса..Задал я его потому что для дальнейшего использования это абсолютно не будет иметь никакого значения, буть это функция,она будет вызвана только внутри конструктора и больше никакой надобности в ней нет.Более того я не просил выдавать мне код,я лиш спросил, как будет правильнее сделать
Цитата
....и ты в нем опять не сможешь разобраться, не говоря уже, чтоб добавить что-нибудь...

Это вы вообще о чем?

P.s. Ненадо сравнивать себя(состоявшегося программиста) и человека, который лиш учится программироватью.Я думаю есть люди,которые другого мнения о методах проектирования и программирования и ,в отличии от меня,они смогут достаточно аргументированно высказать достоинства и недостатки вашего способа и их способа проектирования и программирования.
volvo
Цитата
P.s. Ненадо сравнивать себя(состоявшегося программиста) и человека, который лиш учится программировать
А знаешь, почему я состоялся, как программист? Потому, что когда я школу заканчивал - то раз в неделю мы ездили на "практические занятия по ВТ" (так это тогда называлось) черт знает куда - на другой конец города, только так были компьютеры, за которые нас пускали. И мы всю неделю готовились к этой поездке, и программы "вылизывали" именно в уме, потому что другого способа просто не было. А сидеть и ловить ошибки, когда тебе дают 3 часа машинного времени в неделю - это, знаешь ли, глупо.

И когда я начинал учиться в институте - к нам на кафедру ВМКСС (!!!) привезли два новеньких 80386, так завкафедрой закрыл их в сейф, чтоб не сломали чего, а мы программировали на ВЦ на Примусе (опять же, не чаще 2-3 часов в неделю). И опять приходилось отлаживать код ручками. Потому что если ты знаешь, что такое Примус - то поймешь, сколько надо ждать, чтоб твою задачу поставили в очередь, а поставят же с минимальным приоритетом, пока там до ее исполнения дойдет... И тут что? Ага. ошибка. Тебе возвращают список ошибок, ты исправляешь, опять в очередь... больше 3 раз времени не хватало никогда. Программа не отработала - значит не сдал. Считай, на экзамене проблемы гарантированы. Как тебе такая подготовочка? А вы сейчас сидите за компьютером, и прямо текст набиваете в редактор... А качество программ все ниже и ниже. Думать надо, прежде, чем программу-то набирать...

Цитата
Я думаю есть люди,которые другого мнения о методах проектирования и программирования и ,в отличии от меня,они смогут достаточно аргументированно высказать достоинства и недостатки вашего способа и их способа проектирования и программирования
Мой способ (не я его выбирал, мне его навязали, но я об этом ничуть не жалею) себя оправдал по крайней мере. Был бы постоянный доступ к компьютеру и Интернету - ничего б из меня не получилось.

Цитата
Четкое задание есть и алгоритм его решения я прекрасно представляю.
Вот это называется "представляю"???
Цитата
Проблема в том,что я не знаю как реализовать операцию деления,потому что стек построен таким образом что 1 2 \ выдаст мне не 0.5,как должно а выдаст 2
Это при работе с int-ами-то он у тебя ДОЛЖЕН выдать 0.5??? Проснись уже, что ты себе представляешь? Кто работу со стеком запихал в одну строку, а потом удивляется, почему же из стека сначала читается последнее число, и только потом - предпоследнее? Пушкин что-ли? Ты вообще про стек слышал когда-нибудь? Так вот стек В ПРИНЦИПЕ именно так и работает, и если тебе надо другое поведение - значит стек тебе просто не подходит! Знают они всё, всё прекрасно представляют, а потом НАМ приходится ошибки править и костыли всякие устанавливать, чтоб хоть как-то работало после вот таких "знаек", ибо переписывать код полностью уже времени нет... dry.gif
Krjuger
Цитата

удивляется, почему же из стека сначала читается последнее число

во первых, я не удивляюсь,если ты не заметил, то я сам объяснил проблему моих затруднейний при данной реализации.Если бы я знал, что можно создавать такие конструкции, как (((a = pop(opers)), (b = pop(opers)), b / a),у меня бы таких вопросов вообще не возникло бы.
Цитата
Был бы постоянный доступ к компьютеру и Интернету - ничего б из меня не получилось.

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

Так же наверно у нас с вами разное представление понятия "алгоритм",все, что вы мне исправили было не неправильностью алгоритма,а не совсем верным выбором пути реализации.
Цитата
А качество программ все ниже и ниже

Качество ниже,потому что щас заставляют писать программы всех подрят и зачастую людям,которые далеки от математики и не обладают соответствующим складом ума приходится этим заниматься.
Ну, а что поделаеш,раньше на асм писали, по перфакартам отлаживали,а теперь представь все это сейчас.Серьезные задачи решались бы годами.Зато был бы один плюс,в институтах было всего пара групп которые бы этим занимались,существовало бы лиш избранное количество программистов(причем много меньше чем сейчас).
По хорошему ты сам пользуешся средствами ,которые были написаны людьми,которые либо умнее тебя,либо додумались до этого и реализовали это раньше тебя(тот же билдер и дугие редакторы).А теперь представь чо ты вернешся во времена своего обучения,когда ничего этого не было,в итоге каждый раз для своих целей будет изобретать очередной велосипед,это будет занимать уйму времени,но ты будеш прекрасно знать работу самого процессора да и все функционирование системы,плюс очень хорошо будет разбираться в алгоритмах.

Короче на данном этапе развития знание семантики и синтаксиса языка очень сильно влияет на стабильность, скорость работы программы
while(isdigit(v[i]))-библиотечная функция.
while ((v[i]>='0')&&(v[i]<='9')) мой вариант.
Выполняют они абсолютно одно и тоже с точки зрения аглоритма,но 1 вариант придумал человеком,который уж явно умнее меня и наверно продумал варианты,когда мой варинат будет некорректно работать.В итоге использование библиотечной функции повышаеть стабильность программы.А в конце концов,чем все это было вызвано...тем,что я просто не знал о существовании такой функции.
Кстати о птичках,эта реализация взята из книги Страуструпа.....

Кстати я нашел реализованную на С++ постфиксную запись и вычисление,но знаеш почему я ее не использовал?Да потому что от меня не требуется хорошо копаться в интернете и предоставить отлично работающую программу написанную методами,которые мне неизвестны,а мне надо создать свой собственный еле едущий велосипед,чтобы показать, что я не простой пользователь,нажимающий на иконки,когда кто то другой все сделал за меня,а челвоек,который способен сам сделать что либо.И к вам я обращаюсь с целью либо посоветовать реализацию,либо помоч исправиль ошибку,которую я сам исправить не могу из-за отсутствия необходимых знаний.Я не разу не просил скинуть мне готовый код того чего я хочу.
Lapp
Krjuger, ты во многом по-своему прав, и хорошо, что ты идешь своим путем. Единственное "но": ты долго и старательно отвечал не на то. volvo тебе сказал, что для решения серьезной задачи правильнее будет сначала составить детальный план решения с алгоритмами. Ты действительно хочешь с этим спорить? Если да, то милости прошу в раздел "Дискуссионный клуб" - и получи там по полной программе. Если же нет (и мне кажется, что это так), то никаких слов, кроме "да, конечно" не нужно, и переводить стрелки на совершенно другое и разводить демагогию - незачем. В любом случае, кончай оффтопить в профильном разделе.

Тебе был дан совет по делу. Есть вопросы по его реализации? спрашивай. Нету - поблагодари за помощь. Считаешь, что volvo сказал что-то обидное? поставь ему минус в репу и, снова, иди обсуди в Дискуссиях.
Вопрос считаю исчерпаным, тут мне отвечать не нужно.
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.