ONP konwersja i obliczanie

0

Mam programik, który konwertuje i/lub oblicza wyrażenia w ONP. I niby wszystko działa ale ma pewne wady, których nie umiem rozwiązać :

  1. Można wpisać liczby tylko od 0 do 9 (np 10 czyta jako 1 i 0 i brakuje wtedy operatorów)
  2. Nie obsługuje spacji (po wprowadzeniu 1 + 1 program się wiesza, 1+1 jest ok)

Będę mega wdzięczny za pomoc

 #include<iostream>
#include<cstdio>
#include<string>
#include<cstdlib>
#include<cmath>
#include<istream>

using namespace std;

const int maxlength = 100;
typedef int elementtype, position;
bool operatory(char o)
{
return o == '+' || o == '-' || o == '*' || o == '/' || o == '^' || o == '~';
}

int wagi(char w)
{
    if(w == '^')
        return 3;
    else if(w == '*' || w == '/')
        return 2;
    else if(w == '~' || w == '-' || w == '+')
        return 1;
    else
        return 0;
}

class Stos
{
int S[maxlength];
position top;

public:
	Stos()
	{
		top = -1;
	}
	void PUSH(elementtype x)
	{
		S[++top] = x;
	}
	void POP()
	{
		if((EMPTY() == false))
        S[top--];
	}
	bool EMPTY()
	{
		if(top == -1)
			return true;
		else
			return false;
	}
	elementtype TOP()
	{
		if(EMPTY() == false)
		return S[top];
	}
	void MAKENULL()
	{
		while(top != -1)
            S[top--];
	}
	elementtype pokazTOP()
	{
	    if(EMPTY() == false)
            cout<<(int)S[top]<<endl;
        else
            cout<<"Stos pusty"<<endl;
	}
};


void konwersja(const string wyrazenie, char rezultat[], int dlugosc)
{
Stos s;
int r = 0;
int i = 0;

while(i < dlugosc)
{
    char kursor = wyrazenie.at(i);
    if(kursor == '(' || kursor == '~')
    {
        s.PUSH(kursor);
        i++;
        continue;
    }
    if(kursor == ')')
    {
        while(s.EMPTY() == false && s.TOP() != '(')
        {
            rezultat[r++] = s.TOP();
            s.POP();
        }
       if(s.EMPTY() == false)
            s.POP();
   i++;
    continue;
    }
    int waga = wagi(kursor);
    if(waga == 0)
        rezultat[r++] = kursor;
    else{
        if(s.EMPTY())
            s.PUSH(kursor);
        else{
            while(s.EMPTY() == false && s.TOP() != '(' && waga <= wagi(s.TOP()))
            {
                rezultat[r++] = s.TOP();
                s.POP();
            }
            s.PUSH(kursor);
            }
        }
        i++;
    }
    while(s.EMPTY() == false)
    {
        rezultat[r++] = s.TOP();
        s.POP();
    }
rezultat[r] = 0;
}


obliczanie(const string &wyrazenie)
{
Stos s;
int dlugosc = wyrazenie.size();
int a,b, temp, wynik;
b = -(maxlength) + 1;
a = -(maxlength) + 1;

for(int i = 0; i <= dlugosc; i++)
{
    if(wyrazenie[i] == '=')
        break;

    if(operatory(wyrazenie[i]))
    {
        b = (int)s.TOP() - (maxlength/2 - 2);
        s.POP();
        if(wyrazenie[i] != '~')
        {
            a = (int)s.TOP() - (maxlength/2 - 2);
            s.POP();
        }
        switch(wyrazenie[i])
        {
            case '*': temp = b*a; break;
            case '/': temp = a/b; break;
            case '+': temp = b+a; break;
            case '-': temp = a-b; break;
            case '^': temp = pow(a,b); break;
            case '~': temp = b * (-1); break;
        }
        s.PUSH((char)(temp + (maxlength/2 - 2)));
        a = b = -(maxlength) + 1;
        wynik = temp;
    }
    else
        s.PUSH(wyrazenie[i]);
}
return wynik;
}

void bezSpacji(const string &tekst, string &tekst2)
{
    int i,j = 0;
    tekst2 = "";
    while(j == 0)
    {
    for(i = 0; i < tekst.size(); i++)
    {
        if(tekst.at(i) == ' ')
            j = 1;
        else
            tekst2 = tekst2 + tekst.at(i);
    }
    }
    //return tekst2;
}



