Merge two lines in float on stm32?

I get two UART string values ​​in stm32f3 and would like to combine them into a float, but in fact I don't see how to do this. Let's do it in the following example.

char *s1="100";
char *s2="09"; //should result in 100.09

float x=???(s1,s2);

How can i achieve this?

+4
source share
5 answers

One approach is to print both lines in the buffer and then use strtodto read floatbackward:

char buf[10];
sprintf(buf, "%.4s.%.4s", s1, s2);
float f = strtod(buf, NULL);
printf("%f\n", f);

Note that since it 100.09does not have an exact representation of how float, the result will be something close to 100.089996.

Demo version

+2
source

I would convert each line to an integer and then use arithmetic:

int whole = atoi(s1);
int frac = atoi(s2);

float x = whole + frac / powf(10, strlen(s2));

10 ^ strlen (s2), "09" 09/100, "5" 5/10 ..

powf() ( ), ( , , ):

float myexp10(unsigned x)
{
    if (x == 0)
        return 1.0;

    float res = 10;
    while (--x)
        res *= 10;

    return res;
}
+3

, strtof() ,

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void) {
    char *s1 = "100";
    char *s2 = "09";
    char s[strlen(s1) + 1 + strlen(s2) + 1];
    strcpy(s, s1);
    strcat(s, ".");
    strcat(s, s2);
    float result = strtof (s, NULL);
    printf("%f\n", result);
    return 0;
}

:

100.089996

, strtod(), :

double result = strtod (s, NULL);
+1

, - char atof() :

#include <stdio.h>
#include <string.h> /* strlen */
#include <stdlib.h> /* atof */


float str2float(const char* s1, const char* s2)
{
    int size = strlen(s1) + strlen(s2) + 2;
    char a[size];

    for(int i = 0; i < strlen(s1); ++i)
        a[i] = s1[i];
    a[strlen(s1)] = '.';

    for(int i = strlen(s1)+1, j = 0; i < size && j < strlen(s2); ++i, ++j)
        a[i] = s2[j];

    a[size] = '\0';

    return (float)atof(a);
}

int main(void)
{
    char *s1="100";
    char *s2="09"; 

    printf("%.2f\n", str2float(s1,s2));
    return 0;
}
0

.

  char *s1="100";
  char *s2="09";
  float f1 = strtof(s1, (void*) NULL); 
  unsigned n = strlen(s2);
  float f2 = strtof(s2, (void*) NULL)/powf(10, n);
  return f1 + f2;

, .

strtof(s2, (void*) NULL)/powf(10, n); , , binary32. f1 + f2 . float - .

, , double.

  float f1 = strtof(s1, (void*) NULL); 
  unsigned n = strlen(s2);
  double f2 = strtod(s2, (void*) NULL)/pow(10, n); // use higher precision
  return f1 + f2;

FP , , , 1 . .

  long l1 = strtol(s1, (void*) NULL, 10); 
  long l2 = strtol(s2, (void*) NULL, 10); 
  unsigned n = strlen(s2);
  long p10 = pow10(n);  // Trivial user TBD code

  long sum = l1*p10 + l2;  // Exact unless `long` overflow
  return 1.0f*sum/p10;     // `float` conversion exact for value up to about 1/FLT_EPSILON

This works well if s1negative. Also OK with s2as negative, except for the extra code needed to extract the width of the digit than strlen(s2).

Otherwise, it is difficult to concatenate strings and convert. I recommend float strof()over double atof()as 1) atof()does not have a specific behavior on overflow, 2) atof()uses doublemath, which can be slower.

size_t l1 = strlen(s1);
size_t l2 = strlen(s1);
char buffer[l1 + 1 + l2 + 1];  // Or use a fixed wide buffer with test to insure fit
strcpy(buffer, s1);
buffer[l1] = '.';
strcpy(buffer + l1 + 1, s1);
return strtof(buffer, (void *) NULL);
0
source

Source: https://habr.com/ru/post/1686714/


All Articles