Series of Variables by name - autohotkey

In AHK script:
Code for finding a value between great numbers of variables above, for one variable:
If (Variable1 = "sin (90°)")
MsgBox Value is reached
How searching by this method between series of variables with different value of number in their names? From Variable5 to Variable15, Variable51 to Variable105, etc.
How modify this code if number from 5 to 15, 51 to 105, or 74 to 117 etc?
number = 5
If (Variable%number% = "sin (90°)")
.............
Is %Variable%number%% acceptable and will works surely?
And here may also be useful Associative Arrays. What is it by simple examples?

Best practice here would probably be to use an array in the first place.
myArray := []
myArray[1] := "bla"
myArray.Push("bla2") ;by using this you don't need to worry about the index number
myArray[3] := "sin (90°)"
myArray[4] := 63456
Loop % myArray.MaxIndex()
{
If (myArray[A_Index] = "sin (90°)")
{
MsgBox Value is reached
}
}
... another example
anotherArray := []
Loop, read, C:\Files\prog.txt
{
If (A_LoopReadLine = "FileRead, OutputVar, C:\Files\prog1.txt")
{
anotherArray.Push(A_LoopReadLine)
MsgBox, An interesting code line was found. And was added to the array.
}
Else If (A_LoopReadLine = "blablabla")
{
anotherArray.Push(A_LoopReadLine)
MsgBox, An interesting code line was found. And was added to the array.
}
Else If (A_LoopReadLine = "some other text line")
{
anotherArray.Push(A_LoopReadLine)
MsgBox, An interesting code line was found. And was added to the array.
}
;Else
;{
; MsgBox, Nothing important was found.
;}
}
Loop % anotherArray.MaxIndex()
{
currentArrayEntry := anotherArray[A_Index]
MsgBox, %currentArrayEntry%
}

In an expression you can use variable expansion to modify the name of the variable to use:
number = 5
If (Variable%number% = "sin (90°)")
.............
But consider using arrays instead.

Is %Variable%number%% acceptable and will works surely?
Not. More right way
% Variable%number%
but it may have a problem.
Possible way is use Var := expression
Variable:= number
may be.

Related

Pass one function's output as parameter in another function

I want to pass the output of one function as a parameter of another function without relying on temp-variables. The ways it tried it, it either did not recognize it as a function, and thus outputed 1, or was just empty. Expected output for the example below should be a1.
I tried it with msgbox % functionb(% functiona(),1); msgbox % functionb(functiona.call(),1) and msgbox % functionb(func("functiona"),1).
Is there a way to do it?
msgbox % functionb(functiona.call(),1)
functiona() {
return a
}
functionb(Var1, Var2) {
output := Var1 Var2
return output
}
I think the proper way would be something like this:
msgbox % functionb(functiona(),1)
functiona() {
return "a"
}
functionb(Var1, Var2) {
return, Var1 Var2
}
amsgbox % functionb(% functiona(),1)
would be trying to force an expression, while already in expression syntax. So that's the wrong part there.
msgbox % functionb(functiona.call(),1)
would be trying to call a function object, but "functiona" is not a function object, it's just the name of a function.
msgbox % functionb(func("functiona"),1)
would be creating a function object, not right either.
Second problem is return a.
You're trying to return the value of a variable named a, as opposed to returning character "a".
The correct way would be:
MsgBox, % functionb(functiona, 1)
functiona()
{
return "a"
}
functionb(Var1, Var2)
{
output := Var1 Var2
return output
}

autohotkey use a return value imagesearch and click

I have a function:
NormalRand(x,y,int=1) {
Loop 12
{
Random, var,0.0,1
Num+=var
}
norm := (int) ? Round((y+x)/2+((Num-6)*(y-x))/6) : (y+x)/2+((Num-6)*(y-x))/6
Return norm < x ? x : norm > y ? y : norm
}
I have an imagesearch:
ImageSearch, FoundX, FoundY, 0, 0, A_ScreenWidth, A_ScreenWidth, *50 Okay.jpg
If ErrorLevel = 0
{
xCord = NormalRand(%FoundX%-10,%FoundX%+10)
yCord = NormalRand(%FoundY%-10,%FoundY%+10)
MsgBox, 4,, Found the image at %xCord% %yCord%
Click, %xCord%, %yCord% Left, 1
Sleep, 2000
}
I am trying to use the NormalRand function to distribute my clicks around the buttons so they are harder to detect within the program I will use this with. However, when i try to sent the cords to the click it doens't work. When i test it with msgbox i get this output Found the image at NormalRand(391-10,391+10) NormalRand(676-10,676+10)
I can't seem to figure out how to get it to send the numbers instead of the text.
What we have here, is misuse, and probably also unintentional use, of the legacy syntax.
Lets look at these two lines:
xCord = NormalRand(%FoundX%-10,%FoundX%+10)
yCord = NormalRand(%FoundY%-10,%FoundY%+10)
You're actually assigning text to those variables, not calling a function.
See this as an example:
xCord = NormalRand(%FoundX%-10,%FoundX%+10)
yCord = NormalRand(%FoundY%-10,%FoundY%+10)
MsgBox, % xCord "`n" yCord
For legacy syntax you're referencing the FoundX and FoundY variables correctly by wrapping them around %, but you're not doing that for the function name.
So in legacy syntax you'd do this:
xCord = %NormalRand%(%FoundX%-10,%FoundX%+10)
yCord = %NormalRand%(%FoundY%-10,%FoundY%+10)
However, please stop using legacy syntax. It's so ancient, bad and very different compared to other programming languages you maybe have experienced.
Expression syntax is what you want to use, so instead of legacy =, we're using := to assign an expression to our variables. (= is never ever used!)
In expression syntax your function calls look normal and nice:
xCord := NormalRand(FoundX-10, FoundX+10)
yCord := NormalRand(FoundY-10, FoundY+10)
And to preach even more about legacy syntax, you're also using it on the if-statement. To not use the legacy if-statement, use if ().

