Kalkulator z kolejnością wywoływania działań

0
#include <stdio.h>
#include <stdlib.h>

#define N 5

void get_num(float *num);
char get_char();
float divide(float a, float b);


int main()
{
    float wynik,a;
    float toadd=0.0;
    float tmp_help;
    int last_plus=0, last_minus=0;
    char z;
    char last_char;
    get_num(&wynik);
    int i=1;
    do
    {
        z = get_char();

        if(z!='=')
        {
            get_num(&a);
            i++;
        }

            switch(z)
            {
            case '+':
                if(last_char=='*' || last_char=='/')
                {
                    wynik += toadd;
//                    if(last_minus)
//                        wynik = -wynik;
                    toadd=0;
                }

                toadd += wynik;
                wynik=a;
                last_plus =1;
                last_minus=0;

                break;
            case '-':
                 if(last_char=='*' || last_char=='/')
                {
                    wynik += toadd;
//                    if(last_minus)
//                        wynik = -wynik;
                    toadd=0;
                }
                toadd += -wynik;
                wynik=-a;
                last_plus =0;
                last_minus=1;
                break;
            case '*':
                wynik*=a;


                break;
            case '/':
                wynik = divide(wynik,a);
                break;
            case '=':
                    tmp_help = wynik;
                    wynik += toadd;



                //toadd=0;
                break;

            default:
                if(z!='=')
                puts("Bledny znak");
            }
       // }
         last_char = z;

    }while((z!='=') && (i<N));

    if(last_char=='+')
        wynik+=toadd;
    else if(last_char=='-')
        wynik+=toadd;

    printf("Wynik przed: %f\n",tmp_help);
    printf("Wynik: %lf",wynik);
    printf("\nToadd: %f",toadd);



    return 0;
}


void get_num(float *num)
{
    printf("Podaj liczbe:\n");
    scanf("%f",num);
}
char get_char()
{
    char ch;
    printf("Podaj znak:\n");
    scanf(" %c",&ch);
    return ch;

}

float divide(float a, float b)
{
    if(a==0.0)
        puts("Nie dziel przez 0");
    else
        return(a/b);
}

Mam mały problem z kalkulatorem konsolowym pisanym w C. Ma on wyświetlać odpowiednio wynik po wpisaniu "=" bądź wprowadzeniu 5 liczb. To jak i inne rzeczy zrobione. Problem jest jednak z kolejnością wywoływania działań. Działa to już dla np. 2+22 lub 2+332 ale dla -2-33+6433-2 już niestety nie.

Wiem, że kod pewnie jest chaotyczny ale testowałem tutaj dużo i część wychodziła jednak nie do końca.

Z góry dziękuje za pomoc.

0

Poczytaj o ONP, jeśli interesuje Cię kolejność operatorów.

0

Nie dziwne, że Ci to nie działa, skoro Twoja funkcja divide jest taka biedna. Zastanów się jak takiemu, na przykład, ciągowi znaków:
((2 + 3) / (5 - 1)),
nadać znaczenie (wartość). Przeanalizuj sobie ten algorytm:
https://stackoverflow.com/questions/13421424/how-to-evaluate-an-infix-expression-in-just-one-scan-using-stacks#16068554

0

Wiem że nie C tylko C++, może coś Ci pomoże (proszę nie gańcie mnie za ten kod, to jest kod z moich początków przygody z programowaniem ;), zdaję sobie sprawę że jego jakość jest marna)

plik .h

#pragma once
#include <string>
#include <vector>

void sprawdzanie(std::string &w);

std::vector<std::string> dzielenie(std::string w);

std::vector<std::string> konw(std::vector<std::string> wek);

double obliczanie(std::vector<std::string> w);

void wyswietl(std::vector<std::string>we);

plik .cpp

#include "ONP.h"
#include <string>
#include <iostream>
#include <vector>
#include <stack>
#include <cstdlib>
#include <map>
#include <math.h>

void sprawdzanie(std::string &w) {
	bool poprawnosc = true;
	for (int i = 0; i < w.size(); i++) {
		if ((w[i] == '.' || w[i] == ',') && (static_cast<int>(w[i - 1]) >= 48 && static_cast<int>(w[i] - 1) <= 57) && (static_cast<int>(w[i + 1]) >= 48 && static_cast<int>(w[i + 1]) <= 57)) {
			if (w[i] == ',') {
				w.erase(i, 1);
				w.insert(i, ".");
			}
		}
	}
}

