【问题标题】:Convert hex to float in C在C中将十六进制转换为浮点数
【发布时间】:2015-12-28 10:13:08
【问题描述】:

我有一个十六进制数字。字符串,我想将其转换为浮点数。任何人都可以提出任何想法吗?我在这个论坛中搜索了这里,我得到了一篇提到以下解决方案的帖子。我知道第一个字符串被转换为十六进制数字,然后十六进制数字被转换为浮点数。但我不明白float_data = *((float*)&hexvalue); 是如何发生的。而且代码也不适用于这种方法。

更正1:我想我在这里没有明确提及。非常遗憾。这个十六进制值 39 39 2e 30 35 转换为 ascii 时,它会给出 99.05。我需要这个ascii作为浮点数。 以下是我的代码:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main()
{
    char *my_data;
    double float_data;
    unsigned int hexvalue;
    my_data = malloc (100);
    my_data =strcpy(my_data, "39 39 2e 30 35");
    sscanf (my_data, "%x", &hexvalue);
    float_data = *((float*)&hexvalue);
    printf ("the floating n. is %f", float_data);
    free (my_data);
    return 0;
}

【问题讨论】:

  • 预期输出是什么?
  • 这很好奇;很少有系统的浮点数是 5 个字节长。你应该怎么做?小数点在哪里?将单个字节转换为float 不太可能产生有用的值。 malloc()strcpy() 似乎是多余的。也许您已经剥离了很多代码并将其提炼出来;内存管理行是多余的,但也许更容易解释(一个 MCVE — How to create a Minimal, Complete, and Verifiable Example?)。

标签: c floating-point hex


【解决方案1】:

使用"%hhx" 扫描到字符数组,附加空字符,然后使用atof()strtod() 转换为float

int main(void) {
  unsigned char uc[5+1];
  sscanf("39 39 2e 30 35", "%hhx%hhx%hhx%hhx%hhx", &uc[0], &uc[1], &uc[2], &uc[3], &uc[4]);
  uc[5] = 0;
  float f = atof(uc);
  printf("%f\n", f);
  return 0;
}

输出

99.050003

[编辑] 自 C99 起可用,带有 scanf()

hh 指定以下diouxXn 转换说明符适用于类型指针指向@987654336 的参数@ 或 unsigned char。 C11dr §7.21.6.2 11

【讨论】:

  • 你能解释一下格式说明符%hhx代表什么吗?
【解决方案2】:

float_data = *((float*)&amp;hexvalue);&amp;hexvalue 视为指向float 的指针,然后从&amp;hexvalue 指向float 的位置读取数据。

此代码可能工作,具体取决于环境。

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main()
{
    char *my_data;
    double float_data;
    unsigned int hexvalue[4];
    unsigned char floatdata_hex[4];
    int i;
    my_data = malloc (100);
    strcpy(my_data, "39 39 2e 30 35"); /* the assignment isn't needed */
    /* the original code will read only one hex value, not four or five */
    sscanf (my_data, "%x%x%x%x", &hexvalue[0], &hexvalue[1], &hexvalue[2], &hexvalue[3]); /* read to int */
    for (i = 0; i < 4; i++) floatdata_hex[i] = hexvalue[i]; /* and convert them to char later */
    float_data = *((float*)floatdata_hex);
    /* the value may be too small to display by %f */
    printf ("the floating n. is %.15g", float_data);
    free (my_data);
    return 0;
}

【讨论】:

  • float_data = *((float*)floatdata_hex); 违反了严格的别名规则,因此它是未定义的行为。
  • 非常感谢@MikeCAT:您的代码有效。对不起,我歪曲了这个问题。但是您的代码解释了这个概念。
【解决方案3】:

此代码将进行新的转换,支持任意长度的输入。

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

double ascii_string_to_float(const char *str)
{
    double ret = 0.0;
    char *work1;
    char *work2;
    char *tok, *out;
    size_t len = strlen(str);
    work1 = malloc(len + 1);
    work2 = malloc(len + 1);
    if (work1 == NULL || work2 == NULL)
    {
        if (work1 != NULL) free(work1);
        if (work2 != NULL) free(work2);
        exit(1);
    }
    strcpy(work1, str);
    out = work2;
    tok = strtok(work1, " ");
    do {
        int tmp;
        sscanf(tok, "%x", &tmp);
        *(out++) = tmp;
    } while ((tok = strtok(NULL, " ")) != NULL);
    *out = '\0';
    sscanf(work2, "%lf", &ret);
    free(work1);
    free(work2);
    return ret;
}

int main(void)
{
    const char *my_data = "39 39 2e 30 35";
    double float_data;
    float_data = ascii_string_to_float(my_data);
    printf("the floating n. is %f", float_data);
    return 0;
}

错误检查未完成,如有需要请添加。

【讨论】:

    猜你喜欢
    • 2014-03-01
    • 2010-12-08
    • 1970-01-01
    • 2016-06-02
    • 1970-01-01
    • 2016-06-01
    • 2020-07-28
    • 1970-01-01
    相关资源
    最近更新 更多