int main()
{
char wynik[maxlength];
int wybor, dlugosc;
string znak, dane, wyrazenie, wyrazenie1;
do
{
system("cls");

cout<<"|------------ MENU ------------|"<<endl;
cout<<" Wybierz: \n"<<endl;
cout<<"     1. Wyrazenie w ONP."<<endl;
cout<<"     2. Konwersja do ONP."<<endl;
cout<<"     3. Konwersja i obliczenie."<<endl;
cout<<"     4. Zamknij program"<<endl;

cin>>wybor;
switch(wybor)
{
case 1:
    cout<<"\n\n************  Wyrazenie w ONP.  ************\n"<<endl;
    cout<<"Podaj wyrazenie: "<<endl;
    cout<<"musi byc zakonczone '='"<<endl;
    //getline(cin, dane);
    cin>>dane;
    dlugosc = (int)dane.size();
    cout<<"     Wynik: "<<obliczanie(dane)<<endl;
    getchar();
    break;
case 2:
    cout<<"\n\n************  Konwersja do ONP.  ************"<<endl;
    cout<<"Podaj wyrazenie: "<<endl;
    cin>>dane;
    //getline(cin, dane);
    //getchar();
    //bezSpacji(wyrazenie, wyrazenie1);
    //wyrazenie1 = dane;
    dlugosc = (int)dane.size();
    wynik[dlugosc];
    konwersja(dane, wynik, dlugosc);
    cout<<"     Wyrazenie w ONP: "<<wynik<<endl;
    getchar();
    break;
case 3:
    cout<<"\n\n************  Konwersja i obliczenie  ************"<<endl;
    cout<<"Podaj wyrazenie: "<<endl;
    cin>>dane;
    //getline(cin, dane);
    //getchar();
    dlugosc = (int)dane.size();
    wynik[dlugosc];
    konwersja(dane, wynik, dlugosc);
    cout<<"     Wyrazenie w ONP: "<<wynik<<endl;
    cout<<""<<endl;
    cout<<"     Wynik: "<<obliczanie(wynik)<<endl;
    getchar();
    break;
case 4:
    exit(0);
default:
cout<<"Zly numer."<<endl;
}
cout<<"\n Zakonczyc? (t)"<<endl;
cin>>znak;

}
while(znak != "t");
system("cls");
return 0;
}

0

To zignoruj spację.

0

Pytanie tylko jak? W konwersji dodanie warunku

 if(kursor == ' ' ) i++;

nic nie daje.

0

A jakby pokombinować z cin.ignore ?

0

albo getline()

0

Co do spacji: po prostu usuń je z wyrażenia:

std::string expr = "1 + 1 - 9 +10";
	
expr.erase( std::remove(expr.begin(), expr.end(), ' '), expr.end() );

Funkcję operatory możesz nieco uprościć:

bool operatory(char o) { return strchr("+-*/^~", o) != 0; }

Odnośnie obsługi liczb wielocyfrowych, to tak możesz to zrobić:

int obliczanie(const string &wyrazenie)
{
	...
	 
	for(int i = 0; i < dlugosc; ++i)
	{
		if(wyrazenie[i] == '=') break;

		if(operatory(wyrazenie[i]))
		{
			...
		}
		else 
		{
			char* p_end = nullptr;
			s.PUSH(  strtol( &wyrazenie[i], &p_end, 10 ) );
			size_t diff = p_end - &wyrazenie[i];
			i += diff;
			if(diff > 0) --i;			
		}
	}
	
	return wynik;
}
0

Jak dodam tą metodę z usuwaniem spacji to dostaję

 error: cannot convert ...

opcja z obsługą liczb wielocyfrowych daje niepoprawne wyniki

0

Jak podajesz błąd, to podaj pełną treść, a nie tyle, że nie wiadomo, o co chodzi.

opcja z obsługą liczb wielocyfrowych daje niepoprawne wyniki

Pisząc ten kod, założyłem, że &wyrazenie[i] w bloku else wskazuje na początek liczby. Jeśli tak jest, nie powinno być problemu. W przeciwnym wypadku użyj debuggera...

Dodaj może jeszcze jeden warunek do pętli:

