Odd ATOI behaviour- why??
PHSJason
Posts: 66
Found this behavior when using ATOI and GET_BUFFER_CHAR together:
gives these results:
Line 330 (10:48:37):: VANTAGE CLIENTSTRING: RLS# 1 8 1 1$0D$0A
Line 331 (10:48:37):: VANTAGE BUFFER AFTER REMOVE: SW 1 8 1 0$0D$0ARSW 1 8 1 5 $0D$0A
Line 332 (10:48:37):: RLS# 1 8 1 FOUND
Line 333 (10:48:37):: VANTAGE CLIENTSTRING:1$0D$0A
Line 334 (10:48:37):: CIpLibrary::Atoi - Error
Line 335 (10:48:37):: Library Call error on Line 3649
Line 336 (10:48:37):: nBTNLED:
(nBTNLED is a LOCAL_VAR SINTEGER)
Adding double quotes fixes the problem:
As does the AMX recommended method of removing the GET_BUFFER_CHAR:
Why? What causes this and what is the rhyme/reason to how and why this works this way? Is GET_BUFFER_CHAR broken, or is ATOI broken, or, is there some anomaly when using them together? I have other chunks of code that use each of these and in looking through my code, there are places where I have had to add double quotes and other places where it works without them.
For instance, this works without the double quotes:
Is there a best practices lesson here?
ACTIVE(FIND_STRING (CLIENTSTRING, "'RLS# 1 8 1'",1)): //RETURN FROM VANTAGE PARTY BUTTON { SEND_STRING 0,"'RLS# 1 8 1 FOUND'" REMOVE_STRING (CLIENTSTRING, "'RLS# 1 8 1 '",1) SEND_STRING 0,"'VANTAGE CLIENTSTRING:',CLIENTSTRING" nBTNLED = ATOI(GET_BUFFER_CHAR(CLIENTSTRING)) SEND_STRING 0,"'nBTNLED: ',nBTNLED" IF (nBTNLED = 0) { OFF [devTPLIGHTS,30] //PARTY BUTTON } IF (nBTNLED = 1) { ON [devTPLIGHTS,30] //PARTY BUTTON } CLEAR_BUFFER CLIENTSTRING }
gives these results:
Line 330 (10:48:37):: VANTAGE CLIENTSTRING: RLS# 1 8 1 1$0D$0A
Line 331 (10:48:37):: VANTAGE BUFFER AFTER REMOVE: SW 1 8 1 0$0D$0ARSW 1 8 1 5 $0D$0A
Line 332 (10:48:37):: RLS# 1 8 1 FOUND
Line 333 (10:48:37):: VANTAGE CLIENTSTRING:1$0D$0A
Line 334 (10:48:37):: CIpLibrary::Atoi - Error
Line 335 (10:48:37):: Library Call error on Line 3649
Line 336 (10:48:37):: nBTNLED:
(nBTNLED is a LOCAL_VAR SINTEGER)
Adding double quotes fixes the problem:
nBTNLED = ATOI("GET_BUFFER_CHAR(CLIENTSTRING)")
As does the AMX recommended method of removing the GET_BUFFER_CHAR:
nBTNLED = ATOI(CLIENTSTRING)
Why? What causes this and what is the rhyme/reason to how and why this works this way? Is GET_BUFFER_CHAR broken, or is ATOI broken, or, is there some anomaly when using them together? I have other chunks of code that use each of these and in looking through my code, there are places where I have had to add double quotes and other places where it works without them.
For instance, this works without the double quotes:
nOUTPUT = ATOI(GET_BUFFER_STRING(OUTPUT,(LENGTH_STRING(OUTPUT)-1)))But this I had to add double quotes to:
nAPZONE = ATOI("LEFT_STRING(cAPBUTTONSTRING,LENGTH_STRING(cAPBUTTONSTRING)-1)")
Is there a best practices lesson here?
0
Comments
In fact, if you look at netlinx.axi, the ATOI function is defined as needing an argument of char a[]. You can get the same issue if you create your own function that takes an array of anything, even integers, as an argument and give it a dimensionless variable when you call the function.
If you compile the above code, the compiler will throw an error saying that there is a dimension mismatch, [1] vs. [0] and a type mismatch in call for parameter N. It will throw the same error for parameter 0 if you fix the call for the function to fnTest(nTestArray,nTestArray).
The same thing is going on with ATOI when you use get_buffer_char as the argument. It's return has a dimension of 0, so it doesn't fit the requirements for the function definition. It would be nice if the compiler would throw the error, rather than catching it at runtime, but that's the way it is.
Hope that helps.
On the other hand, if you expect the CLIENTSTRING to return more than one char number (e.g "12") then you could also use: to extract the first char and convert it to integer
Kostas
P.S.
Performing a numerous compilations in the following lines NEVER gave me an error. My NXS is v3.3.1.525 and NX Compiler v2.5.2.20
(nVAR1 is declared as an INTEGER and cTest as: CHAR cTest[6] both VOLATILE in DEFINE_VARIABLE section)
As Andrew mentioned atoi is expecting a string not a char so the double quotes does affectively create a string with a length of 1. You could also use atoi(get_buffer_string(cStr,1)) or as as previously stated atoi(cStr[1]) should also work.
ASCII as in $31.
ATOI is expecting a string or an array to be passed, a single CHAR variable will throw this error during runtime, but will compile.
In that case, would this cause the same error?
I am not in front of a system to compile and test on.
Is it a good rule of thumb to use the double quotes with ATOI in places where you may encounter a string length of 1? Are there any downsides to always using double quotes with ATOI expressions?
What was the value of nVAR1 at runtime here? Did all formats return the same value to nVAR1?
I am not seeing any compiler errors, just errors when the code runs and a var doesn't work the way that it should.
Yes, this should throw the runtime error. The cCHAR_VAR is not a string, but a single character. If you had declared it like so:
it would work and the value of nINT_VAR would be 2.
The initial value of nVAR1 is 0 and the initial value of cTest is '123456'.
Here are the results of the runtime behavior of the source code:
All the following statements throw a runtime Error:
and the following statements work as expected:
Kostas
Thank you for the clarification. Does this also apply to ITOA, HEXTOI, etc?
itoa(12) = '12'
atoi("'12'") = 12
hextoi("'12'") = 18
Also I would assume that any other conversion keyword like ATOL, ATOF, etc that uses a string as an input should also get double quotes.
Thanks again, and yet it goes against what AMX tech told me. AMX TECH (after conferring with another tech agent) had me omit the double quotes in the first example and just pass the entire string variable to ATOI and let it 'ignore' the unprintable characters or $OD, and $OA.
In a case where CLIENTSTRING = "'1',$0D, $0A",
I was told to not use this:
nBTNLED = ATOI("GET_BUFFER_CHAR(CLIENTSTRING)")
and to instead use this:
nBTNLED = ATOI(CLIENTSTRING)
Both of these work, however.
I prefer to use the top one, instead of relying on the system always properly ignoring the unprintable characters. but perhaps a better one would be:
nBTNLED = ATOI("LEFT_STRING(CLIENTSTRING,1)")
or
nBTNLED = ATOI("GET_BUFFER_STRING(CLIENTSTRING,1)")