Binary data in std::string

12 Jan 2018

The std::string class can hold values that are not printable ASCII characters including a zero. When using the find method, the std::string class returns a different result when using the Mbed compiler than when using Microsoft Visual Studio. Here's an example:

        int i;
        std::string r;
    
        r.append(1, 'A');
        r.append(1, 'T');
        r.append(1, 0);
        r.append(1, 0);
        r.append(1, 13);
        r.append(1, 10);
        r.append(1, 'O');
        r.append(1, 'K');
        r.append(1, 13);
        r.append(1, 10);
    
        i = r.find("\r\nOK\r\n");
        printf("i = %d\r\n",i);

In MSVS the string is found and i = 4; In Mbed the string is not found and i = -1;

Why does the std::string method behave differently in MBed? Is there any way to change the functionality so it works the same as MSVS?

11 Jan 2018

It works as in MSVS also when building offline with the GNU Arm Embedded Toolchain. A workaround for the online compiler is to pass a string type to the find function rather than a simple c string. For example as below:

#include "mbed.h"
#include <string>

DigitalOut  led1(LED1);

int main(void) {
    int     i;
    string  r;

    while (true) {
        r.append(1, 'A');
        r.append(1, 'T');
        r.append(1, 0);
        r.append(1, 0);
        r.append(1, '\r');
        r.append(1, '\n');
        r.append(1, 'O');
        r.append(1, 'K');
        r.append(1, '\r');
        r.append(1, '\n');
               
        i = r.find(string("\r\nOK\r\n"));
        printf("i = %d\r\n", i);

        r.clear();

        led1 = !led1;
        wait(0.5);
    }
}
12 Jan 2018

By the strict definition of the find function, I think my example should fail when a C style string is passed. See the description for the "s" parameter here:

http://www.cplusplus.com/reference/string/string/find/

MSVS must be assuming the quoted string is of type std::string and not a char *.

12 Jan 2018

I think when a C style string (const char array* terminated with a null char) is passed as the only argument to the string::find function then the second overloaded version is called by the compiler, which seems to be buggy in the online compiler imlementation. On the other hand, when a const string& is passed as the only argument to the string::find function then the first overloaded version is called, which seems to be implemented correctly also in the online compiler. By the way I have recently tested also the the third overloaded version (i = r.find("\r\nOK\r\n", 0, 6);) and it seems to be working correctly online too. So in my opinion it's up to the supplier of the online compiler (most likely ARM Keil) to fix the issue with the second overloaded version of the string::find function. Meanwhile, as a workaround we can use the first or the third overloaded version :-)