for(int i = 0; i < dlugosc; i++)
{
	if(wyrazenie[i] == '=') break;

	if(wyrazenie[i] == ' ') continue; //<--- pomija spacje

	if(operatory(wyrazenie[i])) { ... }
	...
0
 cannot convert 'std::basic_string<char>::iterator {aka __gnu_cxx::__normal_iterator<char*, std::basic_string<char> >}' to 'const char*' for argument '1' to 'int remove(const char*)'
     dane.erase(remove(dane.begin(), dane.end(), ' '), dane.end() );
0

Dodaj nagłówek <algorithm>.

p.s. to usuwanie spacji ma oczywiście sens tylko w przypadku notacji konwencjonalnej.

0
0x666 napisał(a):

Co do spacji: po prostu usuń je z wyrażenia:

std::string expr = "1 + 1 - 9 +10";
	
expr.erase( std::remove(expr.begin(), expr.end(), ' '), expr.end() );

Funkcję operatory możesz nieco uprościć:

bool operatory(char o) { return strchr("+-*/^~", o) != 0; }

Odnośnie obsługi liczb wielocyfrowych, to tak możesz to zrobić:

int obliczanie(const string &wyrazenie)
{
	...
	 
	for(int i = 0; i < dlugosc; ++i)
	{
		if(wyrazenie[i] == '=') break;

		if(operatory(wyrazenie[i]))
		{
			...
		}
		else 
		{
			char* p_end = nullptr;
			s.PUSH(  strtol( &wyrazenie[i], &p_end, 10 ) );
			size_t diff = p_end - &wyrazenie[i];
			i += diff;
			if(diff > 0) --i;			
		}
	}
	
	return wynik;
}

nie wiem dlaczego ale usuwanie spacji zawiesza program

getline(cin ,dane); //powinno wczytywać linijkę wraz ze spacjami 
 dane.erase(remove(dane.begin(), dane.end(), ' '), dane.end() );

czy jest jakiś inny sposób na obsługę liczb wielocyfrowych ?

0

Na pewno usuwanie spacji zawiesza? Pytam, bo w tych dwóch linijkach nie ma miejsca na błąd powodujący zawieszenie.

Czy zastosowałeś wszystkie moje uwagi odnośnie funkcji obliczanie?

p.s. Nie cytuj całych postów.

0
 getline(cin, dane);
    getchar();
    dane.erase(remove(dane.begin(), dane.end(), ' '), dane.end() );
    dlugosc = (int)dane.size();
    wynik[dlugosc];
    konwersja(dane, wynik, dlugosc);
    cout<<"     Wyrazenie w ONP: "<<wynik<<endl;
    getchar();
    break;

po wprowadzeniu wyrażenia np. : 2 + 2
pojawia się znowu prośba o wprowadzenie wyrażenia a jeśli wpiszę 2+2 program znowu przenosi do "Menu"

0

Wywal te wywołania getchar, bo są zbędne. Zrób tak:

(cin >> wybor).ignore(666, '\n');
switch(wybor)
{
   ...
}
0
error: case label '1' not within a switch statement 

i tak dla wszystkich case

0

No i? Coś źle przepisałeś/poprawiłeś, i tyle mogę Ci powiedzieć.

0

Sorry mój błąd. Więc sprawa ze spacją rozwiązana. Dzięki :)
Teraz tylko obsługa liczb więcej niż jednocyfrowych

0

Zadam jeszcze raz pytanie: czy zastosowałeś wszystkie moje uwagi odnośnie funkcji obliczanie?

0

Tak i np 3+3 wychodzi -63; 2+2 -74

0

Hmm, wydawało mi się, że obliczanie liczy wyrażenia w notacji ONP, a nie konwencjonalnej. Spróbuj z takim wyrażeniem: *10 20 + 2 * *, powinno wyjść 60.

0
 double obliczanie(const string &wyrazenie)
{
Stos s;
int dlugosc = wyrazenie.size();
int a,b, temp, wynik;
b = -(maxlength) + 1;
a = -(maxlength) + 1;

for(int i = 0; i <= dlugosc; i++)
{
    if(wyrazenie[i] == '=')
        break;

    if(wyrazenie[i] == ' ')
        continue;

    if(operatory(wyrazenie[i]))
    {
        b = (int)s.TOP() - (maxlength/2 - 2);
        s.POP();
        if(wyrazenie[i] != '~')
        {
            a = (int)s.TOP() - (maxlength/2 - 2);
            s.POP();
        }
        switch(wyrazenie[i])
        {
            case '*': temp = b*a; break;
            case '/': temp = a/b; break;
            case '+': temp = b+a; break;
            case '-': temp = a-b; break;
            case '^': temp = pow(a,b); break;
            case '~': temp = b * (-1); break;
        }
        s.PUSH((char)(temp + (maxlength/2 - 2)));
        a = b = -(maxlength) + 1;
        wynik = temp;
    }
   /*else
        s.PUSH(wyrazenie[i]);*/
    else
    {
        char* p_end = nullptr;
        s.PUSH(strtol(&wyrazenie[i], &p_end, 10));
        size_t diff = p_end - &wyrazenie[i];
        i = i + diff;
        if(diff > 0)
            -- i;
    }

}
return wynik;
}

0
int obliczanie(const string &wyrazenie)
{
	Stos s;
	int a,b, temp, wynik;

	for(int i = 0; i < wyrazenie.size(); ++i)
	{
		if(wyrazenie[i] == '=')	break;
		if(wyrazenie[i] == ' ') continue;
		if(operatory(wyrazenie[i]))
		{
			b = s.TOP() ;
			s.POP();
			
			if(wyrazenie[i] != '~')
			{
				a = s.TOP();
				s.POP();
			}
			
			switch(wyrazenie[i])
			{
			case '*': temp = b * a; break;
			case '/': temp = a / b; break;
			case '+': temp = b + a; break;
			case '-': temp = a - b; break;
			case '^': temp = pow(a, b); break;
			case '~': temp = b * (-1); break;
			}
			
			s.PUSH(temp);
			wynik = temp;
		}
		else
		{
			char* p_end = nullptr;
			s.PUSH(strtol(&wyrazenie[i], &p_end, 10));
			size_t diff = p_end - &wyrazenie[i];
			i = i + diff;
			if(diff > 0) --i;
		}
	}
	
	return wynik;
}

Nie wiem, o co chodzi z tym maxlength, więc pousuwałem to. Spróbuj teraz...

1 użytkowników online, w tym zalogowanych: 0, gości: 1