Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 17.06.2009, 22:45   #1
barm
 
Регистрация: 17.06.2009
Сообщений: 7
По умолчанию жду помощи

В общем начал писать программу и столкнулся с проблемой.
Код:
Код:
#include <iostream>
#include <stack>
#include <string>
#include <queue>
using namespace std;

int prior(char a) // возвращает приоритет лексемы
  {
	switch(a)
	  {
		case '0': case '1': case '2': case '3': case '4': case '5':
		case '6': case '7': case '8': case '9': case '.':
		  return 0;
		case '(':
		  return 1;
		case '+':
		case '-':
		  return 2;
		case '*':
		case '/':
		  return 3;
	  }
  }

int main()
  {
	stack<char> st;
	queue<string> outString;
	string inString;
	string cache;
	cache.clear();

	cout << "Vvedite stroku: ";
	cin >> inString;
	int inStrLen = inString.length();

	for(int i=0; i<inStrLen; i++)
	  {
		char cur_tok = inString[i]; // текущая лексема
		if(prior(cur_tok)==0) // если число или точка
		  {
			cache += cur_tok; //положить в кэш
			continue;
		  }
		else // если текущая лексема - знак операции
		  {
			if(!cache.empty())
			  {
				outString.push(cache); // добавить число из кэша в выходную строку
				cache.clear();
			  }
			if(cur_tok=='(')
              {
				st.push('('); // если открывающая скобка, положить в стек
				continue;
              }
			if(cur_tok==')') // если закрывающая скобка
			  {
				while(st.top()!='(') // пока не дойдём до открывающей скобки
				  {
					outString.push(cache=st.top()); //выталкиваем всё из стэк в выходную строку
					st.pop();
				  }
				st.pop(); // выталкиваем саму скобку
				cache.clear();
				continue;
			  }
			if(st.empty()) // если стэк пустой
			  {
				st.push(cur_tok); // заталкиваем текущую лексему в стек
				continue;
			  }
			else
			  {
				if(prior(cur_tok)<=prior(st.top())) // если приоритет текущей лексемы меньше или
													// равен приоритету лексемы на вершине стека
				  while(prior(cur_tok)<=prior(st.top()))
					{
					  outString.push(cache=st.top()); // выталкиваем из стека все лексемы с большим или равным приоритетом
					  cache.clear();
					  st.pop();
					}
				st.push(cur_tok); // кладём текущую лексему в стек
				continue;
			  }
		  }
	  }
	if(!cache.empty()) outString.push(cache); // очищаем кэш
	while(!st.empty())
	  {
		outString.push(cache=st.top()); // выталкиваем из стека оставшиеся лексемы в выходную строку
		st.pop();
	  }
	while(!outString.empty())
	  {
		cout << outString.front() << " ";
		outString.pop();
	  }

	return 0;
  }
компилятор утверждает что я насилую память... покажите как должно быть ибо опыт программирования отсутствует и сам найти ошибку не могу. Код должен переводить арифметическое выражение из инфиксной формы записи в обратную польскую нотацию по такому алгоритму:
- читаем символ из строки
- определяем его приоритет
- если символ число, добавляем его в выходную строку
- если символ открывающая скобка, кладём в стек
- если закрывающая скобка, выталкиваем всё из стека в выходную строку до открывающей скобки, удаляем из стека открывающую скобку
- если знак операции и стек пустой, кладём в стек
- если знак операции и стек не пустой, сравниваем приоритет взятой операции с приоритетом операции на вершине стека и:
- если приоритет операции на вершине стека меньше, кладём в стек взятый символ
- если больше или равен - выталкиваем из стека все операции с равным или большим приоритетом в выходную строку, а взятую операцию кладём в стек
- когда вся строка пройдена, выталкиваем содержимое стека в выходную строку


в качестве выходной строки решил использовать очередь, т.к. с ней в дальнейшем будет удобно работать...

Заранее спасибо!

Последний раз редактировалось barm; 17.06.2009 в 22:47.
barm вне форума Ответить с цитированием
Старый 18.06.2009, 17:13   #2
barm
 
Регистрация: 17.06.2009
Сообщений: 7
По умолчанию

апапапапапапапапап
barm вне форума Ответить с цитированием
Старый 19.06.2009, 12:18   #3
Impuls1989
Форумчанин
 
Аватар для Impuls1989
 
Регистрация: 16.08.2008
Сообщений: 276
По умолчанию

Добрый день barm. Порылся у себя в закромах, и нашел реализацию обратной польской записи:
Код:
#include<stdio.h>
#include<stdlib.h>

struct st                 /* Описание структуры(элемента стека) */
{ char c;struct st *next;};
struct st *push(struct st *,char); /* Прототипы функций */
char DEL(struct st **);
int PRIOR(char);

