Help doing math with strings

Hi, I am trying to work on a simple calculator to evaluate some strings (using PEMDAS). I know the format of the strings will always be: "(# ? # ) ? # ? #" where '#' is a single digit positive whole number greater than 0 and '?' is an operand (the only ones it could be are '+' '-' '*' '/').

I am trying to add code where I input a string in the format described above, and I get an output equal to the result.

I looked through some other forum posts as well as some stuff online, but I wasn't seeing a good way to do this. I am also used to javaScript coding, so I might just be missing something obvious. My original code was returning non English characters like:
Screenshot 2025-04-15 12.19.35 PM

My code no longer returns those characters, but seems to just return random all capital things (ignoring the first output), and one number that should be the result of it's calculation. The problem is, for 5+5 it returned 106.

My end goal is to evaluate the full string format, but for now I just want to get the first calculation done. After that I will finish off the rest of the code and report back as to if the new code works. Thanks in advance!

Here is what I have so far:

// C++ code
//
String given_eq = "(5+5)+7/7";
int result = 0;
String result_string = given_eq;
String current_best_op = "";
//op scores: '*', '/' = 2|| '+', '-' = 1
int current_best_op_score = 0;
int op_score_other = 0;
String op_to_check = "";
String final_op_string = "";
int best_op_pos = 0;
//how to eval:
//first I will use if statements to evaluate the substring 1,2,3
//Then I will (going left to right) look at the next operand. If it
//comes before the current one in PEMDAS I will save it as the new thing.
//If not, I will use the first.
void setup()
{
  Serial.begin(11500);
  Serial.print("First thing to do: " + given_eq.substring(1,4));
  //eval in ()
  //the code below is going to be changed later to work wih other
  //operands. For now, I am just testing with addition
  result_string = given_eq[1] + given_eq[3];
  Serial.print("\n THE ANSWER IS: ");
  Serial.print(result_string);
  //set best op to next op
  current_best_op = given_eq[5];
  //set op score
  if (current_best_op == "*" || current_best_op == "/"){
  current_best_op_score = 2;
  } else {
  current_best_op_score = 1; 
  }
  //This loop will be used to find the next ooperation I should do
  //as well as the position of the symbol. The loop works.
  for (int op_loop_1 = 5; op_loop_1 < given_eq.length(); op_loop_1++){
  op_score_other = 0;
  //set op string
    op_to_check = given_eq[op_loop_1];
    //check if op is 'better'
    if (op_to_check == "*" || op_to_check == "/"){
  op_score_other = 2;
  } else {
  op_score_other = 1; 
  }
    //final check
    if (op_score_other > current_best_op_score) {
      final_op_string = op_to_check;
      best_op_pos = op_loop_1;
      current_best_op = given_eq[op_loop_1];
      op_score_other = 0;
    }
  }
  //print op chosen
  Serial.print("\n NEXT OP: ");
  Serial.print(current_best_op);
}

void loop()
{

}

In the following line of code you are adding the ASCII codes not the integers. Instead of 5+5 you are adding 53+53.

  result_string = given_eq[1] + given_eq[3];

The ASCII code for the character 5 is 53, so 53+53=106.

If there are other issues with the output, please show examples of the serial monitor output that you are getting.

1 Like
  Serial.println((given_eq[1] - 48) + (given_eq[3] - 48)); // ASCII of '0' is 48
  Serial.println((given_eq[1] + given_eq[3]) / 2); // ASCII of '5' is 53
1 Like

@dylan_k
Given a rough and ready solution...

result_string = (given_eq[1] - 48) + (given_eq[3] - 48);
  Serial.print("\n THE ANSWER IS: ");
  Serial.print(result_string);

Gives...

First thing to do: 5+5
 THE ANSWER IS: 10
 NEXT OP: /

@xfpd Wow you just beat me too it :rofl:

2 Likes

But I do not understand String class or how to use it.

Thanks! So if I want to do 9+9 I still just subtract 48 from each number before the operation? This also seems to work for my other operations which is great!

Thanks again!

Yes, it will work unless your numbers are >9.

Cool! What would I have to do for 2 digit numbers (since the final result will be 2 digits long)?

I realized the mistake was one I had made code to fix earlier, so I just added that solution and it worked

Should be

if (given_eq[2] == '+') {

etc

2 Likes

a common approach is to have 2 separate stacks (arrays): one for values and the other for operations.

the input can be processed one char at a time. a digit increases the value of the current value on the value stack. an operation char is pushed on the operation stack, as well as incrementing the value stack index.

also when an operation is recognized, an operation can be computed by popping two values of the value stack, performing the indicated operation and pushing the result back on the stack.

while this approach may sound overcomplicated, i think you'll realize, if you haven't already, that such an approach is required when operations need to be deferred as in the case of processing expressions withing parenthesis or handling priority operation (i.e. multiplications befoer addition)

a much better example is in chapter 8, Program Developement in the Unix Programming Environment

look this over

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

const int MaxOp = 10;
char       op [MaxOp];
int        opIdx;

const int MaxVal = 10;
int       val [MaxVal];
int       valIdx = 0;

void
calc (
    char c )
{
    int val1;
    int val2;

    printf ("calc: c %c\n", c);

    switch (c) {
    case '0'...'9':
        val [valIdx] = 10*val [valIdx] + c - '0';
        break;

    case '+':
    case '-':
    case '*':
    case '/':
        if (MaxVal <= ++valIdx)  {
            printf ("Error: MaxVal exceeded\n");
            exit (1);
        }
        op [opIdx++] = c;
        break;

    case '=':
        if (1 > valIdx)  {
            printf ("Error: too few vals - valIdx %d\n", valIdx);
            exit (1);
        }

        val1 = val [--valIdx];
        val2 = val [--valIdx];

        switch (op [--opIdx])  {
        case '+':
            val [valIdx++] = val1 += 2;
            break;
        case '-':
            val [valIdx++] = val1 -= 2;
            break;
        }
            
        printf (" %6d\n", val1);
        break;
    }
}

// -----------------------------------------------------------------------------
int
main ()
{
    char c;
    while (c = getchar ())  {
        calc (c);
    }
    return 0;
}

From each ASCII CHARACTER '9' (single quote)

replace by

if (given_eq[2] == '+') { // single quotes in place of double ones

Parse each ASCII character, subtract 48, multiply the "ones" by 1, "tens" by 10, "hundreds" by 100

This looks great, but I am trying to avoid using libraries at all costs. Thanks for the input though!

Thanks, I will make some code to do this and I will let you know if I get it working!

i'm not using any libraries.
the code is written on my laptop and needed stdio.h to do prints

Sorry, I had assumed that the code above was libraries. Sorry about that!

Those are libraries...the C standard libraries.