obliczanie wyrażeń algebraicznych.

0

założenie jest takie, że program ma obliczać wyrażenie podane przez użytkownika. Jednak jest pewne utrudnienie, w programie nie wolno używać pętli ani zmiennych globalnych i nie wiem jak to ominąć. Program liczy kolejność wprowadzania a nie kolejność wykonywania działań, np 2+2*2=8.
Napisz program, który pobierze od użytkownika wyrażenie arytmetyczne (nie dłuższe niż 200 znaków, składające się z liczb nieujemnych oraz operatorów arytmetycznych +, -, / i *), a następnie korzystając z przygotowanych wcześniej funkcji obliczy jego wartość i wypisze ją w konsoli z dokładnością dwóch miejsc po przecinku.
W przypadku błędnych danych wejściowych program powinien wyświetlić komunikat Incorrect input i zakończyć działanie z kodem błędu 1.

tak brzmi polecenie prosiłbym o pomoc w sprawie funkcji calculate jest jeszcze druga do zrobienia ale z tamtą powinienem sobie poradzić :)

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

int calculate(const char* expr, float *result);

int main()
{
    char tab[201];
    float wyn = 0;
    int spr = 0;
    printf("Podaj wyrazenie\n");
    spr = scanf("%200s", tab);
    calculate(tab, &wyn);
    printf("%.2f", wyn);


    return 0;
}

int calculate(const char* expr, float *result)
{
    if (expr == NULL || result == NULL)
        return 0;
    char *znak = strpbrk(expr, "+-/*");


    switch (*znak)
    {
        case '+':
        {
            *result += atoi(expr);
            break;
        }
        case '-':
        {
            *result -= atoi(expr);
            break;
        }
        case '/':
        {
            *result /= atoi(expr);
            if(atoi(expr)==0)
            {
                printf("Dzielenie przez 0");
                return 0;
            }
            break;
        }
        case '*':
        {
            *result *= atoi(expr);
            break;
        }
        default:
            printf("Nie ma takiego dzialnia");

    }
    return 1;
}

1

Szedłbym w rekurencję bądź tricki z wykorzystaniem function pointers :-)

0

Przepisz sobie to do C++ i pozamiatane:)

0

próbuje wrzucić tu rekurencje to wywala mi sigsegv

int calculate(const char* expr, float *result)
{
    if (expr == NULL || result == NULL)
        return 0;
    char *znak = strpbrk(expr, "+-/*");


    switch (*znak)
    {
        case '+':
        {
            *result += atoi(expr);
            break;
        }
        case '-':
        {
            *result -= atoi(expr);
            break;
        }
        case '/':
        {
            *result /= atoi(expr);
            if(atoi(expr)==0)
            {
                printf("Dzielenie przez 0");
                return 0;
            }
            break;
        }
        case '*':
        {
            *result *= atoi(expr);
            break;
        }
        default:
            printf("Nie ma takiego dzialnia");

    }
    calculate(znak+1,result);
    return 1;
}

wydaje mi się że muszę sprawdzić kiedy ciąg się kończy za pomocą terminatora ale nie wiem gdzie go wrzucić

0

Instrukcja goto na ratunek.
https://www.tutorialspoint.com/cprogramming/c_goto_statement.htm

Ogólnie to chyba nie zaleca się używania tej instrukcji, ale jak pętli nie wolno, to raczej ciężko będzie to zrobić szybciej w inny sposób.

0

funkcja goto wydaje się idealnym rozwiązaniem ale nie wiem dalej jak się poruszać bo tych stringach żeby całe wyrażenie sprawdzić
goto chyba dobrze zastosowałem

int calculate(const char* expr, float *result)
{
    if (expr == NULL || result == NULL)
        return 0;
    char *znak = strpbrk(expr, "+-/*");




    onemore: switch (*znak)
    {
        case '+':
        {
            *result += atoi(expr);
            break;
        }
        case '-':
        {
            *result -= atoi(expr);
            break;
        }
        case '/':
        {
            *result /= atoi(expr);
            if(atoi(expr)==0)
            {
                printf("Dzielenie przez 0");
                return 0;
            }
            break;
        }
        case '*':
        {
            *result *= atoi(expr);
            break;
        }
        default:
            printf("Nie ma takiego dzialnia\n");
            break;

    }

    if (*znak != '\0') {
        znak++;
        znak = strpbrk(znak,"+-/*");
        goto onemore;
    }
    }

example pls ;c

0

Gdyby założyć, że na wejściu jest lista (np.: ["2", "+", "2"]) reprezentująca poprawne wyrażenie arytmetyczne, które Opisałeś, to, potrzebujemy jeszcze funkcji:
length, head(pierwszy element), rest(reszta, poza pierwszym, lista); i wtedy, dość kulawo, ale czysto rekurencyjnie, pseudokod (Python):

def math(a, op, b):
	if op == "+": 
		return int(a) + int(b)
	if op == "-":
		return int(a) - int(b)

def evaluate(expr_list):
	if length(expr_list) == 1:
		return head(expr_list)
	else: 
		return math(head(expr_list), head(rest(expr_list)), 
			   evaluate(rest(rest(expr_list))))
0

**ja raczej miałem na myśli coś takiego że mamy 2+2*2-2 i wyzerowane result to program pobiera liczbe do 1 znaku i dodaje do result *result=atoi(expr); potem sprawdza znak char *znak = strpbrk(expr, "+-/*"); i wykonuje operacje zależną od pobranego znaku z liczbą od znaku pobranego wcześniej do kolejnego znaku niebędącego liczbą tak mi się wydaje działa funkcja atoi. Jednak nie potrafię sprawdzić gdzie moje wyrażenie się kończy. W stringach jest terminator (\0) ale jak sprawdzić gdzie on się znajduje.**

1
char *znak = strpbrk(expr, "+-/*");

onemore: switch (*znak)

strbrk() zwraca wskaźnik na pierwszy znaleziony char z podanej puli lub NULL gdy nie znajdzie. Dodaj obsługę tego drugiego przypadku (odpadnie przynajmniej jeden SIGSEGV).

Po tych liniach pomiędzy expr a znak masz lewą część wyrażenia. Ty traktujesz to jako prawą część. Przez to większość programu do przerobienia...

            *result /= atoi(expr);
            if(atoi(expr)==0)
            {
                printf("Dzielenie przez 0");
                return 0;
            }

Wykonujesz operację a potem sprawdzasz czy możesz ją wykonać?

0

No i dobra. Dziękuje dzięki Twoim uwagom dotarłem do celu :) trochę nieuwagi i trochę braku wiedzy i patrzcie jak pozornie proste zadanie może się skomplikować dobrze że mamy życzliwych ludzi :P
dzięki raz jeszcze wszystko działa jak należy :)

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