IPB
ЛогинПароль:

> Внимание!

1. Пользуйтесь тегами кода. - [code] ... [/code]
2. Точно указывайте язык, название и версию компилятора (интерпретатора).
3. Название темы должно быть информативным.
В описании темы указываем язык!!!

Наладить общение поможет, если вы подпишитесь по почте на новые темы в этом форуме.

2 страниц V  1 2 >  
 Ответить  Открыть новую тему 
> Преобразование в постфикстую запись
сообщение
Сообщение #1


Профи
****

Группа: Пользователи
Сообщений: 652
Пол: Мужской
Реальное имя: Алексей

Репутация: -  20  +


В общем надо разработать класс,который будет переводить из обычной записи в постфиксную.

#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)
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #2


Гость






Ты для начала описание класса заверши (точку с запятой поставь), а потом описывай методы:
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>, и используй...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #3


Профи
****

Группа: Пользователи
Сообщений: 652
Пол: Мужской
Реальное имя: Алексей

Репутация: -  20  +


Мда ппц косяк,не заметил(((
Ладно исправил,потом кое что изменил.добавил возможный пример

#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(добавление элемента в стек).ошибка что то типа нет доступа для записи по какомото там адресу
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #4


Гость






А ты что хотел, чтобы у тебя PTR сам инициализировался? Ты выделяешь память под PRT вообще-то... PTR остается неинициализированным, вот тебе и ошибка доступа.

Не торопись, когда программу пишешь, программирование - не Formula I.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #5


Профи
****

Группа: Пользователи
Сообщений: 652
Пол: Мужской
Реальное имя: Алексей

Репутация: -  20  +


Мда моя безграмотность моя проблема.Ладно все эти ошибки я исправил,все стало нормально работать,вот только как лучше всего будет внести реализацию функций синуса косинуса и тд в эту программу?Я предполагаю создать какую нибудь буферную переменную и скидывать туда.

Сообщение отредактировано: Krjuger -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #6


Профи
****

Группа: Пользователи
Сообщений: 652
Пол: Мужской
Реальное имя: Алексей

Репутация: -  20  +


В общем попробовал добавить добавить поддержку функций,но моя попытка обернулась крахом,нужна помощ.

#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)).Происходила ошибка записи на моменте когда первый знак "+" должен был быть помещен в стек.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #7


Гость






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

Третье: посмотри внимательно на свою строку func, и подумай, почему exp не будет определена как функция, даже если она присутствует во введенной пользователем строке?
 К началу страницы 
+ Ответить 
сообщение
Сообщение #8


Профи
****

Группа: Пользователи
Сообщений: 652
Пол: Мужской
Реальное имя: Алексей

Репутация: -  20  +


Насчет экспоненты,да действительно она не будет присутстовавать,потому что для проверки на принадлежность в моем варианте необходимы пробелы с двух сторон а для экспоненты пробела после функции попросту нет,исправил.Над остальным пока думаю.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #9


Гость






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

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

Еще раз: программа СИЛЬНО упростится, если вместо твоего самописного стека использовать std::stack<std::string>, подумай над этим...
 К началу страницы 
+ Ответить 
сообщение
Сообщение #10


Профи
****

Группа: Пользователи
Сообщений: 652
Пол: Мужской
Реальное имя: Алексей

Репутация: -  20  +


Я бы с радостью,но со структурой и возможностями std::stack<std::string> я не знаком напроч,тогда раз лучше будет пойду ка я почитаю)
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #11


Профи
****

Группа: Пользователи
Сообщений: 652
Пол: Мужской
Реальное имя: Алексей

Репутация: -  20  +


В общем я решил доделать то что есть,я прекрасно поимаю,что то, что я пишу далеко от вершины грамотности и ужасно с точки зрения оптимизации,но других вариантов я пока что не вижу,потому что реализовывать через 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();


Вроде как бы оно работает с функциями правильно,вот только я не могу понять почему когда я функцию заменяю числом и записываю его в стек,по идее вместо чесла туда должна будет записаться литера стоящая под соответствующим номером в аски коде,но почему при каждом вызове программы эта буква(символ) меняется
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #12


Гость






  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.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #13


Профи
****

Группа: Пользователи
Сообщений: 652
Пол: Мужской
Реальное имя: Алексей

Репутация: -  20  +


В общем я исправил все что надо и теперь с функциями более менее работает.Вот код

#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 туда уже не записывается в выходную строку и по неведомой причине портится стек.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #14


Гость






Раз:
		{
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 позиции? Вылет за границы строки.
 К началу страницы 
+ Ответить 
сообщение
Сообщение #15


Профи
****

Группа: Пользователи
Сообщений: 652
Пол: Мужской
Реальное имя: Алексей

Репутация: -  20  +


Тогда чисто теоретический вопрос почему появились то проблемы со стеком,если бы я просто переменную d не смог бы записать,ну или коряво записывал бы, это понятно,тут то,что ты написал абсолютно верно,но почему же в момент записи моего значения в выходную строку портился стек.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #16


Профи
****

Группа: Пользователи
Сообщений: 652
Пол: Мужской
Реальное имя: Алексей

Репутация: -  20  +


С большими выражениями теперь более менее нормально, но ошибка появилась там,где ее не ждали.при варианте a+b*c получается ошибка в том что основной цикл переходит на 7 элемент,который забит мусором в результате цикл не прерывается ,а зацикливается.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #17


Гость






Цитата
но почему же в момент записи моего значения в выходную строку портился стек.
А этого я тебе не говорил. Вот Билдер 2009, например, говорит:
Прикрепленное изображение
Где здесь видно порчу стека? Другой компилятор по-другому отреагирует на выполнение этой программы. Ты чем пользуешься?

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

abc*+

 К началу страницы 
+ Ответить 
сообщение
Сообщение #18


Профи
****

Группа: Пользователи
Сообщений: 652
Пол: Мужской
Реальное имя: Алексей

Репутация: -  20  +


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

Добавлено через 11 мин.
Вот что именно происходит:
До
Изображение
После
Изображение
Красный свидетельствует о том что на данной операции с "красными" переменными произведены изменения.

Сообщение отредактировано: Krjuger -
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 
сообщение
Сообщение #19


Гость






Так. Проблема - в том, что 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)


Теперь корректно отрабатывает и со знаком =, и без него... Тестируй
 К началу страницы 
+ Ответить 
сообщение
Сообщение #20


Профи
****

Группа: Пользователи
Сообщений: 652
Пол: Мужской
Реальное имя: Алексей

Репутация: -  20  +


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

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 ну или любое другое подобное выражение.
 Оффлайн  Профиль  PM 
 К началу страницы 
+ Ответить 

2 страниц V  1 2 >
 Ответить  Открыть новую тему 
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 





- Текстовая версия 6.05.2024 0:47
500Gb HDD, 6Gb RAM, 2 Cores, 7 EUR в месяц — такие хостинги правда бывают
Связь с администрацией: bu_gen в домене octagram.name