std::vector<std::string> dzielenie(std::string w) {
	std::string czesc; //zmienna pomocnicza(najpotrzebniejsza w while) ma przede wszystkim przechowywa� liczb�
	std::vector<std::string> gotowe; //przechowywanie podzielonych danych wejsciowych
	int k; //zmienna pomicnicza (osobny licznik do while, po wyjsciu z while i=k)
	for (int i = 0; i < w.size(); i++) { //przejrzenie wszystkich elementow string
		if (static_cast<int>(w[i]) >= 48 && static_cast<int>(w[i]) <= 57 || static_cast<int>(w[i] == 46)) {
			k = i;
			czesc.clear(); //czyszczenie
			while ((static_cast<int>(w[k]) >= 48 && static_cast<int>(w[k]) <= 57) || (static_cast<int>(w[k]) == 46)) {
				//	std::clog << w[k] << " ";
				czesc += w[k];
				k++;
			}
			k--;
			gotowe.push_back(czesc);
			i = k;
			czesc.clear();
		}
		else {
			czesc.clear();
			czesc += w[i];
			gotowe.push_back(czesc);
			czesc.clear();
		}
	}
	return gotowe;
}

std::vector<std::string> konw(std::vector<std::string> wek) {
	//priorytety
	std::map<std::string, int> priorytety;
	priorytety["("] = 0;
	priorytety["+"] = 1;
	priorytety["-"] = 1;
	priorytety["*"] = 2;
	priorytety["/"] = 2;
	priorytety["^"] = 3;
	std::vector<std::string> wyjscie;
	std::stack<std::string> stos;
	std::string tek;
	for (unsigned int i = 0; i < wek.size(); i++) {
		tek.clear();
		tek += wek[i];
		//jest liczb�
		if (atoi(tek.c_str()) != 0 || tek == "0") {
			wyjscie.push_back(tek);
		}
		else {//nie jest liczb�
			if (tek == "(") {
				stos.push(tek);
			}
			if (tek == ")") {//je�li jest prawym nawiasem wszstko do ( wy�lij na wyj�cie a ( zrzu�
				while (stos.top() != "(") {
					wyjscie.push_back(stos.top());
					stos.pop();
				}
				stos.pop();
			}
			//jest operatorem
			if (tek == "+" || tek == "-" || tek == "*" || tek == "*" || tek == "/" || tek == "^") {
				if (stos.empty() == true) {
					stos.push(tek);
				}//stos nie jest pusty
				else {
					if (priorytety[tek] > priorytety[stos.top()]) {
						stos.push(tek);
					}
					//if (priorytety[tek] <= priorytety[stos.top()]) 
					else {
						while (stos.empty() == false && priorytety[tek] <= priorytety[stos.top()])
						{
							wyjscie.push_back(stos.top());
							stos.pop();
						}
						stos.push(tek);
					}
				}
			}
		}
	}
	while (!stos.empty())
	{
		wyjscie.push_back(stos.top());
		stos.pop();
	}
	return wyjscie;
}

double obliczanie(std::vector<std::string> w) {
	std::map<std::string, int> priorytety; //potrzebne do wybrania odpowiedniej opcji p�niej 
	priorytety["+"] = 1;
	priorytety["-"] = 2;
	priorytety["*"] = 3;
	priorytety["/"] = 4;
	priorytety["^"] = 5;
	std::stack<double> stos; //wykonywane operacje na nim
	double a, b; //zmienne pomocnicze do zapami�tywania wartosci ze stosu
	for (unsigned int i = 0; i < w.size(); i++) {
		//jest liczb�

		if (w[i] != "+" && w[i] != "-" && w[i] != "*" && w[i] != "*" && w[i] != "/" & w[i] != "^") {
			stos.push(std::stod(w[i]));
		}
		else { //nie jest liczb�
			a = stos.top(); //zapami�tywanie i �ci�ganie ze stosu liczb
			stos.pop();
			b = stos.top();
			stos.pop();
			switch (priorytety[w[i]]) //wykonywanie odpowiedniej akcji w zale�no�ci od operatora
			{
			case 1:

				stos.push(b + a);

				break;
			case 2:
				stos.push(b - a);
				break;
			case 3:
				stos.push(b*a);
				break;
			case 4:
				stos.push(b / a);
				break;
			case 5:
				stos.push(pow(b, a));
				break;
			}
		}
	}
	return stos.top();
}

void wyswietl(std::vector<std::string>we) {
	for (auto i = 0; i <we.size(); i++)
	{
		std::clog << we[i] << " ";
	}
}
1

Nie ganię Cię za kod, ale w ten sposób - dorzucając więcej spaghetti:), nie Pomożesz.

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