I have a string that looks as follows: XYZ values - X: 35.3 Y: 446 Z:10.5
or A: 5.321 B: 446 C: 10.553 D: 45000
And I need to separate the extract from the string only the numbers, which can be integers or floats.
Inspired by this: Split Strings based on space
This is the approach I am currently using, which works well, but I would like to move away from String arrays to either char arrays or any other method that is more optimised.
// first element passed is the string that needs to be separated
// second element is the array where to store the values
void StringSeparator(String str, String strs[]) {
memset(strs, 0, sizeof(strs));
uint8_t StringCount = 0;
while (str.length() > 0) {
int8_t index = str.indexOf(' ');
if (index == -1) {
strs[StringCount++] = str;
break;
} else {
if (isDigit(str.charAt(StringCount+0))) {strs[StringCount++] = str.substring(0, index);}
str = str.substring(index + 1);
}
}
}
I don't have that much experience with Strings in C/C++, never really had to use them until now, and I know they are not really a good way to do things. Please keep in mind the string I receive is from a source that I cannot modify/change, so the string is the one showed at the top.
The solution should be "universal", as in I can have floats or ints, maximum 6 digits (355.125 format for example), but the amount of numbers that need to be extracted can vary, it can be 3, 4 etc.
use indexOf() to find "X:" and use toFloat() or toDouble() on the substring starting at the index +2 (+2 to skip the "X:"and be on the first digit or the space
Wouldn't using SubString defeat the purpose of the function?
As my number can be 1.352 or 356.321 or 57543.
I understand that with the +2 you are moving to the first digit, but how does "it know" when to stop the digit extraction? Does it stop automatically as soon as it encounters another character because of the toDouble?
Indeed, that is why I am asking. I cannot change the string, it is not "made by me" the same way it is in your example code, I receive it and I have to process it.
If you receive the data in the form of a C-string (zero terminated character array), there there is an entire collection of standard functions that allow you to search, break up and interpret any part of that string.
For example, strtok() breaks up a string into individual components, separated by commas, blanks, etc.
Sadly there is none. I either have to edit the library to have everything return with &x &y &z which would break at the next update and I would have to provide a modified library with my code.
Or just use the way they implemented it and split the string in my code.
I can see there is no other way of returning the actual values.
Some other sensors have the method temperature.value() which returns the actual float value. "temperature" is the name I gave to the sensor.
Any return/output that has more than 1 output, so for example an IMU compared to a temp sensor, is returned as a String, in order to include all outputs as one.
@runaway_pancake How does that help? Your method only works with cStrings, and mine is different.
The actual data are stored in a struct associated with each sensor, as clearly demonstrated by this debugging code from the library. But I would certainly not waste my time working with that can of worms.
(I gave up on most Bosch sensors long ago, as they intended for black box consumer devices, and are not keeping up with the accuracy and precision of sensors available from other manufacturers).
Edit 2: While I agree the library may not have used the best implementation on returning the values. And as I would prefer not to modify the library which would get wiped with an update, I would like to return to the topic of the post for the best way to split the string while using least amount of memory and no Strings.