D
D
DDD2021-12-20 16:57:15
C++ / C#
DDD, 2021-12-20 16:57:15

How to write a simple calculator?

I want to write a one-line calculator, but there was a problem when writing: the function atoi(ex.c_str())duplicates the first parameter entered. Tell me how to fix this and, if possible, give advice on logic, otherwise a bunch of ifs annoys me.

int fu(std::string ex)
{
    std::string r;
    float result=0;
    for (size_t v=0;v<ex.size();++v)
    {
        r=ex[4];
        if (ex[v]=='+')result=atoi(ex.c_str())+atoi(ex.c_str());
        else if (ex[v]=='+' || ex[v]=='*')result=atoi(ex.c_str())+(atoi(ex.c_str())*atoi(r.c_str()));
        else if (ex[v]=='+' || ex[v]=='/')result=atoi(ex.c_str())+(atoi(ex.c_str())/atoi(r.c_str()));

        else if (ex[v]=='-')result=atoi(ex.c_str())-atoi(ex.c_str());
        else if (ex[v]=='-' || ex[v]=='*')result=atoi(ex.c_str())-atoi(ex.c_str())*atoi(r.c_str());
        else if (ex[v]=='-' || ex[v]=='/')result=atoi(ex.c_str())-atoi(ex.c_str())/atoi(r.c_str());

        else if (ex[v]=='*')result=atoi(ex.c_str())*atoi(ex.c_str());
        else if (ex[v]=='*' || ex[v]=='-')result=atoi(ex.c_str())*atoi(ex.c_str())-atoi(r.c_str());
        else if (ex[v]=='*' || ex[v]=='+')result=atoi(ex.c_str())*atoi(ex.c_str())+atoi(r.c_str());
        else if (ex[v]=='*' || ex[v]=='/')result=atoi(ex.c_str())*(atoi(ex.c_str())/atoi(r.c_str()));

        else if (ex[v]=='/')result=atoi(ex.c_str())/atoi(ex.c_str());
    }
    return result;
}

Answer the question

In order to leave comments, you need to log in

2 answer(s)
V
Victor Bomberow, 2021-12-20
@Kiberchief

I will answer for the case of working with a simple input format: 1) you do not modify the input string, therefore, if we are dealing with the standard from c++17, then it is better to accept explicitly into the function or , if lower, then you need to accept . 2) if we already accept something string-like, then we can safely use the member function , which is both in the string and in the view. With its help, you can immediately find the position of an arithmetic symbol. For a simple case, we don't even need to traverse from the found position to the beginning of the string and to the end of the string to check if the character is a space, since we can immediately send to atoi for the left number for example . And, it turns out, only one if / switch, which will match the operation symbol, for example, with a function pointer.
12345 + 6789

...
int plus(int left, int right) { return left + right; }

using CalculatorFunction = int (*)(int, int);
...
CalculatorFunction operation;
...
switch (opChar):
case '+': operation = plus;
...

3) I strongly recommend that after that you implement a normal simple calculator, and then add support for brackets, hex oct binary and with the mantissa notation for writing numbers, the degree and root operation in the third run.
Normal - meaning that the calculator includes a string that is a valid arithmetic expression. In this case, you still need to deal with delimiters. In a good way, the solution consists of several stages:
- at the first logical stage, the function parses the expression and saves it in the context or returns a container with tokens, (or aborts the whole process due to a bad line). In your case, the task is single-threaded, so you can use the strtok function to conveniently extract the string value of the token from the input string from delimiter to delimiter.
- alternatively, tokens can be structures with a string_view member for string representations and a member for the token type (number, operation).
- at the second logical stage, we read the sequence of tokens and do some action:
  • counted the number - we expect the operation token behind it
  • if it turned out to be not an operation token, we throw an exception about an incorrect arithmetic expression, otherwise we prepare the arguments and feed the function evaluate<T>( Token::kOperation op, T arg1, T arg2), in case the operation needs two arguments, then the first one has already been read, and the second one will be in the sequence of tokens after the operation. The result of evalaute is written to the result variable, which, by the way, is of double type.
  • we continue moving along the sequence of tokens to the end, the container can be std::list, when we get to the end, we return the result.

R
res2001, 2021-12-20
@res2001

For example:
atoi(ex.c_str())+atoi(ex.c_str())
this expression converts the same string into a number 2 times, and then adds these 2 identical numbers.
So it "does not duplicate", but does what is written in your code.
You need to split the string into "tokens" first, i.e. for operands and operations.
If at this stage you expect to process only the simplest actions, then enter a string and break it into 3 tokens. Then you convert the operands to numbers and after that you already perform the action.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question