0

I made a program that evaluates expressions, for example

Enter text: 97+74/51-98-11+68-34-2-22+73/40+81/15+100

output :

105.36

If any wrong data is given a user gets a response Incorrect input

I am wondering if I could replace all my for loops to recursion, but I don't know how could I achieve that. Could anybody help ?

Any assistance would be much appreciated.

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

int my_atoi(const char* tab, int from, int to)
{
    int score = 0;
    int minus = 0;
    for (int i = from; i <= to; i++)
    {
        if (*(tab + i) == 10)
            break;

        if (*(tab + i) == 32)
            break;

        if (*(tab + i) == '-' && from == i)
        {
            minus = 1;
            continue;
        }
        if (*(tab + i) == '+' && i == from)
        {
            continue;
        }
        if (*(tab + i) > '9' || *(tab + i) < '0')
            break;
        else if (*(tab + i) >= '0' && *(tab + i) <= '9')
        {
            score *= 10;
            score += (*(tab + i) - '0');

        }
    }
    if (minus == 1)
        score *= -1;
    return score;
}
int validate_expression(const char* expr)
{
    if (!expr)return -1;
    int lng = strlen(expr) - 1;
    if (*(expr) > '9' || *(expr) < '0' ||  * (expr + lng) > '9' || *(expr + lng) < '0')return 0;

    int flaga = 0; // flag
    for (int i = 1; i < lng; i++) {
        if (*(expr + i) <= '9' && *(expr + i) >= '0')
        {
            flaga = 0;
        }
        else if (*(expr + i) == '/' || *(expr + i) == '*' || *(expr + i) == '-' || *(expr + i) == '+')
        {
            if (flaga == 1)
                return 0;
            flaga = 1;
        }
        else
            return 0;
    }
    return 1;
}
int calculate(const char* expr, float* result)
{
    if (!expr || !result || !validate_expression(expr)) return 0;
    if (strpbrk(expr, "i") != NULL) return 0;

    int index = 0;
    float score = 0;
    char sign_memory = 'A';
    int flaga = 0;
    unsigned int i = 1;

    for (; i <= strlen(expr); i++) {
        if (*(expr + i) == '-' || *(expr + i) == '+' || *(expr + i) == '/' || *(expr + i) == '*' || *(expr + i) == '\0') {
            score += (int)my_atoi(expr, index, i - 1);
            index = i;
            break;
        }
    }
    for (; i <= strlen(expr); i++) {
        if (*(expr + i) == '-' || *(expr + i) == '+' || *(expr + i) == '/' || *(expr + i) == '*' || i == strlen(expr)) {
            flaga = 1;
            if (sign_memory == '+')
                score += (int)my_atoi(expr, index, i - 1);
            else if (sign_memory == '-')
                score -= (int)my_atoi(expr, index, i - 1);
            else if (sign_memory == '/')
            {
                if (my_atoi(expr, index, i - 1) == 0)return 0;
                score /= (int)my_atoi(expr, index, i - 1);
            }
            else if (sign_memory == '*')
                score *= (int)my_atoi(expr, index, i - 1);
            sign_memory = *(expr + i);
        }
        else if (*(expr + i) <= '9' && *(expr + i) >= '0' && flaga == 1) {
            flaga = 0;
            index = i;
        }
    }
    *result = score;
    return 1;
}
int main()
{
    char tab[201];
    float result, * pointer = &result;

    printf("Enter text: ");
    fgets(tab, sizeof(tab), stdin);

    *(tab + strlen(tab) - 1) = '\0';
    if (!validate_expression(tab))
    {
        printf("Incorrect input");
        return 1;
    }
    else
    {
        if (calculate(tab, pointer))
            printf("%.2f", *pointer);
        else {
            printf("Incorrect input");
            return 1;
        }
    }
    return 0;
}

7
  • 4
    It would be much clearer to replace if (*(tab + i) == 10) with if (tab[i] == '\n'). Using subscripts is sensible; using *(ptr + idx) is not; using '\n' for newline and ' ' for space is more sensible than using 10 and 32. Also consider the merits of <ctype.h> and isdigit(), etc. Commented Dec 8, 2020 at 20:40
  • You probably could use recursion; I'm not convinced it would benefit the code. Do you support parentheses? Should you? Commented Dec 8, 2020 at 20:43
  • I need to use pointers and I need to use recursion now, I've tried implementing it but it's hard for me. Should've known to use it from start.. Commented Dec 8, 2020 at 20:52
  • 1
    for (; i <= strlen(expr); i++) { <<- painful Commented Dec 8, 2020 at 20:57
  • 2
    Pointer notation is going to come down to your instructor's definition of 'using pointers' — using ptr[idx] is using a pointer (one of the terms must be a pointer for subscription to be usable), but it uses the pointer more readably than using *(ptr + idx). As to recursion, you'll need to decide what you are recursing on. For example, if you support parentheses, you might have code to recurse on an expression when you encounter an open parenthesis (left bracket, aka () and stop recursing when you reach the balanced close parenthesis (aka )). And if you encounter another (, recurse. Commented Dec 8, 2020 at 20:57

1 Answer 1

1

I would make a function, which does the following:

  • Check if there is just one or more operators ("+", "-", "*", "/")
  • In case there is only one, perform the calculation.
  • In case there are two, perform a tail recursion, as proposed by Jonathan, something like:
calculate("97+74/51-98-11+68-34-2-22+73/40+81/15+100")
 = calculate("97+74/51-98-11+68-34-2-22+73/40+81/15") + 100
 = (calculate("97+74/51-98-11+68-34-2-22+73/40+81") / 15) + 100
 = ((calculate("97+74/51-98-11+68-34-2-22+73/40") + 81) / 15) + 100
 = (((calculate("97+74/51-98-11+68-34-2-22+73") / 40) + 81) / 15) + 100
 = ((((calculate("97+74/51-98-11+68-34-2-22") + 73) / 40) + 81) / 15) + 100
 = (((((calculate("97+74/51-98-11+68-34-2") - 22) + 73) / 40) + 81) / 15) + 100
 = ((((((calculate("97+74/51-98-11+68-34") - 2) - 22) + 73) / 40) + 81) / 15) + 100
 = (((((((calculate("97+74/51-98-11+68") - 34) - 2) - 22) + 73) / 40) + 81) / 15) + 100
 = ((((((((calculate("97+74/51-98-11") + 68) - 34) - 2) - 22) + 73) / 40) + 81) / 15) + 100
 = (((((((((calculate("97+74/51-98") - 11) + 68) - 34) - 2) - 22) + 73) / 40) + 81) / 15) + 100
 = ((((((((((calculate("97+74/51") - 98) - 11) + 68) - 34) - 2) - 22) + 73) / 40) + 81) / 15) + 100
 = (((((((((((calculate("97+74") / 51) - 98) - 11) + 68) - 34) - 2) - 22) + 73) / 40) + 81) / 15) + 100
 = ((((((((((((97 + 74) / 51) - 98) - 11) + 68) - 34) - 2) - 22) + 73) / 40) + 81) / 15) + 100
Sign up to request clarification or add additional context in comments.

3 Comments

What if the expression is unknown?
@Simonsoft177: what do you mean by an unknown expression?
U showed me on function calculate("97+......") but what if i got another expression, for example 2+2 or 4/2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.