Converting a double of varying size, to a char array

I'm currently trying to convert a double into a character array for transmitting.

//Declaration of character array
 char stroutPart[8]; 

//Calls function to shift, convert and get the original value into the correct form
double particleDouble = convertShiftVal("Particle");

//Convert double to character 
dtostrf(particleDouble,6, 2, stroutPart);

After the convertShfitVal function has been called I receive a double value that in the range 1.11 up to 12345.67. The problem seems to be with the size of the "dtostrf()" function. I had 6 in there but it can vary from 4 to 8 and I can't figure out how to make this dynamic.

I have tried things like particleDouble.length() and also sizeof(particleDouble) in the following way:

//Convert double to character 
dtostrf(particleDouble,particleDouble.length(), 2, stroutPart);

or

//Convert double to character 
dtostrf(particleDouble, sizeof(particleDouble), 2, stroutPart);

but neither of these approaches seem to work and only give fixed values rather than dynamic ones. Just wondering is there some way I can inform the function of the number size before it runs?

If you are trying to remove extra zeros at the end of small floats: Once converted, find the first '0' char ( at the end of the string ) and then place the terminating null there.

A decrementing loop should do it.

The zeroes don't matter too much is is the size of the double in digits that is the problem. Using the two numbers in the OP as an example;

A double of value 1.11 would have a length of 4 including the decimal point A double of value 12345.67. would have a length of 8 including decimal point.

When that large double value goes into the dtostrf() function which is expecting a 6 but I give it an 8, the output goes nuts. On the other end of the scale when I put a value smaller than 6, I have gaps in the output. I'm thinking that a function that dynamically checks the length of the variable would solve this?

char * dtostrf(
    double __val,
    signed char __width,
    unsigned char __prec,
    char * __s)

Conversion is done in the format "[-]d.ddd". The minimum field width of the output string (including the '.' and the possible sign for negative values) is given in width, and prec determines the number of digits after the decimal sign. width is signed value, negative for left adjustment.

I haven't used dtostrf however, 'width' appears to be the output size, if you pass 8 to it, your string may not be null terminated, causing any output of the string to print raw memory after the array until it hits a null.

Yeah the width is what needs to change depending on the size of the double that I'm passing to it. How can I measure the length of that double so that the width changes as the number changes?

Does the width really need to change? Seems wrong. You aren't changing the size of the array, which is what the width should be limited to. If you increase your buffer to 10 chars and use a width of 9, does this not fix the problem.

Set the last element to null.

I was trying that approach but that then installs white-space in front of the value which then prevents it from transmitting correctly. I either need to figure out the length at the start or remove the white-space at the end.

I have been trying to use trim() to get rid of the white space but it doesn't seem to work correctly with character arrays.

You don't have to remove the white space, you can just move the pointer ( start of the array ).

 char stroutPart[8];
 char idx = 0x00;

//Conversion here

//count white space
 while( stroutPart[ idx ] == ' ' ) ++idx;
 Serial.println( stroutPart + idx );      //print
 Serial.println( &stroutPart[ idx ] );  //or the equivalent.

Replace the comparison with whatever white space you are receiving. This assumes the white space is all the same character.

You could play with the log() function, or use brute force:

int fwidth;

if (x < 10.0)
{
   fwidth = 4;
} 
else if (x < 100.0)
{
    fwidth = 5;
} 
else if (x < 1000.0)
{    fwidth = 5;
} 
else
{
   fwidth = 6;
}

dtostrf(x, fwidth, 2, buf);

but counting whitespace is better.

After the convertShfitVal function has been called I receive a double value that in the range 1.11 up to 12345.67. The problem seems to be with the size of the “dtostrf()” function. I had 6 in there but it can vary from 4 to 8 and I can’t figure out how to make this dynamic.

Do you actually need to make it dynamic ?

From a definition quoted earlier in this thread

The minimum field width of the output string (including the ‘.’ and the possible sign for negative values) is given in width

This is the second parameter of dtostfr(). What happens if you make this parameter zero ? It is, after all, the minimum field width required, not the maximum. It seems to work, or have I completely missed the point as seems likely !

char outBuffer[8];

void setup() 
{
  Serial.begin(115200);
  double x = 1.23;
  showOutput(x);

  x = -1.23;
  showOutput(x);
  
  x = 12345.67;
  showOutput(x);
}

void loop() 
{}

void showOutput(double x)
{
  int y = strlen(dtostrf(x, 0, 2, outBuffer));
  Serial.print(">");
  Serial.print(outBuffer);
  Serial.println("<");
}

I went with Keith's brute force method and that worked. I then tried your method by putting in the zero and it works also! Thanks guys!