C 将两个字符串合并为stm32上的浮点?

C 将两个字符串合并为stm32上的浮点?,c,string,floating-point,C,String,Floating Point,我通过UART接收到两个字符串值到stm32f3,并希望将它们连接到浮点,但实际上我不知道如何做到这一点。让我们 在下面的示例中执行此操作 char *s1="100"; char *s2="09"; //should result in 100.09 float x=???(s1,s2); 如何实现这一点?一种方法是将两个字符串打印到缓冲区中,然后使用strtod读回浮点值: char buf[10]; sprintf(buf, "%.4s.%.4s", s1, s2); float f

我通过UART接收到两个字符串值到stm32f3,并希望将它们连接到浮点,但实际上我不知道如何做到这一点。让我们 在下面的示例中执行此操作

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

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

如何实现这一点?

一种方法是将两个字符串打印到缓冲区中,然后使用
strtod
读回
浮点值:

char buf[10];
sprintf(buf, "%.4s.%.4s", s1, s2);
float f = strtod(buf, NULL);
printf("%f\n", f);
请注意,由于
100.09
没有精确表示为
float
,因此结果将接近
100.089996


我会将每个字符串转换成一个整数,然后使用算术:

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()
在您的系统上不起作用(如您在评论中所说),您可以使用此选项(仅适用于小的非负输入,但这就是您所拥有的):


另一种简单但繁琐的方法是将它们存储在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;
}
#包括
#包括/*斯特伦*/
#包括/*atof*/
浮点str2float(常量字符*s1,常量字符*s2)
{
int size=strlen(s1)+strlen(s2)+2;
字符a[大小];
对于(int i=0;i
我将两个字符串连接在一起,中间有一个点,然后使用提取浮点数,如下所示:

#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;
}
double result = strtod (s, NULL);

考虑按其他人的建议缩放分数部分并添加

  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;
这通常已经足够了,但还需要进一步挖掘

strof(s2,(void*)NULL)/powf(10,n)
使用除法进行四舍五入,因为商(分数)很少能精确表示为整数。然后,加法
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

如果
s1
为负值,则上述方法效果良好。除了提取数字宽度所需的代码比strlen(s2)
多之外,
s2
作为负数也可以

否则很难打败字符串串联和转换。我建议
float strof()
over
double-atof()
as 1)
atof()
在溢出时缺少定义的行为,2)
atof()
使用
double
数学,这可能会更慢

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);

float x=整体+frac*powf(10,-(int)strlen(s2))
@hanspetersoft:pow()怎么样?这里也一样好,我很确定它在STM32上也能工作。您可能需要通过添加编译器/链接器选项
-lm
来链接
libm
,或者解释“不工作”是什么意思。@Hanspetersoft,如果powf不工作,那么就实现它。@Hanspetersoft:我为您编写了一个替换函数,以防您的系统真的没有
pow()
,如果您最终编写了一个自定义的
myexp10
,您也可以只编写一个自定义的
float my_decimal_part(const char*)
。stm32上不存在STROD,sscanf似乎无法工作。我的buf如下所示:buf={'1','0','0','0','9','\n','\0','\0'..},val是一个浮点数。然后我这样称呼它:sscanf(buf、%f、&val);但是val变成了一个随机的非常小的值。@HansPeterLoft奇怪的是,
strod
不可用。我想你包括了stdlib.h,对吧?给定
buf
的内容,
sscanf
应该可以工作,假设
val
是一个
float
,而不是一个
double
。字符串是像
char*s1=“100”这样的负数吗;char*s2=“-09”
“-100”;"-09";
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);