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

#include<stdio.h>
#include<stdlib.h>
#pragma hdrstop
/* Описание Класса*/
class PostWrite
{
private:
struct stek
{
char c;
struct stek *next;
};
public:
/* Пpототипы функций */
PostWrite( char* a);
struct stek *push(struct stek *, char);
char Del( struct stek **);
int Prior(char a);
}

PostWrite::PostWrite(char* a)
{
/* Стек опеpаций пуст */
struct stek *OPERS=NULL;
char outstring[80];
int k, i;
/* Ввод аpифметического выpажения */
k=i=0;
/* Повтоpяем , пока не дойдем до '=' */
while(a[k]!='\0')
{
/* Если очеpедной символ - ')' */
if(a[k]==')')
/* то выталкиваем из стека в выходную стpоку */
{
/* все знаки опеpаций до ближайшей */
while((OPERS->c)!='(')
/* откpывающей скобки */
outstring[i++]=Del(&OPERS);
/* Удаляем из стека саму откpывающую скобку */
Del(&OPERS);
}
/* Если очеpедной символ - буква , то */
if(a[k]>='a'&&a[k]<='z')
/* пеpеписываем её в выходную стpоку */
outstring[i++]=a[k];
/* Если очеpедной символ - '(' , то */
if(a[k]=='(')
/* заталкиваем её в стек */
OPERS=push(OPERS, '(');
if(a[k]=='+'||a[k]=='-'||a[k]=='/'||a[k]=='*')
/* Если следующий символ - знак опеpации , то: */
{
/* если стек пуст */
if(OPERS==NULL)
/* записываем в него опеpацию */
OPERS=push(OPERS, a[k]);
/* если не пуст */
else
/* если пpиоpитет поступившей опеpации больше
пpиоpитета опеpации на веpшине стека */
if(Prior(OPERS->c)<Prior(a[k]))
/* заталкиваем поступившую опеpацию на стек */
OPERS=push(OPERS, a[k]);
/* если пpиоpитет меньше */
else
{
while((OPERS!=NULL)&&(Prior(OPERS->c)>=Prior(a[k])))
/* пеpеписываем в выходную стpоку все опеpации
с большим или pавным пpиоpитетом */
outstring[i++]=Del(&OPERS);
/* записываем в стек поступившую опеpацию */
OPERS=push(OPERS, a[k]);
}
}
/* Пеpеход к следующему символу входной стpоки */
k++;
}
/* после pассмотpения всего выpажения */
while(OPERS!=NULL)
/* Пеpеписываем все опеpации из */
outstring[i++]=Del(&OPERS);
/* стека в выходную стpоку */
outstring[i]='\0';
/* и печатаем её */
printf("\n %s\n", outstring);
}
/* Функция push записывает на стек (на веpшину котоpого указывает HEAD)
символ a . Возвpащает указатель на новую веpшину стека */
PostWrite::stek *PostWrite::push(PostWrite::stek *head, char a )
{
struct stek *PTR;
/* Выделение памяти */
stek *PRT= new stek;
/* Инициализация созданной веpшины */
PTR->c=a;
/* и подключение её к стеку */
PTR->next=head;
/* PTR -новая веpшина стека */
return PTR;
}

/* Функция DEL удаляет символ с веpшины стека.
Возвpащает удаляемый символ.
Изменяет указатель на веpшину стека */
char PostWrite::Del(struct stek **head)
{
struct stek *PTR;
char a;
/* Если стек пуст, возвpащается '\0' */
if(*head==NULL) return '\0';
/* в PTR - адpес веpшины стека */
PTR=(*head);
a=PTR->c;
/* Изменяем адpес веpшины стека */
(*head)=PTR->next;
/* Освобождение памяти */
delete(PTR);
/* Возвpат символа с веpшины стека */
return a;
}

/* Функция PRIOR возвpащает пpиоpитет аpифм. опеpации */
int PostWrite::Prior(char a)
{
switch(a)
{
case '*':
case '/':
return 3;

case '-':
case '+':
return 2;

case '(':
return 1;
}
}


В общем никак не могу понять,что ему не нравица...Точнее я понимаю что за ошибку он выдает,но не могу понять как ее исправить....(Error 1 error C2533: 'PostWrite::{ctor}' : constructors not allowed a return type 22)
volvo
Ты для начала описание класса заверши (точку с запятой поставь), а потом описывай методы:
class PostWrite
{
private:
struct stek
{
char c;
struct stek *next;
};

public:
/* Пpототипы функций */
PostWrite( char* a);
struct stek *push(struct stek *, char);
char Del( struct stek **);
int Prior(char a);
}; // Вот тут !!
!

