learningpal
learningpal

Reputation: 359

Convert hex to float in C

I have a hexdecimal no. string and I want to convert it into float. Can anyone suggest any idea? I searched here in this forum and i got one post mentioning the following solution. I understood that first string is converted to hex number and then hex no is converted to float. But I didn't understand how this float_data = *((float*)&hexvalue); is taking place. And the code also does not work with this method too.

Correction 1: I think i didn't mention clearly here. sorry for this. This hex value 39 39 2e 30 35 when converted to ascii, then it gives 99.05. And I need this ascii as float no. Following is my code:

#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;
}

Upvotes: 0

Views: 6760

Answers (3)

chux
chux

Reputation: 153456

Scan using "%hhx" into a character array, append the null character and then convert to float using atof() or strtod().

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

Output

99.050003

[edit] Available since C99, With scanf():

hh Specifies that a following d, i, o, u, x, X, or n conversion specifier applies to an argument with type pointer to signed char or unsigned char. C11dr §7.21.6.2 11

Upvotes: 2

MikeCAT
MikeCAT

Reputation: 75062

This code will do the new conversion, supporting arbitrary length of input.

#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;
}

Error checking isn't done, so please add them if needed.

Upvotes: 1

MikeCAT
MikeCAT

Reputation: 75062

float_data = *((float*)&hexvalue); considers &hexvalue as a pointer to float and then read the data from where &hexvalue points as float.

Thid code may work, depending on the environment.

#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;
}

Upvotes: 1

Related Questions