В общем надо разработать класс,который будет переводить из обычной записи в постфиксную.
#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;
}
}
Ты для начала описание класса заверши (точку с запятой поставь), а потом описывай методы:
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);
}; // Вот тут !!
Мда ппц косяк,не заметил(((
Ладно исправил,потом кое что изменил.добавил возможный пример
#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 сам инициализировался? Ты выделяешь память под PRT вообще-то... PTR остается неинициализированным, вот тебе и ошибка доступа.
Не торопись, когда программу пишешь, программирование - не Formula I.
Мда моя безграмотность моя проблема.Ладно все эти ошибки я исправил,все стало нормально работать,вот только как лучше всего будет внести реализацию функций синуса косинуса и тд в эту программу?Я предполагаю создать какую нибудь буферную переменную и скидывать туда.
В общем попробовал добавить добавить поддержку функций,но моя попытка обернулась крахом,нужна помощ.
#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();
}
elseс неинициализированнй outstring. Тут программа вылетает. Это первое. Второе: если даже инициализировать строку:
strcat(outstring, tmp);
char outstring[80] = {0};, то программа правильно работать не станет. Она, конечно, теперь не вылетает, но результат выдает бредовый. Ищи ошибку в алгоритме.
Насчет экспоненты,да действительно она не будет присутстовавать,потому что для проверки на принадлежность в моем варианте необходимы пробелы с двух сторон а для экспоненты пробела после функции попросту нет,исправил.Над остальным пока думаю.
Чего думать? Ты в одном месте заполняешь строку outstring через strcat (естественно, i при этом не изменяется), а в другом - через прямую запись: outstring[ i ] = ..., при этом то, что раньше было записано через strcat - перезаписывается. Вот тебе и источник проблем.
Теперь о функциях: нельзя так делать, как ты делаешь. Что у тебя происходит? Ты ПОБУКВЕННО запихиваешь название функции в стек, но он предназначен не для этого. Либо ставь каждой функции в соответствие какой-то номер (индекс, как угодно), и заталкивай его в стек, либо переписывай struct stek так, чтобы там хранился не один символ, а столько, сколько может понадобится для названия самой длинной функции. Но это потребует переделок программы.
Еще раз: программа СИЛЬНО упростится, если вместо твоего самописного стека использовать std::stack<std::string>, подумай над этим...
Я бы с радостью,но со структурой и возможностями std::stack<std::string> я не знаком напроч,тогда раз лучше будет пойду ка я почитаю)
В общем я решил доделать то что есть,я прекрасно поимаю,что то, что я пишу далеко от вершины грамотности и ужасно с точки зрения оптимизации,но других вариантов я пока что не вижу,потому что реализовывать через 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();
switch(*a)и так далее - это ты сам придумал? Так делать нельзя:
{
case 'cos':
В общем я исправил все что надо и теперь с функциями более менее работает.Вот код
#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();
}
Раз:
{, два:
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]);
}
{. Понимаешь в чем дело? Ты дописываешь символ в строку outstring, так ее после этого надо закрыть нулевым символом? Надо. Вот и закрываем. Теперь ошибки исчезли... Может, где еще проявятся, пройди по всей программе, там где ты делаешь outstring[i++] = чему_то, добавляй outstring[ i ] = '\0';
/* все знаки опе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++;
Тогда чисто теоретический вопрос почему появились то проблемы со стеком,если бы я просто переменную d не смог бы записать,ну или коряво записывал бы, это понятно,тут то,что ты написал абсолютно верно,но почему же в момент записи моего значения в выходную строку портился стек.
С большими выражениями теперь более менее нормально, но ошибка появилась там,где ее не ждали.при варианте a+b*c получается ошибка в том что основной цикл переходит на 7 элемент,который забит мусором в результате цикл не прерывается ,а зацикливается.
a+b*c=
abc*+
У меня MVS 2008,а увидел что портится просто в дебагере пошагово просматривая вкладку Locals.Если ввести = то у меня тоже нормально,зато вот если просто ввести выражение то почему то не получается
Добавлено через 11 мин.
Вот что именно происходит:
До
После
Красный свидетельствует о том что на данной операции с "красными" переменными произведены изменения.
Так. Проблема - в том, что 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)
Я уже затюкал наверно с этой задачей,но опять нашлась ошибка.Припроходе по строке,если последнее действие умножение или деление,то происходит вылет за пределы строки и я из цикла не выхожу.
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";
}
}
Очень похожая ошибка на то, что раньше описывалось в 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);
}
Мне компилятор не выдал ниодной ошибки, ниодного предупреждения вообще,если не повериш на слово, могу скрин выложить..по поводу первого...этот зверски корявый ввод был лиш для того чтобы отладить данную часть программы,для меня важным было лиш то чтобы класс выполнял свою задачу.
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;//<----вот длягодаря этому все нормально вроде стало)
/* после 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);