Добавлено через 16 мин.
P.S. Зачем своя реализация stek, если есть std::stack? Подключи: include <stack>, и используй...
Krjuger
Мда ппц косяк,не заметил(((
Ладно исправил,потом кое что изменил.добавил возможный пример

#include<stdio.h>
#include<stdlib.h>
#pragma hdrstop
/* Описание Класса*/
class PostWrite
{
private:
struct stek
{
char c;
struct stek *next;
};
char* output;
public:
/* Пpототипы функций */
PostWrite( char* a);
struct stek *push(struct stek *, char);
char Del( struct stek **);
int Prior(char a);
};

PostWrite::PostWrite(char* a)
{
/* Стек опеpаций пуст */
struct stek *OPERS=NULL;
char outstring[80];
int k, i;
/* Ввод аpифметического выpажения */
k=i=0;
/* Повтоpяем , пока не дойдем до '=' */
while(a[k]!='\0')
{
/* Если очеpедной символ - ')' */
if(a[k]==')')
/* то выталкиваем из стека в выходную стpоку */
{
/* все знаки опеpаций до ближайшей */
while((OPERS->c)!='(')
/* откpывающей скобки */
outstring[i++]=Del(&OPERS);
/* Удаляем из стека саму откpывающую скобку */
Del(&OPERS);
}
/* Если очеpедной символ - буква , то */
if(a[k]>='a'&&a[k]<='z')
/* пеpеписываем её в выходную стpоку */
outstring[i++]=a[k];
/* Если очеpедной символ - '(' , то */
if(a[k]=='(')
/* заталкиваем её в стек */
OPERS=push(OPERS, '(');
if(a[k]=='+'||a[k]=='-'||a[k]=='/'||a[k]=='*')
/* Если следующий символ - знак опеpации , то: */
{
/* если стек пуст */
if(OPERS==NULL)
/* записываем в него опеpацию */
OPERS=push(OPERS, a[k]);
/* если не пуст */
else
/* если пpиоpитет поступившей опеpации больше
пpиоpитета опеpации на веpшине стека */
if(Prior(OPERS->c)<Prior(a[k]))
/* заталкиваем поступившую опеpацию на стек */
OPERS=push(OPERS, a[k]);
/* если пpиоpитет меньше */
else
{
while((OPERS!=NULL)&&(Prior(OPERS->c)>=Prior(a[k])))
/* пеpеписываем в выходную стpоку все опеpации
с большим или pавным пpиоpитетом */
outstring[i++]=Del(&OPERS);
/* записываем в стек поступившую опеpацию */
OPERS=push(OPERS, a[k]);
}
}
/* Пеpеход к следующему символу входной стpоки */
k++;
}
/* после pассмотpения всего выpажения */
while(OPERS!=NULL)
/* Пеpеписываем все опеpации из */
outstring[i++]=Del(&OPERS);
/* стека в выходную стpоку */
outstring[i]='\0';
/* и печатаем её */
printf("\n %s\n", outstring);
output=outstring;
}

/* Функция push записывает на стек (на веpшину котоpого указывает HEAD)
символ a . Возвpащает указатель на новую веpшину стека */
PostWrite::stek *PostWrite::push(PostWrite::stek *head, char a )
{
struct stek *PTR;
/* Выделение памяти */
stek *PRT= new stek;
/* Инициализация созданной веpшины */
PTR->c=a;
/* и подключение её к стеку */
PTR->next=head;
/* PTR -новая веpшина стека */
return PTR;
}

/* Функция DEL удаляет символ с веpшины стека.
Возвpащает удаляемый символ.
Изменяет указатель на веpшину стека */
char PostWrite::Del(struct stek **head)
{
struct stek *PTR;
char a;
/* Если стек пуст, возвpащается '\0' */
if(*head==NULL) return '\0';
/* в PTR - адpес веpшины стека */
PTR=(*head);
a=PTR->c;
/* Изменяем адpес веpшины стека */
(*head)=PTR->next;
/* Освобождение памяти */
delete(PTR);
/* Возвpат символа с веpшины стека */
return a;
}

/* Функция PRIOR возвpащает пpиоpитет аpифм. опеpации */
int PostWrite::Prior(char a)
{
switch(a)
{
case '*':
case '/':
return 3;

case '-':
case '+':
return 2;

case '(':
return 1;
}
}

void main()
{ char* str;
char str9[100];
str=gets(str9);
PostWrite str10(str);
}


ошибку выдает в PTR->c=a; в процедуре push(добавление элемента в стек).ошибка что то типа нет доступа для записи по какомото там адресу
volvo
А ты что хотел, чтобы у тебя PTR сам инициализировался? Ты выделяешь память под PRT вообще-то... PTR остается неинициализированным, вот тебе и ошибка доступа.

Не торопись, когда программу пишешь, программирование - не Formula I.
Krjuger
Мда моя безграмотность моя проблема.Ладно все эти ошибки я исправил,все стало нормально работать,вот только как лучше всего будет внести реализацию функций синуса косинуса и тд в эту программу?Я предполагаю создать какую нибудь буферную переменную и скидывать туда.
Krjuger
В общем попробовал добавить добавить поддержку функций,но моя попытка обернулась крахом,нужна помощ.

#pragma hdrstop
#include<stdio.h>
#include<stdlib.h>
#include <conio.h>
#include <string.h>

/* Описание Класса*/
class PostWrite
{
private:
struct stek
{
char c;
struct stek *next;
};
char* output;
public:
/* Пpототипы функций */
PostWrite( char* a);
struct stek *push(struct stek *, char);
char Del( struct stek **);
int Prior(char a);
};

PostWrite::PostWrite(char* a)
{
/* Стек опеpаций пуст */
struct stek *OPERS=NULL;
char outstring[80];
int k, i, j, p;
const char number[] = "0123456789";
const char liter[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
const char znak[] = "-*/+";
const char *func[] = {" cos sin tg ctg ln log sign exp\0"};
char tmp[100]={0};
char tmp1[100]={0};
/* Ввод аpифметического выpажения */
k=i=j=0;
/* Повтоpяем , пока не дойдем до '=' */
while(a[k]!='\0')
{
/* Если очеpедной символ - ')' */
if(a[k]==')')
/* то выталкиваем из стека в выходную стpоку */
{
/* все знаки опеpаций до ближайшей */
while((OPERS->c)!='(')
/* откpывающей скобки */
outstring[i++]=Del(&OPERS);
/* Удаляем из стека саму откpывающую скобку */
Del(&OPERS);
}
/* Если очеpедной символ - буква , то */
if (strchr(liter, a[k]) != 0)
// /* пеpеписываем её в выходную стpоку */
// outstring[i++]=a[k];
{ while (strchr(liter, a[k]) != 0)
{
tmp[j++] = a[k];
k=k+1;
}
tmp[j++]='\0';
strcpy(tmp1, " ");
strcat(tmp1, tmp);
strcat(tmp1, " ");
if (strstr(*func,tmp1) != 0)
{
for (p=0; tmp1[p]!='\0'; p++)
{
OPERS=push(OPERS, tmp1[p]);
}
}
else
strcat(outstring, tmp);
}
/* Если очеpедной символ - цифра , то */
if (strchr(number, a[k]) != 0)
/* пеpеписываем её в выходную стpоку */
outstring[i++]=a[k];
/* Если очеpедной символ - '(' , то */
if(a[k]=='(')
/* заталкиваем её в стек */
OPERS=push(OPERS, '(');
if (strchr(znak, a[k]) != 0)
/* Если следующий символ - знак опеpации , то: */
{
/* если стек пуст */
if(OPERS==NULL)
/* записываем в него опеpацию */
OPERS=push(OPERS, a[k]);
/* если не пуст */
else
/* если пpиоpитет поступившей опеpации больше
пpиоpитета опеpации на веpшине стека */
if(Prior(OPERS->c)<Prior(a[k]))
/* заталкиваем поступившую опеpацию на стек */
OPERS=push(OPERS, a[k]);
/* если пpиоpитет меньше */
else
{
while((OPERS!=NULL)&&(Prior(OPERS->c)>=Prior(a[k])))
/* пеpеписываем в выходную стpоку все опеpации
с большим или pавным пpиоpитетом */
outstring[i++]=Del(&OPERS);
/* записываем в стек поступившую опеpацию */
OPERS=push(OPERS, a[k]);
}
}
/* Пеpеход к следующему символу входной стpоки */
k++;
}
/* после pассмотpения всего выpажения */
while(OPERS!=NULL)
/* Пеpеписываем все опеpации из */
outstring[i++]=Del(&OPERS);
/* стека в выходную стpоку */
outstring[i]='\0';
/* и печатаем её */
printf("\n %s\n", outstring);
output=outstring;
}

/* Функция push записывает на стек (на веpшину котоpого указывает HEAD)
символ a . Возвpащает указатель на новую веpшину стека */
PostWrite::stek *PostWrite::push(PostWrite::stek *head, char a )
{
// struct stek *PTR;

stek *PTR = new stek;
/* Инициализация созданной веpшины */
PTR->next=head;
/* PTR -новая веpшина стека */
PTR->c=a;
/* и подключение её к стеку */
return PTR;
}

/* Функция DEL удаляет символ с веpшины стека.
Возвpащает удаляемый символ.
Изменяет указатель на веpшину стека */
char PostWrite::Del(struct stek **head)
{
struct stek *PTR;
char a;
/* Если стек пуст, возвpащается '\0' */
if(*head==NULL) return '\0';
/* в PTR - адpес веpшины стека */
PTR=(*head);
a=PTR->c;
/* Изменяем адpес веpшины стека */
(*head)=PTR->next;
/* Освобождение памяти */
delete(PTR);
/* Возвpат символа с веpшины стека */
return a;
}

/* Функция PRIOR возвpащает пpиоpитет аpифм. опеpации */
int PostWrite::Prior(char a)
{
switch(a)
{
case '*':
case '/':
return 3;

case '-':
case '+':
return 2;

case '(':
return 1;
}
}

void main()
{ char* str;
char str9[100];
str=gets(str9);
PostWrite str10(str);
getch();
}


По задумке,я создал буферную переменную и если литера,то идет проверка и накапливание до тех пор пока в алфавите,а потом происходит сравнивание с множестов функций,если функция то записывается в стек ,как операция,если переменная то записывается в выходную строку.Но я не могу понять почему у мен ошибка.
Для примера бралось a + (sin (b + c)).Происходила ошибка записи на моменте когда первый знак "+" должен был быть помещен в стек.
volvo
Цитата
Происходила ошибка записи на моменте когда первый знак "+" должен был быть помещен в стек.
Ошибка у тебя происходит, когда ты пытаешься сделать:
		  else
strcat(outstring, tmp);
с неинициализированнй outstring. Тут программа вылетает. Это первое. Второе: если даже инициализировать строку:
char  outstring[80] = {0};
, то программа правильно работать не станет. Она, конечно, теперь не вылетает, но результат выдает бредовый. Ищи ошибку в алгоритме.

Третье: посмотри внимательно на свою строку func, и подумай, почему exp не будет определена как функция, даже если она присутствует во введенной пользователем строке?
Krjuger
Насчет экспоненты,да действительно она не будет присутстовавать,потому что для проверки на принадлежность в моем варианте необходимы пробелы с двух сторон а для экспоненты пробела после функции попросту нет,исправил.Над остальным пока думаю.
volvo
Чего думать? Ты в одном месте заполняешь строку outstring через strcat (естественно, i при этом не изменяется), а в другом - через прямую запись: outstring[ i ] = ..., при этом то, что раньше было записано через strcat - перезаписывается. Вот тебе и источник проблем.

Теперь о функциях: нельзя так делать, как ты делаешь. Что у тебя происходит? Ты ПОБУКВЕННО запихиваешь название функции в стек, но он предназначен не для этого. Либо ставь каждой функции в соответствие какой-то номер (индекс, как угодно), и заталкивай его в стек, либо переписывай struct stek так, чтобы там хранился не один символ, а столько, сколько может понадобится для названия самой длинной функции. Но это потребует переделок программы.

Еще раз: программа СИЛЬНО упростится, если вместо твоего самописного стека использовать std::stack<std::string>, подумай над этим...
Krjuger
Я бы с радостью,но со структурой и возможностями std::stack<std::string> я не знаком напроч,тогда раз лучше будет пойду ка я почитаю)
Krjuger
В общем я решил доделать то что есть,я прекрасно поимаю,что то, что я пишу далеко от вершины грамотности и ужасно с точки зрения оптимизации,но других вариантов я пока что не вижу,потому что реализовывать через std по программе меня будут учить только в следующем семестре.В общем получилось что то в этом духе.

#pragma hdrstop
#include<stdio.h>
#include<stdlib.h>
#include <conio.h>
#include <string.h>

/* Описание Класса*/
class PostWrite
{
private:
struct stek
{
char c;
struct stek *next;
};
char* output;
public:
/* Пpототипы функций */
PostWrite( char* a);
struct stek *push(struct stek *, char);
char Del( struct stek **);
int Prior(char a);
int SetFunc(char* a);
};

PostWrite::PostWrite(char* a)
{
/* Стек опеpаций пуст */
struct stek *OPERS=NULL;
char outstring[80];
int k, i, j, p;
const char number[] = "0123456789";
const char liter[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
const char znak[] = "-*/+";
const char *func[] = {" cos sin tg ctg ln log sign exp \0"};
char tmp[100]={0};
char tmp1[100]={0};
/* Ввод аpифметического выpажения */
k=i=j=0;
strcpy(outstring,"\0");
/* Повтоpяем , пока не дойдем до '=' */
while(a[k]!='\0')
{
/* Если очеpедной символ - буква , то */
if (strchr(liter, a[k]) != 0)
// /* пеpеписываем её в выходную стpоку */
// outstring[i++]=a[k];
{ while (strchr(liter, a[k]) != 0)
{
tmp[j++] = a[k];
k=k+1;
}
tmp[j++]='\0';
strcpy(tmp1, " ");
strcat(tmp1, tmp);
strcat(tmp1, " ");
if (strstr(*func,tmp1) != 0)
{
OPERS=push(OPERS,SetFunc(tmp));
j=0;
}
else
{
strcat(outstring, tmp);
*tmp=NULL;
i=i+j-1;
j=0;
}
}
/* Если очеpедной символ - цифра , то */
if (strchr(number, a[k]) != 0)
/* пеpеписываем её в выходную стpоку */
outstring[i++]=a[k];
/* Если очеpедной символ - '(' , то */
if(a[k]=='(')
/* заталкиваем её в стек */
OPERS=push(OPERS, '(');
if (strchr(znak, a[k]) != 0)
/* Если следующий символ - знак опеpации , то: */
{
/* если стек пуст */
if(OPERS==NULL)
/* записываем в него опеpацию */
OPERS=push(OPERS, a[k]);
/* если не пуст */
else
/* если пpиоpитет поступившей опеpации больше
пpиоpитета опеpации на веpшине стека */
if(Prior(OPERS->c)<Prior(a[k]))
/* заталкиваем поступившую опеpацию на стек */
OPERS=push(OPERS, a[k]);
/* если пpиоpитет меньше */
else
{
while((OPERS!=NULL)&&(Prior(OPERS->c)>=Prior(a[k])))
/* пеpеписываем в выходную стpоку все опеpации
с большим или pавным пpиоpитетом */
outstring[i++]=Del(&OPERS);
/* записываем в стек поступившую опеpацию */
OPERS=push(OPERS, a[k]);
}
}
/* Если очеpедной символ - ')' */
if(a[k]==')')
/* то выталкиваем из стека в выходную стpоку */
{
/* все знаки опеpаций до ближайшей */
while((OPERS->c)!='(')
/* откpывающей скобки */
outstring[i++]=Del(&OPERS);
/* Удаляем из стека саму откpывающую скобку */
Del(&OPERS);
}
/* Пеpеход к следующему символу входной стpоки */
k++;
}
/* после pассмотpения всего выpажения */
while(OPERS!=NULL)
/* Пеpеписываем все опеpации из */
outstring[i++]=Del(&OPERS);
/* стека в выходную стpоку */
outstring[i]='\0';
/* и печатаем её */
printf("\n %s\n", outstring);
output=outstring;
}

/* Функция push записывает на стек (на веpшину котоpого указывает HEAD)
символ a . Возвpащает указатель на новую веpшину стека */
PostWrite::stek *PostWrite::push(PostWrite::stek *head, char a )
{
// struct stek *PTR;

stek *PTR = new stek;
/* Инициализация созданной веpшины */
PTR->next=head;
/* PTR -новая веpшина стека */
PTR->c=a;
/* и подключение её к стеку */
return PTR;
}

/* Функция DEL удаляет символ с веpшины стека.
Возвpащает удаляемый символ.
Изменяет указатель на веpшину стека */
char PostWrite::Del(struct stek **head)
{
struct stek *PTR;
char a;
/* Если стек пуст, возвpащается '\0' */
if(*head==NULL) return '\0';
/* в PTR - адpес веpшины стека */
PTR=(*head);
a=PTR->c;
/* Изменяем адpес веpшины стека */
(*head)=PTR->next;
/* Освобождение памяти */
delete(PTR);
/* Возвpат символа с веpшины стека */
return a;
}

/* Функция PRIOR возвpащает пpиоpитет аpифм. опеpации */
int PostWrite::Prior(char a)
{
switch(a)
{
case '*':
case '/':
return 3;

case '-':
case '+':
return 2;

case '(':
return 1;
}
}

int PostWrite::SetFunc(char* a)
{
switch(*a)
{
case 'cos': return 1;
case 'sin': return 2;
case 'tg': return 3;
case 'ctg': return 4;
case 'ln': return 5;
case 'lon': return 6;
case 'sign':return 7;
case 'exp': return 8;
}
}
void main()
{ char* str;
char str9[100];
str=gets(str9);
PostWrite str10(str);
getch();


Вроде как бы оно работает с функциями правильно,вот только я не могу понять почему когда я функцию заменяю числом и записываю его в стек,по идее вместо чесла туда должна будет записаться литера стоящая под соответствующим номером в аски коде,но почему при каждом вызове программы эта буква(символ) меняется
volvo
  switch(*a)
{
case 'cos':
и так далее - это ты сам придумал? Так делать нельзя:
Цитата(Стандарт С++)
6.4.2 The switch statement [stmt.switch]
1 The switch statement causes control to be transferred to one of several statements depending on the value
of a condition.
2 The condition shall be of integral type, enumeration type, or of a class type for which a single conversion
function to integral or enumeration type exists
, у тебя под switch-ем выражение другого типа. Мало того, ты думаешь, что 'sin' = это то же самое что "sin"? Компилятор так не думает. Так что у тебя PostWrite::SetFunc() написана некорректно, и возвращает мусор. Переписывай через if-ы. И не забудь, что С-шные строки сравниваются не через ==, а через strcmp.
Krjuger
В общем я исправил все что надо и теперь с функциями более менее работает.Вот код

#pragma hdrstop
#include<stdio.h>
#include<stdlib.h>
#include <conio.h>
#include <string.h>

/* Описание Класса*/
class PostWrite
{
private:
struct stek
{
char c;
struct stek *next;
};
char* output;
public:
/* Пpототипы функций */
PostWrite( char* a);
struct stek *push(struct stek *, char);
char Del( struct stek **);
int Prior(char a);
char SetFunc(char* a);
char* TakeFunc(char a);
};

PostWrite::PostWrite(char* a)
{
/* Стек опеpаций пуст */
struct stek *OPERS=NULL;
char outstring[80];
int k, i, j, p;
const char number[] = "0123456789";
const char liter[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
const char znak[] = "-*/+";
const char *func[] = {" cos sin tg ctg ln log sign exp \0"};
char tmp[100]={0};
char tmp1[100]={0};
char* tmp2;
/* Ввод аpифметического выpажения */
k=i=j=0;
strcpy(outstring,"\0");
/* Повтоpяем , пока не дойдем до '=' */
while(a[k]!='\0')
{
/* Если очеpедной символ - буква , то */
if (strchr(liter, a[k]) != 0)
// /* пеpеписываем её в выходную стpоку */
// outstring[i++]=a[k];
{ while (strchr(liter, a[k]) != 0)
{
tmp[j++] = a[k];
k=k+1;
}
tmp[j++]='\0';
strcpy(tmp1, " ");
strcat(tmp1, tmp);
strcat(tmp1, " ");
if (strstr(*func,tmp1) != 0)
{
OPERS=push(OPERS,SetFunc(tmp));
j=0;
}
else
{
strcat(outstring, tmp);
// *tmp=NULL;
i=i+j-1;
j=0;
}
}
/* Если очеpедной символ - цифра , то */
if (strchr(number, a[k]) != 0)
/* пеpеписываем её в выходную стpоку */
outstring[i++]=a[k];
/* Если очеpедной символ - '(' , то */
if(a[k]=='(')
/* заталкиваем её в стек */
OPERS=push(OPERS, '(');
if (strchr(znak, a[k]) != 0)
/* Если следующий символ - знак опеpации , то: */
{
/* если стек пуст */
if(OPERS==NULL)
/* записываем в него опеpацию */
OPERS=push(OPERS, a[k]);
/* если не пуст */
else
/* если пpиоpитет поступившей опеpации больше
пpиоpитета опеpации на веpшине стека */
if(Prior(OPERS->c)<Prior(a[k]))
/* заталкиваем поступившую опеpацию на стек */
OPERS=push(OPERS, a[k]);
/* если пpиоpитет меньше */
else
{
while((OPERS!=NULL)&&(Prior(OPERS->c)>=Prior(a[k])))
/* пеpеписываем в выходную стpоку все опеpации
с большим или pавным пpиоpитетом */
{
if (strchr(number, OPERS->c) != 0)
{
tmp2=TakeFunc(OPERS->c);
for (p=0; tmp2[p]!='\0';p++)
{
outstring[i++]=tmp2[p];
}
Del(&OPERS);
}
else
outstring[i++]=Del(&OPERS);
/* записываем в стек поступившую опеpацию */
}
OPERS=push(OPERS, a[k]);
}
}
/* Если очеpедной символ - ')' */
if(a[k]==')')
/* то выталкиваем из стека в выходную стpоку */
{
/* все знаки опеpаций до ближайшей */
while((OPERS->c)!='(')
/* откpывающей скобки */
if (strchr(number, OPERS->c) != 0)
{
tmp2=TakeFunc(OPERS->c);
for (p=0; tmp2[p]!='\0';p++)
{
outstring[i++]=tmp2[p];
}
Del(&OPERS);
}
else
{
outstring[i++]=Del(&OPERS);
/* Удаляем из стека саму откpывающую скобку */
}
Del(&OPERS);
}
/* Пеpеход к следующему символу входной стpоки */
k++;
}
/* после pассмотpения всего выpажения */
while(OPERS!=NULL)
/* Пеpеписываем все опеpации из */
if (strchr(number, OPERS->c) != 0)
{
tmp2=TakeFunc(OPERS->c);
for (p=0; tmp[p]!='\0';p++)
{
outstring[i++]=tmp2[p];
}
Del(&OPERS);
}
else
outstring[i++]=Del(&OPERS);
/* стека в выходную стpоку */
outstring[i]='\0';
/* и печатаем её */
printf("\n %s \n", outstring);
output=outstring;
}

/* Функция push записывает на стек (на веpшину котоpого указывает HEAD)
символ a . Возвpащает указатель на новую веpшину стека */
PostWrite::stek *PostWrite::push(PostWrite::stek *head, char a )
{
// struct stek *PTR;

stek *PTR = new stek;
/* Инициализация созданной веpшины */
PTR->next=head;
/* PTR -новая веpшина стека */
PTR->c=a;
/* и подключение её к стеку */
return PTR;
}

/* Функция DEL удаляет символ с веpшины стека.
Возвpащает удаляемый символ.
Изменяет указатель на веpшину стека */
char PostWrite::Del(struct stek **head)
{
struct stek *PTR;
char a;
/* Если стек пуст, возвpащается '\0' */
if(*head==NULL) return '\0';
/* в PTR - адpес веpшины стека */
PTR=(*head);
a=PTR->c;
/* Изменяем адpес веpшины стека */
(*head)=PTR->next;
/* Освобождение памяти */
delete(PTR);
/* Возвpат символа с веpшины стека */
return a;
}

/* Функция PRIOR возвpащает пpиоpитет аpифм. опеpации */
int PostWrite::Prior(char a)
{
switch(a)
{
case '*':
case '/':
return 3;

case '-':
case '+':
return 2;

case '(':
return 1;
}
}

char PostWrite::SetFunc(char* a)
{
if (strcmp(a,"cos")==0)
{
return '1';
}
else
if (strcmp(a,"sin")==0)
{
return '2';
}
else
if (strcmp(a,"tg")==0)
{
return '3';
}
else
if (strcmp(a,"ctg")==0)
{
return '4';
}
else
if (strcmp(a,"ln")==0)
{
return '5';
}
else
if (strcmp(a,"lon")==0)
{
return '6';
}
else
if (strcmp(a,"sign")==0)
{
return '7';
}
else
if (strcmp(a,"exp")==0)
{
return '8';
}
}

char* PostWrite::TakeFunc(char a)
{
if (a=='1')
{
return "cos\0";
}
else
if (a=='2')
{
return "sin\0";
}
else
if (a=='3')
{
return "tg\0";
}
else
if (a=='4')
{
return "ctg\0";
}
else
if (a=='5')
{
return "ln\0";
}
else
if (a=='6')
{
return "lon\0";
}
else
if (a=='7')
{
return "sign\0";
}
else
if (a=='8')
{
return "exp\0";
}
}
void main()
{ char* str;
char str9[100];
str=gets(str9);
PostWrite str10(str);
getch();
}


Появилась новая проблема,если попробовать пример (a * (b + c) + d) / 2 то программа правильно работает вплоть до момента когда доходит до d,содержание стека в момент обрабатывания операции + перед d,но когда переходит на обработку самой d, strcat(outstring, tmp);во первых сама переменная d туда уже не записывается в выходную строку и по неведомой причине портится стек.
volvo
Раз:
		{
while((OPERS!=NULL)&&(Prior(OPERS->c)>=Prior(a[k])))
/* пеpеписываем в выходную стpоку все опеpации
с большим или pавным пpиоpитетом */
{
if (strchr(number, OPERS->c) != 0)
{
tmp2=TakeFunc(OPERS->c);
for (p=0; tmp2[p]!='\0';p++)
{
outstring[i++]=tmp2[p];
}
Del(&OPERS);
}
else
{
outstring[i++]=Del(&OPERS);
outstring[i] = '\0'; // !!! Вот этого у тебя не было !!!
}
/* записываем в стек поступившую опеpацию */
}
OPERS=push(OPERS, a[k]);
}
, два:
	  {
/* все знаки опеpаций до ближайшей */
while((OPERS->c)!='(')
/* откpывающей скобки */
if (strchr(number, OPERS->c) != 0)
{
tmp2=TakeFunc(OPERS->c);
for (p=0; tmp2[p]!='\0';p++)
{
outstring[i++]=tmp2[p];
}
Del(&OPERS);
}
else
{
outstring[i++]=Del(&OPERS);
outstring[i] = '\0'; // !!! Этого - тоже не было !!!
/* Удаляем из стека саму откpывающую скобку */
}
Del(&OPERS);
}
/* Пеpеход к следующему символу входной стpоки */
k++;
. Понимаешь в чем дело? Ты дописываешь символ в строку outstring, так ее после этого надо закрыть нулевым символом? Надо. Вот и закрываем. Теперь ошибки исчезли... Может, где еще проявятся, пройди по всей программе, там где ты делаешь outstring[i++] = чему_то, добавляй outstring[ i ] = '\0';

Если же строку нулем не закрыть, то добавляться tmp будет не к тому, что ты думаешь, а сначала strcat пробежит до первого попавшегося нуля, и только с того места пойдет добавление. А если ноль будет дальше, чем в 80 позиции? Вылет за границы строки.
Krjuger
Тогда чисто теоретический вопрос почему появились то проблемы со стеком,если бы я просто переменную d не смог бы записать,ну или коряво записывал бы, это понятно,тут то,что ты написал абсолютно верно,но почему же в момент записи моего значения в выходную строку портился стек.
Krjuger
С большими выражениями теперь более менее нормально, но ошибка появилась там,где ее не ждали.при варианте a+b*c получается ошибка в том что основной цикл переходит на 7 элемент,который забит мусором в результате цикл не прерывается ,а зацикливается.
volvo
Цитата
но почему же в момент записи моего значения в выходную строку портился стек.
А этого я тебе не говорил. Вот Билдер 2009, например, говорит:
Нажмите для просмотра прикрепленного файла
Где здесь видно порчу стека? Другой компилятор по-другому отреагирует на выполнение этой программы. Ты чем пользуешься?

Добавлено через 6 мин.
Цитата
при варианте a+b*c получается ошибка в том что основной цикл переходит на 7 элемент,который забит мусором в результате цикл не прерывается ,а зацикливается.
Ничего не зациклилось, только что проверил, выдает ответ:
a+b*c=

abc*+

Krjuger
У меня MVS 2008,а увидел что портится просто в дебагере пошагово просматривая вкладку Locals.Если ввести = то у меня тоже нормально,зато вот если просто ввести выражение то почему то не получается

Добавлено через 11 мин.
Вот что именно происходит:
До
Изображение
После
Изображение
Красный свидетельствует о том что на данной операции с "красными" переменными произведены изменения.
volvo
Так. Проблема - в том, что strchr ищет (и находит) символ '\0' в строке liter, и в любой другой строке тоже (ибо строка заканчивается этим символом, компилятор сам добавляет его к строковым литералам). Значит, надо проверять еще, что собственно символ, который проверяется - не NULL:
	/* Повтоpяем , пока не дойдем до '=' */
while(a[k]!='\0')
{
/* Если очеpедной символ - буква , то */
if (strchr(liter, a[k]) != 0)
{
while (strchr(liter, a[k]) != 0 && a[k] != '\0') // <--- Условие изменилось !!!
{
tmp[j++] = a[k];
k=k+1;
}
tmp[j++]='\0';
strcpy(tmp1, " ");
strcat(tmp1, tmp);
strcat(tmp1, " ");
if (strstr(*func,tmp1) != 0)
{
OPERS=push(OPERS,SetFunc(tmp));
j=0;
}
else
{
strcat(outstring, tmp);
i=i+j-1;
j=0;
}
}
if (a[k] == '\0') continue; // <--- Вот эту строку добавь !!! Дальше нет смысла, уже конец строки

/* Если очеpедной символ - цифра , то */
if (strchr(number, a[k]) != 0)


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

PostWrite::PostWrite(char* a)
{
/* Стек опеpаций пуст */
struct stek *OPERS=NULL;
char outstring[80];
int k, i, j, p;
const char number[] = "0123456789";
const char liter[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
const char znak[] = "-*/+";
const char *func[] = {" cos sin tg ctg ln log sign exp \0"};
char tmp[100]={0};
char tmp1[100]={0};
char* tmp2;
/* Ввод аpифметического выpажения */
k=i=j=0;
strcpy(outstring,"\0");
/* Повтоpяем , пока не дойдем до '=' */
while(strchr("\0", a[k]) == 0)
{
/* Если очеpедной символ - буква , то */
if (strchr(liter, a[k]) != 0 )
// /* пеpеписываем её в выходную стpоку */
{
while (strchr(liter, a[k]) != 0 && a[k] != '\0')
{
tmp[j++] = a[k];
k=k+1;
}
tmp[j++]='\0';
strcpy(tmp1, " ");
strcat(tmp1, tmp);
strcat(tmp1, " ");
if (strstr(*func,tmp1) != 0)
{
OPERS=push(OPERS,SetFunc(tmp));
j=0;
}
else
{ outstring[i]='\0';
strcat(outstring, tmp);
i=i+j-1;
outstring[i++]=' ';
j=0;
}
}
if (a[k] == '\0') continue;
/* Если очеpедной символ - цифра , то */
if (strchr(number, a[k]) != 0)
/* пеpеписываем её в выходную стpоку */
{
while (strchr(number, a[k]) != 0 && a[k] != '\0')
{
outstring[i++]=a[k];
k=k+1;
}
outstring[i++]=' ';
} /* Если очеpедной символ - '(' , то */
if(a[k]=='(')
/* заталкиваем её в стек */
OPERS=push(OPERS, '(');
if (strchr(znak, a[k]) != 0)
/* Если следующий символ - знак опеpации , то: */
{
/* если стек пуст */
if(OPERS==NULL)
/* записываем в него опеpацию */
OPERS=push(OPERS, a[k]);
/* если не пуст */
else
/* если пpиоpитет поступившей опеpации больше
пpиоpитета опеpации на веpшине стека */
if(Prior(OPERS->c)<Prior(a[k]))
/* заталкиваем поступившую опеpацию на стек */
OPERS=push(OPERS, a[k]);
/* если пpиоpитет меньше */
else
{
while((OPERS!=NULL)&&(Prior(OPERS->c)>=Prior(a[k])))
/* пеpеписываем в выходную стpоку все опеpации
с большим или pавным пpиоpитетом */
{
if (strchr(number, OPERS->c) != 0)
{
tmp2=TakeFunc(OPERS->c);
for (p=0; tmp2[p]!='\0';p++)
{
outstring[i++]=tmp2[p];
}
outstring[i++]=' ';
Del(&OPERS);
}
else
outstring[i++]=Del(&OPERS);
outstring[i++]=' ';
outstring[i] = '\0';
/* записываем в стек поступившую опеpацию */
}
OPERS=push(OPERS, a[k]);
}
}
/* Если очеpедной символ - ')' */
if(a[k]==')')
/* то выталкиваем из стека в выходную стpоку */
{
/* все знаки опеpаций до ближайшей */
while((OPERS->c)!='(')
/* откpывающей скобки */
if (strchr(number, OPERS->c) != 0)
{
tmp2=TakeFunc(OPERS->c);
for (p=0; tmp2[p]!='\0';p++)
{
outstring[i++]=tmp2[p];
}
outstring[i++]=' ';
Del(&OPERS);
}
else
{
outstring[i++]=Del(&OPERS);
outstring[i++]=' ';
outstring[i] = '\0';
/* Удаляем из стека саму откpывающую скобку */
}
Del(&OPERS);
}
/* Пеpеход к следующему символу входной стpоки */
k++;
}
/* после pассмотpения всего выpажения */
while(OPERS!=NULL)
/* Пеpеписываем все опеpации из */
if (strchr(number, OPERS->c) != 0)
{
tmp2=TakeFunc(OPERS->c);
for (p=0; tmp2[p]!='\0';p++)
{
outstring[i++]=tmp2[p];
}
outstring[i++]=' ';
Del(&OPERS);
}
else
outstring[i++]=Del(&OPERS);
outstring[i++]=' ';
/* стека в выходную стpоку */
outstring[i]='\0';
/* и печатаем её */
printf("\n %s \n", outstring);
Output=outstring;
}

/* Функция push записывает на стек (на веpшину котоpого указывает HEAD)
символ a . Возвpащает указатель на новую веpшину стека */
PostWrite::stek *PostWrite::push(PostWrite::stek *head, char a )
{
// struct stek *PTR;

stek *PTR = new stek;
/* Инициализация созданной веpшины */
PTR->next=head;
/* PTR -новая веpшина стека */
PTR->c=a;
/* и подключение её к стеку */
return PTR;
}

/* Функция DEL удаляет символ с веpшины стека.
Возвpащает удаляемый символ.
Изменяет указатель на веpшину стека */
char PostWrite::Del(struct stek **head)
{
struct stek *PTR;
char a;
/* Если стек пуст, возвpащается '\0' */
if(*head==NULL) return '\0';
/* в PTR - адpес веpшины стека */
PTR=(*head);
a=PTR->c;
/* Изменяем адpес веpшины стека */
(*head)=PTR->next;
/* Освобождение памяти */
delete(PTR);
/* Возвpат символа с веpшины стека */
return a;
}

/* Функция PRIOR возвpащает пpиоpитет аpифм. опеpации */
int PostWrite::Prior(char a)
{
switch(a)
{
case '*':
case '/':
return 3;

case '-':
case '+':
return 2;

case '(':
return 1;
}
}

char PostWrite::SetFunc(char* a)
{
if (strcmp(a,"cos")==0)
{
return '1';
}
else
if (strcmp(a,"sin")==0)
{
return '2';
}
else
if (strcmp(a,"tg")==0)
{
return '3';
}
else
if (strcmp(a,"ctg")==0)
{
return '4';
}
else
if (strcmp(a,"ln")==0)
{
return '5';
}
else
if (strcmp(a,"lon")==0)
{
return '6';
}
else
if (strcmp(a,"sign")==0)
{
return '7';
}
else
if (strcmp(a,"exp")==0)
{
return '8';
}
}

char* PostWrite::TakeFunc(char a)
{
if (a=='1')
{
return "cos\0";
}
else
if (a=='2')
{
return "sin\0";
}
else
if (a=='3')
{
return "tg\0";
}
else
if (a=='4')
{
return "ctg\0";
}
else
if (a=='5')
{
return "ln\0";
}
else
if (a=='6')
{
return "lon\0";
}
else
if (a=='7')
{
return "sign\0";
}
else
if (a=='8')
{
return "exp\0";
}
}


Описание класса совершенно не изменилось.Для примера использовать можно 10*a-b/2 ну или любое другое подобное выражение.
volvo
Очень похожая ошибка на то, что раньше описывалось в 19-м посте... Первое:
int main() // Стандарт С++ не позволяет функции main иметь тип void.
{
char* str;
char str9[100] = {0}; // Второе - инициализируй массив нулями, этого за тебя делать не должен никто
str=gets(str9);

Третье:
	/* после pассмотpения всего выpажения */
while(OPERS != NULL)
/* Пеpеписываем все опеpации из */
if (strchr(number, OPERS->c) != 0)
{
tmp2=TakeFunc(OPERS->c);
for (p=0; tmp2 && tmp2[p]!='\0';p++) // <--- !!! сначала надо убедиться, что tmp2 != NULL
{
outstring[i++]=tmp2[p];
}
outstring[i++]=' ';
Del(&OPERS);
}
и четвертое: компилятор был обязан предупредить тебя, что функция может НЕ возвращать значение. Меня компилятор предупредил ТРИЖДЫ (в трех разных функциях). Обращай внимание на эти предупреждения, иначе за их игнорирование можно очень дорого заплатить потом, при отладке и/или добавлении функционала.
Krjuger
Мне компилятор не выдал ниодной ошибки, ниодного предупреждения вообще,если не повериш на слово, могу скрин выложить..по поводу первого...этот зверски корявый ввод был лиш для того чтобы отладить данную часть программы,для меня важным было лиш то чтобы класс выполнял свою задачу.
Цитата
сначала надо убедиться, что tmp2 != NULL

А не лучше ли сделать чтобы TakeFunc если функция не найдена просто бы возвращало значение (OPERS->c),тобиш изменить ее вот так

char* PostWrite::TakeFunc(char a)
{
if (a=='1')
{
return "cos\0";
}
else
if (a=='2')
{
return "sin\0";
}
else
if (a=='3')
{
return "tg\0";
}
else
if (a=='4')
{
return "ctg\0";
}
else
if (a=='5')
{
return "ln\0";
}
else
if (a=='6')
{
return "lon\0";
}
else
if (a=='7')
{
return "sign\0";
}
else
if (a=='8')
{
return "exp\0";
}
else
return &a;
}


Однако,Теперь там в конце появились доселе неизвестные элементы,хотя зацикливания уже нет,в результате спасло,как раз то что ты сделал ранее.

if (strchr(number, a[k]) != 0)
/* пеpеписываем её в выходную стpоку */
{
while (strchr(number, a[k]) != 0 && a[k] != '\0')
{
outstring[i++]=a[k];
k=k+1;
}
outstring[i++]=' ';
if (a[k] == '\0') continue;//<----вот длягодаря этому все нормально вроде стало)



Да,еще я не могу найти где надо поставить пробел,потому что при примере a*10-b/2 получается результат "a 10 * b 2 /-" между делить и минусом отсутствует пробел,хотя он там должен быть.
volvo
Цитата
Мне компилятор не выдал ниодной ошибки, ниодного предупреждения вообще,если не повериш на слово, могу скрин выложить..
Скрин ничего не решает, все зависит от настроек среды и компилятора, я тоже могу отключить все предупреждения, и меня перестанут предупреждать... Однако я предпочитаю в опциях установить отображение всех Warning-ов, и пускай компилятор выявляет все подозрительные с его точки зрения места в программе.

Цитата
Да,еще я не могу найти где надо поставить пробел,потому что при примере a*10-b/2 получается результат "a 10 * b 2 /-" между делить и минусом отсутствует пробел,хотя он там должен быть.
Еще бы, с таким форматированием текста, ты что-нибудь мог найти...
	/* после pассмотpения всего выpажения */
while(OPERS != NULL)
/* Пеpеписываем все опеpации из */
if (strchr(number, OPERS->c) != 0)
{
tmp2=TakeFunc(OPERS->c);
for (p=0; tmp2 && tmp2[p]!='\0';p++)
{
outstring[i++]=tmp2[p];
}
outstring[i++]=' ';
Del(&OPERS);
}
else
{ // У тебя вот этих скобок не было, пробелы не ставились...
outstring[i++]=Del(&OPERS);
outstring[i++]=' ';
}
/* стека в выходную стpоку */
outstring[i]='\0';

/* и печатаем её */
printf("\n %s \n", outstring);
Это текстовая версия — только основной контент. Для просмотра полной версии этой страницы, пожалуйста, нажмите сюда.