Repeatedly calling a hotkey

I've tried to implement a t flip flop(I think this is what it's called) into my program but am having some issues with it. The idea is to have the program start and stop while using the same hotkey. This is what I have so far.
looping := false
pass = 0
max = 2
^r::
pass++
looping := true
while(looping = true AND pass < max)
{
Send, stack overflow, save me!
}
looping := false
pass = 0
return
When I run the program and hit the hotkey the while loop starts. However, when I attempt to break the loop by pressing ^r I get no response and the program keeps looping.
I think you are referring to a "toggle" script. I am not what sure you are trying to achieve exactly, but the key is using a logical not: looping := !true. More about it here.
looping := false
pass = 0
max = 2
^r::
pass++
looping := !true
while (looping & pass < max)
{
Send, stack overflow, save me!
}
pass = 0
return
There's a lot of resources for this, here are a few:
https://autohotkey.com/boards/viewtopic.php?t=11952
http://maul-esel.github.io/ahkbook/en/toggle-autofire.html
https://www.reddit.com/r/AutoHotkey/comments/6wqgbu/how_do_i_toggle_hold_down_a_key/dmad0xx

Find the first vowel in a word

Please write a Matlab function to find the first vowel in a word, and test the program using your name as the input.
The function header is function v = findfirstvowel (word)
My work is :
function v = findfirstvowel (word)
vow = 'aeiouAEIOU';
for i=1:size(word)
for j=1:10
if word(i)==vow(j)
v=word(i);
break;
end
end
end
I don't know why but I didn't work
The break only breaks out of the innermost for loop.
From the documentation:
In nested loops, break exits only from the loop in which it occurs. Control passes to the statement that follows the end of that loop.
If you want to exit the function, you'd want to use return instead.
function v = findfirstvowel (word)
vow = 'aeiouAEIOU';
for i=1:size(word)
for j=1:10
if word(i)==vow(j)
v=word(i);
return;
end
end
end
Instead of the double for loop, you'd be much better off using something like ismember to check to find the vowels and use find to return the index of the first one. Also you can convert the word to lowercase and only compare to 'aeiou'.
function v = findfirstvowel (word)
isvowel = ismember(lower(word), 'aeiou');
v = word(find(isvowel, 1, 'first'));
end
If you wanted the other vowels using this approach you could do the following.
isvowel = ismember(lower(word), 'aeiou');
vowels = word(isvowel);
first_vowel = vowels(1);
second_vowel = vowels(2);

autohotkey how to cycle through array

I'm mainly a javascript developer and I'm starting to play with authotkey. I'm guessing if there is a better way to loop through an array than the way I'm using. Basically is like this:
cycle(value,maxValue){
value += 1
if value not between 1 and %maxValue%
value :=1
return value
}
Then I use it like this:
variable := cycle(variable,array.MaxIndex())
Seems a bit rudimentary. Is any other way?
EDIT:
I saw that my description was not clear. What I want is to get variables from the array in a circular way: when you ask for the next value and you are already at the last one, start again from the beginning.
Sounds like what you need is a for-loop
Example:
colors := Object("red", 0xFF0000, "blue", 0x0000FF, "green", 0x00FF00)
for key, value in colors
s .= key "=" value "`n"
MsgBox % s
Edit:
As per your comment, this may be more towards your need
index := 0
maxValue := 10
f3::
tooltip % index := cycle(index, maxValue)
return
cycle(index, maxValue)
{
return index := mod(index + 1, maxvalue)
}
Hope it helps
Since what blackholyman did is correct, it is not aimed on arrays.
Here is an approach that now I know it works:
i:=0,somearr:= ["bla","morebla","bla bla"]
;-- do whatever stuff here
somearr[i:=i>1?--i:somearr.MaxIndex()]