Help Needed Parsing Ugly String

Here’s a little challenge for the folks much more fluent in C than I am (which is mostly everyone). I have a Core connected to my 3D printer RAMPS board running Marlin. It can successfully issue commands over serial and retrieve the response. The one G-code command that I’m interesting is parsing is M105 to get all of the temperatures. That command returns a string like ok T:21.9 /0.0 B:22.1 /0.0 T0:21.9 /0.0 @:0 B@:0 ok T:22.0 /0. I’d like to extract the first 4 numbers (21.9, 0.0, 22.1, and 0.0). I have it working with a series of terrible String .substring() and .indexOf() functions, but it’s ugly.

Here’s what that mess looks like:

void getTemperatures() {
    if(String strTemps = sendData("M105")) {
        // ok T:21.9 /0.0 B:22.1 /0.0 T0:21.9 /0.0 @:0 B@:0 ok T:22.0 /0
        // Get extruder current temperature
        String a = strTemps.substring(strTemps.indexOf("T:")+2, strTemps.indexOf("/"));
        //Spark.publish("wi3d", a);
        // Get extruder target temperature
        String b = strTemps.substring(strTemps.indexOf("/")+1, strTemps.indexOf("B:"));
        //Spark.publish("wi3d", b);
        // Get bed current temperature
        String c = strTemps.substring(strTemps.indexOf("B:")+2, strTemps.indexOf("/", strTemps.indexOf("B:")+2));;
        //Spark.publish("wi3d", c);
        // Get bed target temperature
        String d = strTemps.substring(strTemps.indexOf("/", strTemps.indexOf("B:"))+1, strTemps.indexOf("T0:"));
        Spark.publish("wi3d", d);

It returns the values I'm looking for, but it feels like there should be a better/easier way of doing it.  I know regular expressions aren't available, but maybe it could be done with `sscanf()` or another method.  Since there are (literally) hundreds of G-code commands, a regex or sscanf-like parsing method would be preferred.

Any ideas?
1 Like


Your code looks good. Keep in mind that nice is the enemy of good. I would create a little helper function that extracts a temp of the string.


String T1 = get_temp(strTemps,“T:”);
String T2 = get_temp(strTemps,“B:”);
et cetera.

I got sscanf() working, but it’s a memory hog. Using the ugly way (in original post), I get:

Flash used	73960 / 110592	66.9 %
RAM used	14684 / 20480	71.7 %```

And, using `sscanf()`, I get:

Flash used 105744 / 110592 95.6 %
RAM used 15076 / 20480 73.6 %```

Ugly way wins, although I’m not sure how I feel about that. I hate parsing strings that way!