void main(void)
{
  struct st *OPERS=NULL;     /* Стек операций пуст */
  char a[80],outstring[80];
  int k,point;
  do
  { puts("Введите выражение(в конце '='):");
    fflush(stdin);
    gets(a);                 /* Ввод арифметического выражения */
    k=point=0;
    while(a[k]!='\0'&&a[k]!='=') /* Повторяем ,пока не дойдем до '=' */
    {
      if(a[k]==')')    /* Если очередной символ - ')' */
      {                /* то выталкиваем из стека в выходную строку */
 while((OPERS->c)!='(') /* все знаки операций до ближайшей */
   outstring[point++]=DEL(&OPERS); /* открывающей скобки */
 DEL(&OPERS);   /* Удаляем из стека саму открывающую скобку */
      }
      if(a[k]>='a'&&a[k]<='z')   /* Если очередной символ - буква ,то */
 outstring[point++]=a[k]; /* переписываем её в выходную строку */
      if(a[k]=='(')              /* Если очередной символ - '(' ,то */
 OPERS=push(OPERS,'(');   /* заталкиваем её в стек */
      if(a[k]=='+'||a[k]=='-'||a[k]=='/'||a[k]=='*')
      {                 /* Если следующий символ - знак операции ,то: */
 if(OPERS==NULL)           /* если стек пуст */
   OPERS=push(OPERS,a[k]); /* записываем в него операцию */
 else                      /* если не пуст */
   if(PRIOR(OPERS->c)<PRIOR(a[k])) /* если приоритет поступившей
   операции больше приоритета операции на вершине стека */
     OPERS=push(OPERS,a[k]); /* заталкиваем поступившую операцию
           на стек */
   else  /* если приоритет меньше */
   {
            while((OPERS!=NULL)&&(PRIOR(OPERS->c)>=PRIOR(a[k])))
       outstring[point++]=DEL(&OPERS); /* переписываем в выходную
   строку все операции с большим или равным приоритетом */
     OPERS=push(OPERS,a[k]); /* записываем в стек поступившую */
   }       /* операцию */
      }
      k++; /* Переход к следующему символу входной строки */
    }
    while(OPERS!=NULL) /* после рассмотрения всего выражения */
      outstring[point++]=DEL(&OPERS); /* Переписываем все операции из */
    outstring[point]='\0';            /* стека в выходную строку */
    printf("\n%s\n",outstring);       /* и печатаем её */
    fflush(stdin);
    puts("\nПовторить(y/n)?");
  } while(getchar()!='n');
}

/* Функция push записывает на стек (на вершину которого указывает HEAD)
   символ a . Возвращает указатель на новую вершину стека */
struct st *push(struct st *HEAD,char a)
{
  struct st *PTR;
  if((PTR=malloc(sizeof(struct st)))==NULL) /* Выделение памяти */
  { puts("ет памяти");exit(-1);}  /* Если её нет - выход */
  PTR->c=a;       /* Инициализация созданной вершины */
  PTR->next=HEAD; /* и подключение её к стеку */
  return PTR;     /* PTR -новая вершина стека */
}
/* Функция DEL удаляет символ с вершины стека.
   Возвращает удаляемый символ.Изменяет указатель на вершину стека */
char DEL(struct st **HEAD)
{
  struct st *PTR;
  char a;
  if(*HEAD==NULL) return '\0'; /* Если стек пуст, возвращается '\0' */
  PTR=*HEAD;       /* в PTR - адрес вершины стека */
  a=PTR->c;
  *HEAD=PTR->next; /* Изменяем адрес вершины стека */
  free(PTR);       /* Освобождение памяти */
  return a;        /* Возврат символа с вершины стека */
}

/* Функция PRIOR возвращает приоритет арифм. операции */
int PRIOR(char a)
{
  switch(a)
  { case '*':case '/':return 3;
    case '-':case '+':return 2;
    case '(':return 1;
  }
}
Искусственный интеллект - фигня по сравнению с естественной глупостью
Impuls1989 вне форума Ответить с цитированием
Старый 19.06.2009, 20:10   #4
barm
 
Регистрация: 17.06.2009
Сообщений: 7
По умолчанию

этот вариант в интернете встречал, не подходит...
barm вне форума Ответить с цитированием
Старый 20.06.2009, 13:26   #5
Impuls1989
Форумчанин
 
Аватар для Impuls1989
 
Регистрация: 16.08.2008
Сообщений: 276
По умолчанию

Цитата:
Сообщение от barm Посмотреть сообщение
этот вариант в интернете встречал, не подходит...
Не понимаю, чем он Вам не подходит? В конце идет вывод из стека. Выводите не на экран, а в очередь.
Есть еще одно предположение: может по завершению программы стоит очистить все выши стеки и очереди?
Искусственный интеллект - фигня по сравнению с естественной глупостью
Impuls1989 вне форума Ответить с цитированием
Старый 20.06.2009, 15:26   #6
barm
 
Регистрация: 17.06.2009
Сообщений: 7
По умолчанию

уже не надо я сам нашёл ошибку... незачто
barm вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Жду ВАШЕЙ помощи FieryLADY Gamedev - cоздание игр: Unity, OpenGL, DirectX 2 16.05.2009 06:43
Молю о помощи CoCoS БД в Delphi 2 10.04.2009 13:47
с нетерпением жду советов Римма Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 2 06.02.2008 09:43