Best way to parse values from a string?

Hi

I'm writing some code for the Arduino and wanted to parse some settings that will be inputted. The settings must be DIGITS1 = DIGITS2, DIGITS3 = DIGITS4 etc - like the following

 
  2 = 202,1 = 103, 9 = 202

Spaces don't matter and there can be multiple identities (separated by a comma) or only one. At the moment, I'm just looking to see whether its valid

Is there an easy way to do this on the Arduino? Would regex help here (assuming there is a library for it on Arduino?

I've written the below which seems to work following some tests but its long and ugly!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
bool checkSettings (String settingStr)
{
  if (settingStr.length() == 0)    //settings cannot be empty
      return false;
  
  for (int i = 0; i < settingStr.length(); i++) //this deals with the whole string
  {
      bool firstNum = false, secondNum = false, equalsSign = false; //these mark whether each sentence has required characters

      for (int j = i; j < settingStr.length(); j++) //this deals with each sentence
      {
        if (firstNum && secondNum && equalsSign) //for this sentence we have found all required elements
        {

          if (settingStr[j] != ',' && j != settingStr.length() - 1)  //should end with a comma or be the end of the whole string otherwise fail
            return false;
            
          else    //finished with this sentence move to next
          {
            i = j;
            break;
          }
        }

        if (!firstNum)   //expecting first number
        {
          if (settingStr[j] == ' ')
            continue;
          
           if (!isDigit(settingStr[j]))  //return false as must be a digit
              return false;

           for (int k = j + 1; j < settingStr.length(); k++) //see what trails the first digit
           {
              if (!isDigit(settingStr[k]))  //not a digit so stop looking
              {
                  firstNum = true;   //found our number
                  j = k;  //set j back to our non-digit index
                  break;
              }
           }
        }

        if (firstNum  && !equalsSign )  //expecting equals sign
        {
           if (settingStr[j] == ' ')
              continue;
            
            if (settingStr[j] != '=') 
              return false;

            else
            {
              j = j + 1;
              equalsSign = true;
            }
        }

        if (firstNum && equalsSign && !secondNum) //expecting third number
        {       
              if (settingStr[j] == ' ')
                continue;

              if (!isDigit(settingStr[j]))  //return false as must be a digit
                  return false;

              for (int l = j + 1; l < settingStr.length(); l++)
              {
                  if (!isDigit(settingStr[l]) || l == settingStr.length() - 1)  //if next character not a digit or end of whole sentence then go to exit procedure above
                  {
                    secondNum = true;
                    j = l - 1;
                    break;
                  }
              }
        }
      }
  }
  return true;
}


Thanks
Last edited on
I am not sure what is available on the Arduino.
Normally you can use a stringstream and getline to split your string into substrings with ',' as separator.

For each string you can use the find method of the string to locate the '=' and use the substring function get the key and value. Finally you convert the value to an int.
OR
You could use a second stringstream and use >> to extract the key, '=', and value.
Found some spare minutes and hacked together this demo. Maybe easier to understand than my explanation.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#include <cstdlib>

using namespace std;

vector<string> SplitString(const string& s, char sep = ',')
{
  vector<string> v;
  stringstream ss(s);
  string token;
  while (getline(ss, token, sep))
  {
    v.push_back(token);
  }
  return v;
}

bool SplitString(const string& input, int& key, int& val, char sep = '=')
{
  stringstream ss(input);
  char separator;
  int tempKey, tempValue;
  if (!(ss >> tempKey >> separator >> tempValue))
    return false;
  if (separator != sep)
    return false;

  key = tempKey;
  val = tempValue;

  return true;
}

int main()
{
  const string input = "2 = 202,1 = 103, 9 = 202";
  vector<string> tokens = SplitString(input);
  int key, val;
  for (const string& s : tokens)
  {
    if (SplitString(s, key, val))
    {
      cout << "Key = " << key << "\t" << "Value= " << val << "\n";
    }
  }
}

OUTPUT

Key = 2 Value= 202
Key = 1 Value= 103
Key = 9 Value= 202
closed account (48T7M4Gy)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
#include <string>
#include <sstream>

int main()
{
    // SIMULATE INPUT STREAM
    std::istringstream iss;
    std::string input = "2 = 202,1 = 103, 9 = 292, 4 = 402,3 = 773, 8 = 678";
    iss.str (input);
    
    int n1 = 0, n2 = 0;
    char ch1, ch2;
    
    // PROCESS STREAM
    while(iss >> n1 >> ch1 >> n2)
    {
        std::cout << n1 << ' ' << n2 << '\n';
        if(iss.tellg() == -1)
            break;
        else
            iss >> ch2;
    }
    
    return 0;
}


std::string input = "2 = 202,1 = 103, 9 = 292, 4 = 402,3 = 773, 8 = 678";

2 202
1 103
9 292
4 402
3 773
8 678
Program ended with exit code: 0




std::string input = "2 = 202";

2 202
Program ended with exit code: 0
Topic archived. No new replies allowed.