0

This is likely a duplicate, but I couldn't find the original question. This is really basic, but just can't figure it out.

I'm trying to combine a few char arrays together. This is what I've tried so far.

float a = 12.3456;
float b = 5.4321;
bool c = true;

char a_string[4];
dtostrf(a, 4, 1, a_string);

char b_string[4];
dtostrf(b, 4, 1, b_string);

char c_string[2] = {'0', '\0'};
if (c) {
  c_string[0] = '1';
}

char output[12] = "-----------";

output[0] = a_string[0];
output[1] = a_string[1];
output[2] = a_string[2];
output[3] = a_string[3];

output[4] = ' ';

output[5] = b_string[0];
output[6] = b_string[1];
output[7] = b_string[2];
output[8] = b_string[3];

output[9] = ' ';

output[10] = c_string[0];

Serial.println(output);

Results in an empty string in seems.

If I remove the second dtostrf(), and change b_string[0] ... to a_string[0] Then I get 12.3 12.3 1. Doesn't seem to like having dtostrf() called more than once, but it seems like the function I want, since it allows me to set a fixed strint size. The output I'd be looking for is 12.3 5.4 1

another approach

String a_string = String(a, 1);
String b_string = String(b, 1);
String c_string = String(c);

String output;
String space = " ";

output.concat(a_string);
output.concat(space);
output.concat(b_string);
output.concat(space);
output.concat(c_string);

Serial.println(output);

This outputs 12.3 5.4 1. Is there a way to make the String fixed width? I'm looking for

12.3 5.4 1 instead of

12.3 5.4 1

What's the proper way of doing this?

EDIT


After trying to use the @Majenko's answer I sometimes get garbage values printed. Any ideas why?

float a = analogRead(A1) / 1023.;
float b = analogRead(A2) / 1023.;
bool c = analogRead(A3) / 1023;

char* output = createString(a, b, c);
Serial.println(output);


char* createString (float _a, float _b, bool _c) 
{
    char a_string[5];
    dtostrf(_a, 4, 1, a_string);

    char b_string[5];
    dtostrf(_b, 4, 1, b_string);

    char out[12];
    snprintf(out, 12, "%4s %4s %d", a_string, b_string, c ? 1 : 0);
    return out;
}

and the output:

 0.6  1.0 0
 0.6  1.0 0
 0.6  1.0 0
 0.6  1.0 0
 0.6  1.0 0
 0.6  1.0 0
 0.�tS
�
 0.6  `S
�
 0.6  1.0
}
 0.6  1.0 0
 0.7  1.0 0
 0.6  1.0 0
 0.6  1.0 0

using

  Serial.print(a_string);
  Serial.print(" ");
  Serial.print(b_string);
  Serial.print(" ");
  Serial.println(c);

doesn't produce the errors

  • Other than figuring out how long each string is or using *printf()? – Ignacio Vazquez-Abrams Apr 25 '16 at 19:00
3

The simple way would be to format the string with sprintf - however sprintf on the Arduino lacks floating point support (although it is possible to enable it).

So if you convert your floating point numbers into strings first (remember to provide room for the NULL terminating character!) you can then use sprintf to format those converted numbers into what you want:

float a = 12.3456;
float b = 5.4321;
bool c = true;

char a_string[5];
dtostrf(a, 4, 1, a_string);

char b_string[5];
dtostrf(b, 4, 1, b_string);

char out[12];

snprintf(out, 12, "%4s %4s %d", a_string, b_string, c ? 1 : 0);

%4s is replaced by a string which is padded to at least 4 characters wide. The padding is to the left of the string. If you want the padding to the right you can use %-4s instead.


Addendum:

In your new posted code you are making a fundamental error:

char out[12];
snprintf(out, 12, "%4s %4s %d", a_string, b_string, c ? 1 : 0);
return out;

out is a local variable to the function. Its memory is allocated on the stack. You fill that with data and then return the address of that location on the stack. As soon as you leave the function that memory allocation is lost. Yes, the data is still there, but the moment you call another function that memory gets overwritten with the call frame of the new function you have called - thus corrupting your data.

You have two main options:

  1. Make out global
  2. Make out static

The effect of the two options is pretty much the same, except that in the second option the scope of out is restricted to the function which means you can use the name out elsewhere without it conflicting. In both options though the memory allocated to out is in the BSS not the stack and thus won't get overwritten.

  • Thanks, that works great. When I try to use analogRead values for it though I sometimes get garbage. I updated by question. Any ideas? – waspinator May 4 '16 at 14:52
  • 1
    See my addendum. – Majenko May 4 '16 at 14:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.