LabWindows/CVI

cancel
Showing results for 
Search instead for 
Did you mean: 

string to double

Hi,
I have an issue using the Fmt function, I d like to convert an hexadecimal string which value is actually 0023 and I tried to use this  Fmt(&T, "%d<%s", Data); but I receive an error
" NON-FATAL RUN-TIME ERROR:   "RS232C communication.c", line 304, col 9, thread id 0x00001518:   Parameter type incompatible with format specifier."
I have tried other way to convert it like T = strtod(Data, EndPtr); and I get the error
" FATAL RUN-TIME ERROR:   "RS232C communication.c", line 305, col 16, thread id 0x000003DC:   Missing terminating null in string argument."
is ther a way to simply get the 23 value to a double value according to the fact that if the Data is A500 the double value must be -150.0 and if it is F015 the double value must be -15 .
in other words if first byte is A conversion is -1byte2byte3.byte4 and if the first byte is F conversion become -byte2byte3byte4.

Tahnks

Olivier


0 Kudos
Message 1 of 8
(6,917 Views)
first, your first statement is totally wrong...

Fmt(&T, "%d<%s", Data);
here you are asking to format an integer into a string. %d does not stand for double, but for decimal !
what you want to do is : Scan( Data, "%s > %f", &T );


the error you get from your second statement seems pretty obvious: is Data NULL terminated ? i mean, try it with Data declared as:
char *Data = "0023";
and strtod should return 23.0.
now if you want to parse a hexadecimal string, you will have to tell it in your format string. but be aware that an hexadecimal value do always represent an integer, not a double !
T = strtol( "0023", NULL, 16 );
this should return 35.0

the same using CVI formatting functions:
long value;
Scan( Data, "%s > %x", &value );
T = value;

