String to character

Hi everyone,

I am using the BLE Mate 2 with my SAM D21 and encountering some programming issues in using char arrays (or strings). The example application uses Strings but I wanted to use characters as they are more space efficient. Their code looks like this:

  static String inputBuffer;
  while(Serial1.available() > 0)
  {
    inputBuffer.concat((char)Serial1.read());
  }
  // Only read strings which start with RCV and end with \n\r
  if (inputBuffer.endsWith("\n\r"))
  {
    if (inputBuffer.startsWith("RCV="))
    {
      inputBuffer.trim(); // Remove \n\r from end.
      inputBuffer.remove(0,4); // Remove RCV= from front.
      SerialUSB.println(inputBuffer);
      inputBuffer = "";
    }
    else
    {
      inputBuffer = "";
    }
  }

and it prints out something like this : 4:23:40 PM

I am trying to use characters and my code looks like this:

  char input[50];
  char carrage[] = "\n\r";
  char message[] = "RCV=";
  
  while(Serial1.available() > 0)
  {
    char i = (char)Serial1.read();
    strcat(input, &i);
    memset(&i, 0, 1);
  }
// Only read strings which start with RCV and end with \n\r
  if(strcmp(input+(strlen(input)-4), carrage) == 0)
  {
    if(strncmp(input, message, 4) == 0)
    {
      str_remove(input, strlen(input)-4, 4);
      str_remove(input, 0, 4);
      SerialUSB.println(input);
      memset(input, 0, strlen(input));
    }
    else
    {
      memset(input, 0, strlen(input));
    }
  }

and it prints out nothing....

Does anyone see a problem with my code?

P.S SerialUSB is used to talk between Arduino and PC. Serial1 is used to access the UART between BLE and Arduino

Thanks!

input + (strlen(input) - 4)What is this supposed to do ?

Hi that line shifts the point to the 4th last index of the character array as I am trying to compare the end of the string to \n\r and see if it exists!

The length of "\n\r" is two, not four.

This part is wrong:

ddesousa:

    char i = (char)Serial1.read();

strcat(input, &i);
   memset(&i, 0, 1);

strcat() needs a string as the second argument, but i is a char. Just put i in the last position of the input string and then null-terminate it:

size_t len = strlen(input);
input[len] = i;
input[len+1] = '\0';

Hi Whandall,

The length of "\n\r" is two, not four.

I will try that out!

Hi Christop,

input[len] = i;

I don't think we can do this. Should I use memset instead??

Thanks,

DD

ddesousa:
I don't think we can do this. Should I use memset instead??

Why can't you do that? Please explain.

Hi Christop,

In character arrays, do you not have to allocate the memory differently.

My experience with strings and char has only been using the following functions:
http://www.cplusplus.com/reference/cstring/

Would we not do something like this:
memset(input+len, &i, 1);

Thanks!

ddesousa:
Would we not do something like this:
memset(input+len, &i, 1);

You could do it that way, but it's just as easy (or easier) to assign i directly to input[len] than calling memset.

Another way to do it is:

char str[2] = "";
str[0] = (char)Serial1.read();
strcat(input, str);

But that doesn't buy you much either.

Great! That worked too! Thanks for your help!

Do you know if Strings are quicker to work with than char?

I am noticing alot of time is being spent on this function.

Daniel

Do you know if Strings are quicker to work with than char?

Unlikely as it is my understanding that Strings are just a wrapper around the underlying C string functions.

ddesousa:
I am noticing alot of time is being spent on this function.

Do you mean that it runs slowly? How have you measured that?

Hi Christop,

See my problem on this thread: Function taking too long? Blocking out acceleromter? - Programming Questions - Arduino Forum

Thanks

You need to look closely at some conventional approaches to doing things. Your code does all kinds of weird backflips instead of doing things in a logical order. One way to see this is that the code should follow the idea of the desired action, for example:

// Only read strings which start with RCV and end with \n\r

The data comes to you as a stream, you should first look for RCV, and then collect characters while looking for the \n\r.

As an example of how you break the simplicity of it, you keep appending a '\0' to the target string every time you read a character, instead of adding it when you are finished. This happens because you don't have a clear point in your code when you can tell that everything is finished. You only need to do it once. Such juggling is a distraction and complication in the code that makes it hard to understand and increases the likelihood of bugs. Your gratuitous use of memset() is a symptom of this ailment.

Why do you cast the result of a read operation as a char, when it is already a char?