-1

I am using ESP8266 Wifi chip with the SMING framework which uses C++. I have a tcpServer function which receives data from a TCP port. I would like to convert the incoming char *data into String data type. This is what I did.

bool tcpServerClientReceive(TcpClient& client, char *data, int size)
{
    String rx_data;
    rx_data = String(data);
    Serial.printf("rx_data=%s\r",rx_data);
}

The contents of rx_data is rubbish. What is wrong with the code? How to make rx_data into a proper string?

guagay_wk
  • 26,337
  • 54
  • 186
  • 295
  • 2
    Maybe '\0' is missing at the end of data : try data[size] = '\0' – Garf365 Feb 02 '16 at 08:51
  • 1
    The way you are printing it seems like rubbish. Try `Serial.printf("rx_data=%s\r",(const char*)rx_data);` – StoryTeller - Unslander Monica Feb 02 '16 at 08:51
  • @StoryTeller, nothing wrong with `Serial.printf`. If rx_data is a proper string, it will print out fine. – guagay_wk Feb 02 '16 at 08:54
  • May I ask why the negative vote? What is wrong with the question? Can someone explain so that I can improve on the question? – guagay_wk Feb 02 '16 at 08:55
  • 1
    If `Serial.printf` is a variable argument function, and `String` a proper class, than the code as written has [undefined behavior](http://stackoverflow.com/questions/14432539/c-passing-classes-to-vararg-function). There is a very limited set of things that can be legally passed as var-args. The only way to make it well defined is to use a proper cast to a type that *can* be passed to a varargs function. – StoryTeller - Unslander Monica Feb 02 '16 at 08:57
  • 1
    @user1824987 : If you give some examples it should be better. Also, you can use a debugger to see what you have inside data and why rx_data is rubbish – Garf365 Feb 02 '16 at 08:58
  • @user1824987 You say "If rx_data is a proper string". What does that mean? What is the definition of `String`? Is it something defined by sming? – eerorika Feb 02 '16 at 09:02
  • user2079303, the String data type used in SMING is same as the one used in Arduino. https://www.arduino.cc/en/Reference/string – guagay_wk Feb 02 '16 at 09:03
  • 1
    Well, [this](https://www.arduino.cc/en/Reference/StringObject) page pretty much tells us that you invoke undefined behavior. It may work, or fail gloriously until the parameter is something the `printf` can accept. Besides, even if it works for some long strings, the small string optimization will certainly mess it up for small strings. – StoryTeller - Unslander Monica Feb 02 '16 at 09:05
  • 2
    This isn't the problem, but it's a waste of time to create a `String` object with the default constructor then create a temporary to assign to it. Just create it with the argument: `String rx_data(data);`. – Pete Becker Feb 02 '16 at 15:08

1 Answers1

2

Why what you are doing is wrong:

A C style string is an array of char where the last element is a 0 Byte. This is how functions now where the string ends. They scan the next character until they find this zero byte. A C++ string is a class which can hold additional data.

For instance to get the length of a string one might choose to store the length of the stirng in a member of the class and update it everytime the string is modified. While this means additional work if the string is modified it makes the call t length trivial and fast, since it simply returns the stored value.

For C Strings on the other hand length has to loop over the array and count the number of characters until it finds the null byte. thus the runime of strlen depends on the lengh of the string.

The solution:

As pointed out above you have to print it correctly, try either:

#include <iostream>
...
std::cout << "rx_data=" << rx_data << std::endl;

or if you insist on printf (why use c++ then?) you can use either string::c_str(), or (since C++11, before the reutrned array might not be null terminated) string::data(): your code would become:

Serial.printf("rx_data=%s\r",rx_data.c_str());

I would suggest you have a look at std::string to get an idea of the details. In fact if you have the time a good book could help explaining a lot of important concepts, including containers, like std::string or std::vector. Don't assume that because you know C you know how to write C++.

ted
  • 4,791
  • 5
  • 38
  • 84