finally, you said:
"is ther a way to simply get the 23 value to a double value according to the fact that if the Data is A500 the double value must be -150.0 and if it is F015 the double value must be -15"
this does not make any sense. what is the algorithm for converting 0xA500 to -150 (ican't see any 150 anywhere) ? same question for  0xF015 to -15 ? are the 2 algorithm identical ? how does 0x0023 fit into this algorithm and what should be the resulting value ?

0 Kudos
Message 2 of 8
(6,906 Views)
Hi,
Yes you are right I mistaken I have modified my code as you adviced Scan( Data, "%s > %f", &T );    Attempt to read beyond end of string.  and the point is that Data string is 4 bytes data comming from a RS232 acquisition thus it does not contain any null terminated, how should I add the null terminating argument to my string.
Here is how I picked up data from the rs232 frame

Buffer value is @0010000002370*


int  DecodeData (char *Buffer)
{
    char *Parameter;
    char *EndCode;
    char *Data;
     
    Parameter=(char*)malloc(3*sizeof(char));
    EndCode=(char*)malloc(3*sizeof(char));
    Data=(char*)malloc(10*sizeof(char));
   
    *Buffer++; //@
    *Buffer++;
    *Buffer++; //unit NO
    *Buffer++; //R/W
   
    strncpy(Parameter, Buffer, 2);
   
    *Buffer++;                                                 
    *Buffer++; //Parameter NO
       
    *Buffer--;
    *Buffer--;
    *Buffer--;
    *Buffer--;
    *Buffer--;
   
    EndCode = ByteToString(Buffer, 2);
   
    *Buffer++;
    *Buffer++;
    *Buffer++;
    *Buffer++;
   
    Data = ByteToString (Buffer, 4);
   
    Scan( Data, "%s > %f", &T );

the byte to string function is only doing the following operation

char *ByteToString(char *String, int NumOfByte)
{
    int i;
    char *OutputString;
    char *TempString;
    OutputString = (char*)malloc(NumOfByte*sizeof(char));
     
    strncpy(OutputString, String, NumOfByte);
       
    return OutputString;
}


finally, you said:
"is ther a way to simply get the 23 value to a double value according to the fact that if the Data is A500 the double value must be -150.0 and if it is F015 the double value must be -15"
this does not make any sense. what is the algorithm for converting 0xA500 to -150 (ican't see any 150 anywhere) ? same question for  0xF015 to -15 ? are the 2 algorithm identical ? how does 0x0023 fit into this algorithm and what should be the resulting value ?

The algorithm to decode the frame is used for a specific temperature regulator Omron. it is given this way by Omron
This section describes commands and response in detail. The conventions used in this section and data restrictions are as follows:
*Data is expressed in 1-byte units and in ASCII code.
*When the read or write data is a numerical value, the data to be set must conform to the following conditions:
(1) the decimal point"." is not indicated in fractions.
(2) the leftmost bit of minus numerical data must be expressed as follows:
A: -1, F: -(minus)
[example]
10.0 = [0100], -150.0=[A500], -15 = [F015]

Hope this will be more clear to you

Thanks

Olivier

0 Kudos
Message 3 of 8
(6,900 Views)
to add a null character at the end of a string... just allocate the string 1 byte longer and copy a null character here ?

char *ByteToString(char *String, int NumOfByte)
{
    int i;
    char *OutputString;
    char *TempString;
    OutputString = (char*)malloc((NumOfByte+1)*sizeof(char));
     
    strncpy(OutputString, String, NumOfByte);
    strcpy( OutputString + NumOfByte, "" ); // my way of making clear we are null terminating the string
    // a more standard way is : OutputString[NumOfByte] = '\0'
       
    return OutputString;
}


now for DecodeData: you declare it as:
int  DecodeData (char *Buffer)
buffer is a string, it is a pointer to a succession of chars. so why do you write:
*Buffer++ ? Buffer++ is plainly sufficient to move through the string, the * is useless (and the compiler should issue a warning about the value of the expression not being used). or is it that Buffer is not declared correctly ?


what are this bunch of
*Buffer--; in the middle ? you go forward in the string then go backward, then go forward again.

what i read from your function could be shortened to:
Parameter=(char*)malloc(3*sizeof(char));
EndCode=(char*)malloc(3*sizeof(char));
Data=(char*)malloc(10*sizeof(char));

EndCode = ByteToString(Buffer+1, 2);
strncpy(Parameter, Buffer+4, 2);
Data = ByteToString (Buffer+5, 4);

and there is something wrong here, since parameter and data overlaps by 1 byte. i hope there is something missing in the code you posted... (also, strncpy does not move the pointer: you already know that, but i want to make sure).

finally, about the specifications of the format, yes it is clear now. it is clear that the specification from Omron is kind of messy, over-complicated and i understand why you are struggling soing that given such a shit protocol. and to answer your original question, you will have to perform the conversion by hand since there is no built-in function to perform such a conversion.
0 Kudos
Message 4 of 8
(6,891 Views)
Hi
I have tried using the CVI formatting function code you gave me Scan( Data, "%s > %x", &value );T = value;

but I still get the error
"   Error at or near character 4 in the format string: Illegal separator character or illegal position of separator character."

Thanks and sorry for my lacks I am a CVI beginner

Olivier

0 Kudos
Message 5 of 8
(6,889 Views)

In my opinion all of your code could be simplified as follows:

strncpy (EndCode, buffer + 1, 2); EndCode[2] = 0;
strncpy (Parameter, buffer + 4, 2); Parameter[2] = 0;
strncpy (Data, buffer + 10, 4); Data[4] = 0;

As you can see I am forcing a termination byte on every target string since, as stated in the online documentation, strncpy DOES NOT add it.

After this, you will have to decode the measurement string Data, that could be solved this way:

char buf[32];
double val;

if (Data[0] == 'F')
 sprintf (buf, "-%s", Data + 1);
else if (Data[0] == 'A')
 sprintf (buf, "-1%s", Data + 1);
else
 strcpy (buf, Data);
val = atof (buf) / 10.0;       // <=== ???
DebugPrintf ("%s = %f\n", Data, val);

But it remains an uncertainty on the "/ 10.0" since it does not sound good in decoding F015 to -15...



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 6 of 8
(6,887 Views)
Hi,
Thanks very much both of you
it works, and as you said there's still a misunderstanding point I must ask to omron on th 10.0 value

Thanks again.

Olivier
0 Kudos
Message 7 of 8
(6,882 Views)
> I have tried using the CVI formatting function code you gave me Scan( Data, "%s > %x", &value );T = value;
> but I still get the error
> "   Error at or near character 4 in the format string: Illegal separator character or illegal position of separator character."


yes, the format string should be "%s>%x" (no spaces). i overlooked this a little too much...
0 Kudos
Message 8 of 8
(6,880 Views)