editing a single character and problem with ForEach
editing a single character and problem with ForEach
Hi all,
I would appreciate if any of you could help me with a few things:
1. I'm wondering if there's a way of changing/removing a single character from the string, either by doing it with peek/poke or by other means.
In some other languages, I can exploit string=array of characters:
<
string test="test";
test[0]="b";
>
and change test to best.
2. I also have a problem with foreach: it seems like accessing elements of the map manually inside it makes an endless loop, so how are you supposed to do it then?
<
newMap person.s()
person("1")="p1"
person("2")="p2"
current=1
forEach person()
debug mapKey(person())
person(""+current)="p1"
next
>
3. How can I GoTo a label in the global scope from within a procedure?
<
procedure test()
goTo jumpHere
endProcedure
goTo afterJump
global jumpHere:
debug "jumped"
afterJump:
;do something else
>
A reply on one of the topics says to use !jmp l_jumpHere, but that doesn't seem to work.
Any help would be greatly appreciated.
I would appreciate if any of you could help me with a few things:
1. I'm wondering if there's a way of changing/removing a single character from the string, either by doing it with peek/poke or by other means.
In some other languages, I can exploit string=array of characters:
<
string test="test";
test[0]="b";
>
and change test to best.
2. I also have a problem with foreach: it seems like accessing elements of the map manually inside it makes an endless loop, so how are you supposed to do it then?
<
newMap person.s()
person("1")="p1"
person("2")="p2"
current=1
forEach person()
debug mapKey(person())
person(""+current)="p1"
next
>
3. How can I GoTo a label in the global scope from within a procedure?
<
procedure test()
goTo jumpHere
endProcedure
goTo afterJump
global jumpHere:
debug "jumped"
afterJump:
;do something else
>
A reply on one of the topics says to use !jmp l_jumpHere, but that doesn't seem to work.
Any help would be greatly appreciated.
Re: editing a single character and problem with ForEach
You can use ReplaceString with the #PB_String_InPlace mode to change strings and also RemoveString which will do the removing thing.nsstudios wrote:I'm wondering if there's a way of changing/removing a single character from the string
Code: Select all
Define.S sString
sString = "test"
ReplaceString(sString, "t", "b", #PB_String_InPlace, 1, 1)
Code: Select all
Procedure AlterString(*Source, Position.I, New.C)
Protected *Position
*Position = *Source + ((Position - 1) * SizeOf(Character))
PokeC(*Position, New)
EndProcedure
Define.S sString
sString = "test"
Debug sString
AlterString(@sString, 1, 'b')
Debug sString
Use PushMapPosition before an update and PopMapPosition afterwards to preserve the position pointer.nsstudios wrote:I also have a problem with foreach
Code: Select all
NewMap person.s()
person("1")="p1"
person("2")="p2"
current=1
ForEach person()
Debug MapKey(person())
PushMapPosition(person())
person(""+current)="p1"
PopMapPosition(person())
Next
I'd say don't do this, it's just asking for extra bugs to fix. Either you'll be leaving an unreturned call on the stack which will mess up returns down the line. Or you'll be jumping back into the procedure later on to pick up the sequence at the following point; in which case there's no need muck about with jumps outside of the procedure - just put the code inside the procedure.nsstudios wrote:How can I GoTo a label in the global scope from within a procedure?
If you want to write a section of multipurpose code to work the same in several procedures but in the context of the parent procedure separately put it in a macro and call the macro inside the procedures (once it works properly - the debugger doesn't follow code jumps into macros fully which means you can't step through them).
Last edited by spikey on Sun Dec 08, 2019 3:33 pm, edited 1 time in total.
Re: editing a single character and problem with ForEach
1.
There are many ways to do this depending on how your define your string variable and if you want to replace many characters at once. This is a simple way using PB string lib.
2.
3.
I do not recommend jumping out of Procedures.
Instead, set a global status variable or structure element inside your procedures.
On return from any procedure, check your status variable and take appropriate action.
EDIT: spikey beat me!
There are many ways to do this depending on how your define your string variable and if you want to replace many characters at once. This is a simple way using PB string lib.
Code: Select all
Define.s s$ = "test"
Define.i iPos = 3
Define.s s2$ = "b"
Debug ReplaceString(s$, Mid(s$, iPos, 1), s2$, #PB_String_CaseSensitive, iPos, 1)
Code: Select all
NewMap person.s()
person("1")="p1"
person("2")="p2"
current=1
ForEach person()
Debug MapKey(person()) + " = " + person()
Next
I do not recommend jumping out of Procedures.
Instead, set a global status variable or structure element inside your procedures.
On return from any procedure, check your status variable and take appropriate action.
EDIT: spikey beat me!
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
Re: editing a single character and problem with ForEach
Well that makes a change!skywalk wrote:EDIT: spikey beat me!
Re: editing a single character and problem with ForEach
1. Debug ReplaceString("test", "t", "b", 0, 0, 1)
2. You change second key to first key name, so ForEach loop forever
3. Goto: forget it! No one uses that anymore. (last time was in 90' in Gwbasic)
2. You change second key to first key name, so ForEach loop forever
3. Goto: forget it! No one uses that anymore. (last time was in 90' in Gwbasic)
Re: editing a single character and problem with ForEach
1. I'm wondering if there's a way of changing/removing a single character from the string, either by doing it with peek/poke or by other means.
In some other languages, I can exploit string=array of characters:
Code: Select all
test$ = "test"
Debug test$
PokeS(@test$, "c", 1, #PB_Unicode | #PB_String_NoZero) ;only for replacing
Debug test$
Re: editing a single character and problem with ForEach
Or just with PokeC() (that's what spikey did in his function anyway)
Code: Select all
test$ = "test"
Debug test$
pos = 0
PokeC(@test$ + SizeOf(Character) * pos, 'c')
Debug test$
Re: editing a single character and problem with ForEach
I do not recommend treating your MapKey as if they are string variables. (At least, until you thoroughly understand them.) Instead, treat them as the index they are, and use them to look up the data they reference (the "p1"). If you need to store strings that are modified, then use a string, either in a list or an array.
If you really need to use the key as a variable, then you will want to add and remove keys as needed. Otherwise, your code will do odd things like your endless ForEach loop.
If you really need to use the key as a variable, then you will want to add and remove keys as needed. Otherwise, your code will do odd things like your endless ForEach loop.
Re: editing a single character and problem with ForEach
Thank you all for speedy, super useful replies.
I ran into the infinite forEach when I had to do something to a specific element if the currently selected element did something, e.g.
<
forEach user()
if user()\away
send(user(current)\id, user()\name+" is away.")
endIf
;do something else
next
>
which I'm not sure the push and pop trick would work for, but good to know I can do that in other cases.
I ran into the infinite forEach when I had to do something to a specific element if the currently selected element did something, e.g.
<
forEach user()
if user()\away
send(user(current)\id, user()\name+" is away.")
endIf
;do something else
next
>
which I'm not sure the push and pop trick would work for, but good to know I can do that in other cases.
Re: editing a single character and problem with ForEach
Code: Select all
Use code tags in your posts.
Code: Select all
NewMap person.s()
person("1")="p1"
person("2")="p2"
person("3")="p3"
Debug "--BEFORE CHANGES--"
ForEach person()
Debug MapKey(person()) + " = " + person()
Next
ResetMap(person()) ; Move pointer to BEFORE 1st element.
While NextMapElement(person()) ; Move pointer to next element.
r$ = MapKey(person())
PushMapPosition(person())
ForEach person() ; Starts with 1st element.
If person() = "p1"
person("2") = "p1 made me do it!"
Else
; do other stuff...
EndIf
Next person()
PopMapPosition(person())
Wend
Debug "--AFTER CHANGES--"
ForEach person()
Debug MapKey(person()) + " = " + person()
Next
Last edited by skywalk on Sun Dec 08, 2019 6:32 pm, edited 1 time in total.
The nice thing about standards is there are so many to choose from. ~ Andrew Tanenbaum
Re: editing a single character and problem with ForEach
Your initial example actually modified the key. This is bad practice. Your latest example does not do this.
Not sure if you've grasped the map variable concept, or if you just had wonky examples. Just in case...
You should be using the map as a variable to store the "away" status--do not use the map key as the variable. The first way you were trying to do it is not good practice. The map key, in this instance, should not be treated as a string variable, but rather, the variable name. The variable itself (i.e. the status) is the assignment (="away"...but I would use a flag instead of a string).
The later example looks better, and should not be endless. Like this one, use a Structure if you want to store the status of "Name". You can make a structure accessed within a map if you want more data than just the status, and you want it referenced by the Name.
Think of the mapkey as a door key; the key opens the door. You use a different key when you want to open a different door. Using this analogy, you do not modify your key just because you want to open a vacation house door rather than a living house door. Instead, you grab a different key. Maps are kind of like arrays, but instead of (0) and (1), you reference by ("Tom") and ("Harry")
Not sure if you've grasped the map variable concept, or if you just had wonky examples. Just in case...
You should be using the map as a variable to store the "away" status--do not use the map key as the variable. The first way you were trying to do it is not good practice. The map key, in this instance, should not be treated as a string variable, but rather, the variable name. The variable itself (i.e. the status) is the assignment (="away"...but I would use a flag instead of a string).
The later example looks better, and should not be endless. Like this one, use a Structure if you want to store the status of "Name". You can make a structure accessed within a map if you want more data than just the status, and you want it referenced by the Name.
Think of the mapkey as a door key; the key opens the door. You use a different key when you want to open a different door. Using this analogy, you do not modify your key just because you want to open a vacation house door rather than a living house door. Instead, you grab a different key. Maps are kind of like arrays, but instead of (0) and (1), you reference by ("Tom") and ("Harry")
Re: editing a single character and problem with ForEach
@Tenaja, My original example may have been off, but my point was to demonstrate that forEach goes into the endless loop if I manually access specific map elements inside it.
Thanks @skywalk for the tip.
I'll try to use code tags in the future.
Thanks @skywalk for the tip.
I'll try to use code tags in the future.
Re: editing a single character and problem with ForEach
What else should happen if you always reset the map pointer.nsstudios wrote:My original example may have been off, but my point was to demonstrate that forEach goes into the endless loop if I manually access specific map elements inside it.
sorry for my bad english
Re: editing a single character and problem with ForEach
It's a few extra lines, but you can read and edit characters of a string as an array like this:
Code: Select all
test.s = "test"
Debug test
Structure CharacterArray
c.c[0]
EndStructure
*CA.CharacterArray = @test
*CA\c[0] = 'b'
*CA\c[2] = 'a'
Debug test
Re: editing a single character and problem with ForEach
Thanks @kenmo!
I was trying to do something like that, but didn't get it quite right.
I was trying to do something like that, but didn't get it quite right.