Hi
I have noticed, when I call a SUB(String) then the string value from the SUB rutine return to main program.
Does this make any sense.
AUTODEFINE "OFF"
STRING MainString = "Main"
OPENCONSOLE
print tx(MainString)
print MainString
PRINT "Press any key to close"
WAITCON
SUB tx(STRING SubString),int
SubString = SubString + "???"
RETURN 0
ENDSUB
Perhaps I should start by reading the manual ::)
Sorry
That's normal operation.
Strings and UDTs are passed by reference, which means only the pointer to where the value is stored in memory.
If you want to pass a string or UDT to a sub and manipulate it within the subroutine only then define if BYVAL
SUB tx(STRING SubString BYVAL),int
Numbers work just the opposite. They are passed by value.
So, if you want to pass a number to a sub; modigy it in the sub; and have the change appear in the calling program then pass it BYREF.
SUB num(int xx BYREF),int
Thanks Larry
But if I try to manipulate it within the subroutine, the program go bananas.
SUB tx(STRING SubString BYVAL),int
SubString=SubString + "1234567890"
Now I just made a minor modification, and it works
SUB TX(STRING TXLocal),int
INT x:STRING TXData
TXData = RS485_StartFrame + RS485_SrcAddr + RS485_DstAddr + TXLocal
TXData=RS485_StartStop + TXData + CRC_HDLC(DataAsc,ChrHex2Asc(TXData)) + RS485_StartStop
FOR x = 1 to LEN(TXData) step 2
IWSendport(ComPort, CHR$(Hex2Dec(MID$(TXData,x,2))), 1)
NEXT x
Return 0
ENDSUB
QuoteBut if I try to manipulate it within the subroutine, the program go bananas.
SUB tx(STRING SubString BYVAL),int
SubString=SubString + "1234567890"
I'm not sure what you are talking about.
The only reason that should cause you problems is if
SubString + "1234567890" exceeds the maxlength that SubString was defined as outside the sub.
This works:
string x="abc"
print x
tx(x)
print x
SUB tx(STRING SubString BYVAL),int
SubString=SubString + "1234567890"
return 1
endsubThis will cause problems:
istring x[11]
string b=""
x="abc"
print x
tx(x)
print x
SUB tx(STRING SubString BYVAL),int
SubString=SubString + "1234567890"
b="q"
return 1
endsubThen you say:
QuoteNow I just made a minor modification, and it works
SUB TX(STRING TXLocal),int
INT x:STRING TXData
TXData = RS485_StartFrame + RS485_SrcAddr + RS485_DstAddr + TXLocal
TXData=RS485_StartStop + TXData + CRC_HDLC(DataAsc,ChrHex2Asc(TXData)) + RS485_StartStop
FOR x = 1 to LEN(TXData) step 2
IWSendport(ComPort, CHR$(Hex2Dec(MID$(TXData,x,2))), 1)
NEXT x
Return 0
ENDSUB
This is a major change; not a minor change.
In this sub you are not modifying the passed in variable in any way.
All you are doing is adding the passed in string to a local string.
Big difference.
The only place this last example can mess up is the length of the passed in string.
In the sub you defined TXData as a string which is a max of 255 characters.
That means that when you add the lengths of all of this up it can have no more than 255 characters.
Quotelength (RS485_StartFrame
+ RS485_SrcAddr
+ RS485_DstAddr
+ TXLocal
+ RS485_StartStop
+ TXData
+ CRC_HDLC(DataAsc,ChrHex2Asc(TXData))
+ RS485_StartStop)
<= 255
Larry
On my computer this code make this output.
Its the same with or with out BYVAL
First Time - BYVAL !!
First Time - BYVAL !!
Press any key to close
AUTODEFINE "OFF"
OPENCONSOLE
STRING MainString
MainString="First Time - "
TX(MainString)
Print MainString
PRINT "Press any key to close"
WAITCON
END
SUB tx(STRING SubString BYVAL),int
SubString=SubString + "BYVAL !!"
Print SubString
Return 0
ENDSUB
My Bad!
I finally found where it says (here in the forums) that BYVAL is ignored for strings.
So the only way to modify a passed string in a subroutine and have it not change the passed string is to use a temp string.
Like this:
AUTODEFINE "OFF"
OPENCONSOLE
STRING MainString
MainString="First Time - "
TX(MainString)
Print "Main program => ",MainString
PRINT "Press any key to close"
WAITCON
END
SUB tx(STRING SubString BYVAL),int
String t=SubString + "BYVAL !!"
Print "subroutine => ",t
Return 0
ENDSUB
or a variation:
AUTODEFINE "OFF"
OPENCONSOLE
STRING MainString
MainString="First Time - "
Print "subroutine => ",TX(MainString)
Print "Main program => ",MainString
PRINT "Press any key to close"
WAITCON
END
SUB tx(STRING SubString BYVAL),string
Return SubString + "BYVAL !!"
ENDSUB
Just for fun.
Had I written the 2 blocks of code above from scrath with IWB 2.x they
would have looked something like this:
AUTODEFINE "OFF"
STRING MainString="First Time - "
TX(MainString)
? "Main program => ",MainString
END
SUB tx(STRING SubString BYVAL),int
String t=SubString + "BYVAL !!"
? "subroutine => ",t
Return 0
ENDSUBand
AUTODEFINE "OFF"
STRING MainString="First Time - "
? "subroutine => ",TX(MainString)
? "Main program => ",MainString
END
SUB tx(STRING SubString BYVAL),string
Return SubString + "BYVAL !!"
ENDSUB
Larry
I did the same in this code with TXLocal
Im happy now, thought I was totally n...
Thanks Larry
SUB TX(STRING TXLocal,int
INT x:STRING TXData
TXData = RS485_StartFrame + RS485_SrcAddr + RS485_DstAddr + TXLocal
TXData=RS485_StartStop + TXData + CRC_HDLC(DataAsc,ChrHex2Asc(TXData)) + RS485_StartStop
FOR x = 1 to LEN(TXData) step 2
IWSendport(ComPort, CHR$(Hex2Dec(MID$(TXData,x,2))), 1)
NEXT x
Return 0
ENDSUB
i'm not going to say, i have read all of the post and maybe i have missed the point, you may need to read up on the Scope of Variables / Visibility of variables.
this is in C but the same principles apply across the board so to speak
Quotehttp://en.wikipedia.org/wiki/Scope_%28computer_science%29
OPENCONSOLE
'GLOBAL myString (not required)
string myString = "this is my string"
print myString
editstring()
print myString
do:until inkey$ <>""
CLOSECONSOLE
END
SUB editstring()
myString = myString + " modifiyed"
RETURN
ENDSUB
maybe ive missed the point
AUTODEFINE "OFF"
STRING MainString = "Main"
OPENCONSOLE
print MainString
print tx(MainString)
print MainString
PRINT "Press any key to close"
WAITCON
SUB tx(STRING SubString),STRING
SubString = SubString + "???"
RETURN SubString
ENDSUB
Copex - There are some subtle differences between the two examples you posted.
In the first the subroutine can be passed any string to modify.
In the 2nd the subroutine is dedicated to modifying a single string.
Also, in the first, the GLOBAL designation isn't need unless the app is a project and the variable is used in other source files.
What wasn't clear before was the use of BYVAL with string parameters to a sub
Turns out BYVAL is ignored for strings but can be used with other types that are normally passed by reference.
@larry you are right, i should have just deleted the post. i was looking at it from the scope of Variable been local to the sub routine and forgetting the rules of the programing language, as it is defined outside of the sub routine it is global to the source and as you stated the global command is not required.
though if you run the second example the last print MainString prints the modified text, though i never modified the MainString, so as stated i think i have completely missed the point.
Quote from: Copex on February 13, 2013, 02:00:22 AM
...i should have just deleted the post....
I don't see any need to. Your comments added to the discussion.
Your question may have helped some one else out who did not have the courage to ask it.
No question is stupid, if you don't know the answer. Better to ask, because you might be helping some one else out also.
Bill