From Friday, April 19th (11:00 PM CDT) through Saturday, April 20th (2:00 PM CDT), 2024, ni.com will undergo system upgrades that may result in temporary service interruption.

We appreciate your patience as we improve our online experience.

LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

Scan for float in string

Solved!
Go to solution

Hi,

I'm trying to read a 4 byte IEEE 754 float from a string (array of char) using the scan function. I tried all kinds of formatting versions described in the help but I can't get it work proper. I receive a the string from a COM port. It looks like this in Hex (the float value is in [] brackets):

 

FF FF FF FF 86 1A 1E 6C 82 22 01 07 00 00 11 [C0 52 8F 9F] DB FF ...

 

The string format is always like this. The first 15 bytes are some commands I want to skip and then I need to read bytes 16, 17, 18 and 19. The result in this case should be -3.290016.

 

Here is the last of my many attempts to extract the float:

 

char buffer[24];

float myFloatVal=0;

...

Scan(buffer, "%4f[i15b4]", &myFloatVal);

 

This example returns "0" for myFloatVal.

Any advice would be most welcome!

 

 

 

0 Kudos
Message 1 of 10
(5,347 Views)
Solution
Accepted by topic author rdwitt

That Scan conversion seems a bit tricky: while it performs well with doubles I am not be able to make it work with floats too Smiley Frustrated

 

I can suggest you a possible workaround with sscanf:

 

sscanf (buffer + 15, "%c%c%c%c", (char *)&myFloatVal + 3, (char *)&myFloatVal + 2, (char *)&myFloatVal + 1, (char *)&myFloatVal);

 



Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
Message 2 of 10
(5,335 Views)

Roberto's solution is goog and probably more simple than bit considerations, as explained here :

http://en.wikipedia.org/wiki/Single-precision_floating-point_format

 

I know that it's not LV forum but the following LV implementation could be done with CVI as well...Anyway, Roberto's workaround is smarter ! ^^

Bit Handling (with LV).JPG

0 Kudos
Message 3 of 10
(5,327 Views)

Hi Roberto,

thank you for your reply.

I found a workaround myself but yours is much more elegant!

I masked each byte of the buffer with a unsigned short int. Then rotated each byte to the corresponding position of a float. Transferred everything to a 4 byte int with a or mask and finally cast this int to a float. As I said: It's a bit plump, but if your interested have a look:

 

char buffer[24]={0};
float myFloatVal;
unsigned short int a,b,c,d,erg;

 

a = 0x000000FF;
a = a & buffer[15];
a = a << 24;
b = 0x000000FF;
b = b & buffer[16];
b = b << 16;
c = 0x000000FF;
c = c & buffer[17];
c = c << 8;
d = 0x000000FF;
d = d & buffer[18];
erg = 0x00000000;
erg = erg | a;
erg = erg | b;
erg = erg | c;
erg = erg | d;

myFloatVal=*((float*)&erg);

Thank you for your help!

0 Kudos
Message 4 of 10
(5,325 Views)

Hi rdwitt,

I assume that there may be problems in using shorts in your implementation: what happens when you shift a value 16 or 24 bits to the left. i.e. out of short boundaries? And on the final line?

In effect your code returns a "Dereference of a 4 byte object where only 2 bytes exist" on my machine on the cast the ends the process.

Defining all of them as int, nevertheless, gives correct results.



Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
0 Kudos
Message 5 of 10
(5,318 Views)

You are right,

I made a mistake while writing the code to the post. You see I'm using a computer which is not connected to the www due to some security guidelines. So it was fastest to copy the code manually..

Originally I used unsigned ints.

Thanks again

0 Kudos
Message 6 of 10
(5,302 Views)

@Julien_2831

In the sake for simplicity, you could use this method: Smiley Wink

 

Cast units.png

 

I agree that this is not the correct forum, I simply wanted to place a little comment on your solution.



Proud to use LW/CVI from 3.1 on.

My contributions to the Developer Community
________________________________________
If I have helped you, why not giving me a kudos?
0 Kudos
Message 7 of 10
(5,292 Views)

You're perfectly right ! Smiley Very Happy

Obvious now, but I had not even thought about it before ! Thank's.

 

For CVI :

unsigned int U32_Value = 0xC0528F9F;
float Scal_Value = 0;

Scal_Value = * (float *) &U32_Value;

 

Anyway, since the need was to cast 4 char into 1 float, the solution you provided previously is definitely the best.

0 Kudos
Message 8 of 10
(5,284 Views)

Another option would be memcpy:

char buffer[24];

float myFloatVal=0;

...

memcpy(&myFloatVal,&buffer[15],4);

Message 9 of 10
(5,255 Views)

Ah oui ! Very good !

0 Kudos
Message 10 of 10
(5,226 Views)