Home AMX User Forum NetLinx Studio

Assignment in a while guard

A long time ago I was writing some code and wanted to use C style as in:

while(pos = find_string(sRxBuf, "$0D", 1))
{
// code
}

I can't recall exactly why this didn't work at the time, but it compiles. I seem to remember that it wouldn't evaluate correctly but I might be wrong. Does anyone use this without issue? I wonder if I might have had some other error that fooled me into thinking this wouldn't work.
Paul

Comments

  • You could rejig it to something like:
    pos = find_string(sRxBuf, "$0D", 1)
    while(pos)
    {
      // code
      pos = find_string(sRxBuf, "$0D", 1)
    }
    

    not tested or anything and not sure why your original version doesn't work unless sRxBuf contents never change.
  • a_riot42a_riot42 Posts: 1,624
    regallion wrote: »
    You could rejig it to something like:
    pos = find_string(sRxBuf, "$0D", 1)
    while(pos)
    {
      // code
      pos = find_string(sRxBuf, "$0D", 1)
    }
    

    not tested or anything and not sure why your original version doesn't work unless sRxBuf contents never change.

    Yes that is another way, but calling find_string only once is more elegant imho. Its odd that it compiles but I don't believe will work as it does in C.
    Paul
  • a_riot42,

    i don't think your initial code calls find_string only once. i am using the while(find_string.... to parse feedback from devices and it calls find_string for as many times as the searchable string exists.

    Kostas
  • DHawthorneDHawthorne Posts: 4,584
    There are some oddities in NetLinx about boolean evaluations. There are cases where a zero value may be evaluated as true ... I suspect it only evaluates null as false in those cases, but I couldn't tell you what the cases are. There is something happening under the hood that makes this happen ... always an issue with an interpreted language, sometimes the rules aren't visible. Try evaluation pos as <> 0 instead, and see what that does for you.
  • What exactly are you trying to accomplish?

    In your code, you don't show how you initialize pos?

    If you want pos to equal "find_string(sRxBuf, "$0D", 1)", then what were you wanting to evaluate in the while() statement?

    Netlinx cannot do both. At least not in the way you originally suggested.

    You can also do the following:

    while (find_string(sRxBuf, "$0D", 1))
    {
    pos=find_string(sRxBuf, "$0D", 1)
    }

    but that isn't necessarily any cleaner that what others have suggested.
  • a_riot42a_riot42 Posts: 1,624
    I was just trying to do what I do in C where you can have an if or while and do an assignment at the same time. So you can do this:

    if (pos = find_string(sRxBuf, "0D", 1)))

    and what would happen is that the function gets called and the result is stored in pos. Then the if is evaluated on the value of pos. This way you can assign a value to pos, and then have it evaluated in the if guard. If find_string returns a positive number and so pos is a positive number then the if guard is true. If not, then its false. I don't think that Netlinx evaluates it the same way though, but I don't have a master here to try it on.
    Paul
  • a_riot42 wrote: »
    I was just trying to do what I do in C where you can have an if or while and do an assignment at the same time. So you can do this:

    if (pos = find_string(sRxBuf, "0D", 1)))

    and what would happen is that the function gets called and the result is stored in pos. Then the if is evaluated on the value of pos. This way you can assign a value to pos, and then have it evaluated in the if guard. If find_string returns a positive number and so pos is a positive number then the if guard is true. If not, then its false. I don't think that Netlinx evaluates it the same way though, but I don't have a master here to try it on.
    Paul

    I think Netlinx will interpret that as:
    if (pos = [the return of (find_string(sRxBuf,"0D",1)])

    It will not make pos equal the return of the function, but it will compare pos to the return of the function.
  • Joe HebertJoe Hebert Posts: 2,159
    the8thst wrote: »
    I think Netlinx will interpret that as:
    if (pos = [the return of (find_string(sRxBuf,"0D",1)])

    It will not make pos equal the return of the function, but it will compare pos to the return of the function.

    I believe that is the case as the following code demonstrates:
    DEFINE_DEVICE
    
    dvTP = 10001:1:0
    
    DEFINE_VARIABLE _
    
    INTEGER   nPos
    CHAR 	cBuffer[64]
    INTEGER	nLoopCount
    
    DEFINE_EVENT
    
    BUTTON_EVENT[dvTP,1] {
    
       PUSH: {
          
          
          cBuffer = "'The quick',$0D,'brown fox',$0D,'jumped over',$0D,'the lazy',$0D,'dog',$0D"
          nLoopCount=0
    
          nPos=FIND_STRING(cBuffer,"$0D",1)
          SEND_STRING 0,"'nPos before while=',ITOA(nPos)"
          
          
          WHILE (nPos=(FIND_STRING(cBuffer,"$0D",1))) {
          
    	 nLoopCount++
    	 SEND_STRING 0,"'nPos in while=',ITOA(nPos),' nLoopCount=',ITOA(nLoopCount)"
    	 SEND_STRING 0,"'Data=',LEFT_STRING(cBuffer,nPos-1)"
    	 REMOVE_STRING (cBuffer,"$0D",1)
    	      
          }
          SEND_STRING 0,"'Out of here, nPos after while=',ITOA(nPos)"
          
       }
    
    }
    
    The output after button 1 is pushed:
    Line      1 (15:05:40)::  nPos before while=10
    Line      2 (15:05:40)::  nPos in while=10 nLoopCount=1
    Line      3 (15:05:40)::  Data=The quick
    Line      4 (15:05:40)::  nPos in while=10 nLoopCount=2
    Line      5 (15:05:40)::  Data=brown fox
    Line      6 (15:05:40)::  Out of here, nPos after while=10
    

    *The quick* and *brown fox* are the same in length so the while evaluates to true for 2 passes and then drops out when it gets to *jumped over* The value of nPos never changes from the while condition.
  • a_riot42a_riot42 Posts: 1,624
    the8thst wrote: »
    I think Netlinx will interpret that as:
    if (pos = [the return of (find_string(sRxBuf,"0D",1)])

    It will not make pos equal the return of the function, but it will compare pos to the return of the function.

    I think you are right. This is likely because = and == have the same meaning in a if guard and there is no way around this that I know.
    Thanks,
    Paul
  • PhreaKPhreaK Posts: 966
    Yep, having no way to specify assignment over equality kills that approach.
  • HedbergHedberg Posts: 671
    a_riot42 wrote: »
    I think you are right. This is likely because = and == have the same meaning in a if guard and there is no way around this that I know.
    Thanks,
    Paul

    That is correct, as I understand it. In Netlinx, you can't do an assignment in the conditional expression. It may look like it should be an assignment, but it's not.
  • viningvining Posts: 4,368
    What if you change the while to a for?

    For(pos=find_string(sRxBuf, "$0D", 1);pos;pos=find_string(sRxBuf, "$0D", 1))

    It requires using find string twice but it should work.
  • a_riot42a_riot42 Posts: 1,624
    vining wrote: »
    What if you change the while to a for?

    You mean something like this:

    for (pos = find_string(sRxBuf, "$0D", 1) ; pos; )

    Good point. That might work just as well. That gets around the assignment/comparison problem in while/if guards. Does this work or is there some arcane Netlinx reason it wouldn't? I am leaving out the increment field, but most languages have no problem with that. Not sure about Netlinx.
    Paul
  • viningvining Posts: 4,368
    I see you were posting while I was editing. I believe you need the 3rd part of the loop to re-evaluate and set pos on each pass otherwise if pos is set in the initializing statement there's nothing to stop it on the 2nd or subsequent passes. I haven't tried this but I think it would work.

    For(pos=find_string(sRxBuf, "$0D", 1);pos;pos=find_string(sRxBuf, "$0D", 1))
  • a_riot42a_riot42 Posts: 1,624
    vining wrote: »
    I see you were posting while I was editing. I believe you need the 3rd part of the loop to re-evaluate and set pos on each pass otherwise if pos is set in the initializing statement there's nothing to stop it on the 2nd or subsequent passes. I haven't tried this but I think it would work.

    For(pos=find_string(sRxBuf, "$0D", 1);pos;pos=find_string(sRxBuf, "$0D", 1))

    Yes that will probably work. Not pretty to look at it but it would seem to work.
    Paul
  • jjamesjjames Posts: 2,908
    How about a function?

    Untested, but what about something like this? A function can assign your referenced variable, and return whether it succeeded or not - that's basically what you need - right?
    define_function char assignPosition(integer position)
    {
    	position = find_string(sRxBuf, "$0D", 1);
    	
    	if(position > 0)
    		return true;
    	
    	return false;
    }
    
    while(assignPosition(pos)) 
    {	
    // code using pos here
    }
    
  • mpullinmpullin Posts: 949
    DEFINE_FUNCTION PARSE(){ // process data in bufDEV
        if(LENGTH_STRING(bufDEVICE) == false) return;
        if(FIND_STRING(bufDEVICE,CRLF,1)){ // process just one line per function call (change if to while to process all lines at once)
    	PROCESS_FB(REMOVE_STRING(bufDEVICE,CRLF,1));
        }
    }
    
  • a_riot42a_riot42 Posts: 1,624
    mpullin wrote: »
    DEFINE_FUNCTION PARSE(){ // process data in bufDEV
        if(LENGTH_STRING(bufDEVICE) == false) return;
        if(FIND_STRING(bufDEVICE,CRLF,1)){ // process just one line per function call (change if to while to process all lines at once)
    	PROCESS_FB(REMOVE_STRING(bufDEVICE,CRLF,1));
        }
    }
    

    I don't think that will work if $0D also appears somewhere in the response, which in my case it does. Hard to believe the engineers would use the CRLF as both a delimiter and a command code but that's what they did. So if I send that command to the device it will respond with something like $02$0D$01$02$0D
    Paul
  • mpullinmpullin Posts: 949
    a_riot42 wrote: »
    I don't think that will work if $0D also appears somewhere in the response, which in my case it does. Hard to believe the engineers would use the CRLF as both a delimiter and a command code but that's what they did. So if I send that command to the device it will respond with something like $02$0D$01$02$0D
    Paul
    Well, if the protocol doesn't have a terminator your problem is more complicated regardless of what kind of loop you set up.
  • a_riot42a_riot42 Posts: 1,624
    mpullin wrote: »
    Well, if the protocol doesn't have a terminator your problem is more complicated regardless of what kind of loop you set up.

    True but if I was able to use the C style of assigning/comparing in the while guard, that would have made things easier. But yes, it was silly of them to do that, and the command isn't even some obscure never used command, its for volume :(
    Paul
  • vining wrote: »
    I see you were posting while I was editing. I believe you need the 3rd part of the loop to re-evaluate and set pos on each pass otherwise if pos is set in the initializing statement there's nothing to stop it on the 2nd or subsequent passes. I haven't tried this but I think it would work.

    For(pos=find_string(sRxBuf, "$0D", 1);pos;pos=find_string(sRxBuf, "$0D", 1))

    I think that will work. I would probably lean towards a recursive function to check the guard and set the assignment.
  • viningvining Posts: 4,368
    the8thst wrote: »
    I think that will work. I would probably lean towards a recursive function to check the guard and set the assignment.

    Personally I would just do it the standard way posted earlier:
    while (find_string(sRxBuf, "$0D", 1))
    {
    pos=find_string(sRxBuf, "$0D", 1)
    }
    

    You could also create your own function and pass back nPos by reference for use in the while.
Sign In or Register to comment.