Question

Below I am trying to set a format specifier, but I want to do it differently each time I call the function. The point is to print the float Data_Ave. In one instance I want the specifier %2.3f, and so I would pass the function a 2 for sig_figs_before and a 3 for sig_figs_after. In the next instance I want %1.4f, so I would pass those ints.

char * Send_Data(float Data[10], const char* SUBJECT_SEND_NAME, char *Data_Backup, int sig_figs_before, int sig_figs_after)
{
  float Data_Ave = ((Data[0] + Data[1] + Data[2] + Data[3] + Data[4] +
            Data[5] + Data[6] + Data[7] + Data[8] + Data[9])/10);
  sprintf(msgBody,"%%i.%if, ", before_decimal, after_decimal, Data_Ave);
  ... //Some more code
  }

I'm pretty sure this will not work, so I was thinking to split the float into two ints and print it like so:

sprintf(msgBody,"%i.%i, ", int_value, decimal_value);

But I do not know how to properly split the float. Any suggestions?

No correct solution

OTHER TIPS

You want:

sprintf(msgBody,"%*.*f, ", before_decimal+after_decimal+1, after_decimal, Data_Ave);

Note that you can use * to specify the width by an integer argument. Also note that in a format %N.Mf, N is the total size of printed number (including decimals, dot, sign, exponent, padding, etc.) and M is the decimal precision. This is why, in your case, the first number shall be before_decimal+after_decimal+1 not before_decimal only.

You can use sprintf twice to obtain the results you want — once to obtain the format string, and then again to obtain your actual result.

sprintf(format, "%%%i.%if", before_decimal, after_decimal);
sprintf(msgBody, format, Data_Ave);

The first line will write, e.g. (for 2 and 3) %2.3f into format; the second line will operate on that format string to write msgBody.

You should also consider using snprintf instead of sprintf, especially since you're using potentially variable-length strings — don't want to cause a buffer overflow!

sprintf() does not provide a "significant figures before".

It does provide a minimum field width which can be derived from sig_figs_before, sig_figs_after and the value itself.

char * Send_Data(float Data[10], const char* SUBJECT_SEND_NAME, 
    char *Data_Backup, int sig_figs_before, int sig_figs_after) {

  assert(sig_figs_before >= 1);
  assert(sig_figs_after >= 0);

  float Data_Ave = ((Data[0] + Data[1] + Data[2] + Data[3] + Data[4] +
                     Data[5] + Data[6] + Data[7] + Data[8] + Data[9])/10);

  int width = sig_figs_before + 1 + sig_figs_after;  // +1 for '.'
  // Make room for '-'
  if (Data_Ave < 0) width++;
  sprintf(msgBody, "%#*.*f, ", width, sig_figs_after, Data_Ave);
}

'#' is used should sig_figs_after == 0 to preserve the decimal point.

Note: this does not limit the width or the number of sig_figs_before should Data_Ave be large. @Matt Patenaude idea to use snprintf() is a good one.

A hack approach would be to test:

if (log10(fabs(Data_Ave)+0.5) > sig_figs_before) UseAlternativePrint();   
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top