Way to Jump to Next i in For..Next Loop? - vb.net

I'm reverse engineering in QuickBasic and I have code like this:
FOR i = star TO fin
IF a < 1 THEN
CALL clrbot
COLOR 15
PRINT force$(side); " army in "; city$(armyloc(i)); " is CUT OFF !";
TICK turbo!
GOTO alone
END IF
size = size + 1
max = 11: IF LEN(armyname$(i)) < 11 THEN max = LEN(armyname$(i))
mtx$(size) = LEFT$(armyname$(i), max)
array(size) = i
alone:
NEXT i
I'd like to get rid of the line label (alone) and instead do something like:
IF a < 1 THEN
CALL clrbot
COLOR 15
PRINT force$(side); " army in "; city$(armyloc(i)); " is CUT OFF !";
TICK turbo!
NEXT i
END IF

You could replace the GOTO with an Else:
For i = star To Fin
If a < 1 Then
' Do something
Else
' Do Something else
End If
Next
This would follow the same logic - the Else takes the place of the GOTO alone statement.
In the original code (QuickBASIC) if the If block is entered, everything after then GOTO alone statement is ignored.
If the If block is not entered (i.e., a >= 1) then everything after the If block is executed.
The Else statement in the VB.NET code will produce the same behavior. If a < 1, the first block will be executed and the Else block will be ignored, and the loop will advance to the next increment of i.
If a >= 1, then the Else block will be executed and the loop will then advance to the next increment of i.
The above assumes labels in QuickBASIC are like labels in DOS batch files.

Related

Excel VBA: Jump inside a for loop: "Next without For" – What am I doing wrong?

I honestly do not know why the VBA compiler is nagging me because of that GoTo Jump, respectively Jump:.
counter2 = 0
If (counter1 > 1) Then
For i = 0 To (MaxLastCell - 4)
If (IncompleteRows(i) = 1) Then
If ((counter2 > 1) And (counter2 < counter1)) Then
x = x + ", " + CLng(i)
counter2 = counter2 + 1
GoTo Jump
End If
If ((counter2 > 1) And (counter2 = counter1)) Then
x = x + " and " + CLng(i)
GoTo Outside
If (counter2 = 0) Then
x = CLng(i)
counter2 = 1
End If
End If
Jump:
Next i
Every time I am trying to run my code, this code snippet appears to be a problem. The compiler marks Next at the very bottom and tells me that there is a "Next without For".
But shouldn’t this kind of coding work? I just saw it here. A strange thing, however, is that the compiler there did not seem to coerce B H to move his jumping point NextIteration: to the very left but allowed it to stay at the second indent level and, thus, within the for-loop, as it seems. (Does that even matter?)
try this (revision marked in comments):
counter2 = 0
If (counter1 > 1) Then
For i = 0 To (MaxLastCell - 4)
If (IncompleteRows(i) = 1) Then
If ((counter2 > 1) And (counter2 < counter1)) Then
x = x + ", " + CLng(i)
counter2 = counter2 + 1
GoTo Jump
End If
If ((counter2 > 1) And (counter2 = counter1)) Then
x = x + " and " + CLng(i)
GoTo Outside
ElseIf (counter2 = 0) Then '<--*** changed from simple 'If'
x = CLng(i)
counter2 = 1
End If
End If
Jump:
Next i
End If '<--*** added
but you should avoid GoTos
You've got some nice spaghetti code there. GoTo is but a poor alternative to proper control flow.
One GoTo to "skip to next iteration" is one thing. Another to GoTo Outside (wherever that is) is something else.
VBA (the language spec) doesn't care on which column a line label starts; for all we know the answer you linked to was typed in the answer box, not in the VBE. When the VBE (the IDE/editor) sees a line label, it moves it to column 1 automatically, just like it automatically inserts spaces between operators and operands, and just like it automatically adjusts the casing of keywords and identifiers as you type them. So no, it doesn't matter at all.
VBA syntax requires blocks to be closed: just like a Sub DoSomething() procedure must end with End Sub and a With block must end with End With, a For block must end with Next. Proper indentation and small procedure bodies usually help getting this right.
A lot of other languages (C#, Java, C++, etc.) have similar constraints about what makes a valid code block (mismatched { and } braces are a compiler error in every language that uses them AFAIK), so this isn't VBA being picky or complaining for no reason.
That said it's hard to tell whether and where your code is malformed, because you're not including the entire procedure scope so we have to assume there's nothing else that follows your snippet - and the snippet you've posted is missing an End If as user3598756 has noted:
If (counter1 > 1) Then
'...code...
End If
So, how to go about restructuring this?
Assuming the Outside line label is located just before End Sub (or is it End Function?), then you can replace it with Exit Sub (or Exit Function) and call it a day.
If there's more code that needs to run after the loop but before the end of the procedure scope, Exit For will get you out of the loop while keeping you inside the procedure - next line to run will be the first executable statement that follows the Next token.
Now take the condition that makes the loop skip an iteration, and rephrase the loop body accordingly; use ElseIf to avoid evaluating conditions you don't need to, and remove all these extraneous and confusing parentheses:
If IncompleteRows(i) = 1 And counter2 > 1 And counter2 < counter1 Then
x = x + ", " + CLng(i)
counter2 = counter2 + 1
ElseIf counter2 > 1 And counter2 = counter1 Then
x = x + " and " + CLng(i)
Exit For ' assuming...
ElseIf counter2 = 0 Then
x = CLng(i)
counter2 = 1
End If
And that would be the entire body of the loop. Of course it could still be improved; counter2 > 1 is repeated twice, so there's room for some further restructuring. But already, all GoTo's are gone.

For Loop Step -1

I want to know why this loop doesn't show anything in VB.NET.
I think this code will create an infinite loop. But it doesn't show anything.
Dim i as Integer
For i = 1 to 3 Step - 1
MessageBox.Show(i)
Next
Is that loop different with this code (in java/c#) ?
for(int i = 1;i <= 3;i--)
{
// print i
}
http://msdn.microsoft.com/en-us/library/5z06z1kb.aspx
With a negative step size the loop only executes if counter >= end. So in this case with i = 1, that is less than the ending value so the loop doesn't execute at all.
It doesn't show anything because you are running the counter backwards without reversing the start and end conditions.
Think of the loop like this:
Dim counter As Int32 = 1
Do
If counter <= 1 Then
Exit Do
End If
Console.WriteLine("The counter is at " & counter)
counter +=1
Loop
Obviously this won't work properly.
You need to reverse the start and end conditions:
For counter = 3 To 1 Step -1
Console.WriteLine("counter: " & counter)
Next
For i = 1 to 3 Step - 1
It won't create an infinite loop. The loop will simply be skipped, because you can't get from 1 to 3 with a step value of -1.
Is that loop different with this code (in java/c#) ?
This loop will also end immediately, because the initial value (i = 1) meets the exit condition (i <= 3).

Not completed file read

I'm trying to debug what went wrong in my code. My file.txt contains 1763 lines but when I run it, it always ends up not completed. Always stops somewhere at 1680 and up (printed by the row in my code); the thing is it stops at different line every time I run it, so I don't think the problem's with my text file.
row = 0
for line in io.lines("file.txt") do
row = row+1
local new_row1 = {}
for n in line:gmatch'%S+' do
table.insert(new_row1, tonumber(n))
end
if #new_row1 > 0 then
table.insert(input, new_row1)
end
print(row)
end
Is there something wrong in my code?
It looks like in your code, you opened a file handle to "file.txt" at the beginning of your script and it remains open till the end where you close the file. During that time, you attempt to reopen "file.txt" again in your loop which is causing the strange behavior you're seeing.
When I moved your file open and close scopes to the middle section after first loop but before the last outer loop, that fixes the issue:
file = assert(io.open("file.txt", "w"))
for i = 1, 1000 do
j = math.random(i, row-one)
u[i], u[j] = u[j], u[i]
for k = 1, 11 do
file:write(input2[u[i]][k], " ")
end
file:write"\n"
end
num = (row-one)+1
for i = 1, one do
for k=1, 11 do
file:write(input2[num][k], " ") --writes to the file all the rows starting from where '1' in column11 was seen
end
file:write("\n")
num = num + 1
end
file:close()
-----------------------------------Access file.txt.--------------------------
-- ...
This gives the expected output:
Done 1762 1762
--------------------------

Making text go to a new line when in a while loop

I have a richTextbox, and a while loop, x = 0, and every time this loop runs, x += 1 till it reaches a certain value.
Heres what I want to happen:
while x <> 10 then
it will say item 0 +1 on a new line, and then item 1 + 1 on the line under it, etc, so you will see all 10 values after.
What happens is, it will change that line into the new value.
My question is: How do I make it put the words on a new line instead?
Here is my code:
While readListItem <> PaymentList.Items.Count
If readListItem > PaymentList.Items.Count Then
readListItem = 0
Exit While
End If
readListItem += 1
MessageBox.Show(readListItem)
resultBox.Text = vbNewLine + PaymentList.Items.Item(readListItem) + " costs " + enteredCost + "." + vbNewLine
End While
readListItem is "x", and that is being iterated by 1 every time the loop runs
PaymentList is my listbox containing an unknown value (the user sets the number of items in this list)
The If if there because, after x = lets say 10, it would add another to x (so now it = 11) and try to print out the 11th item, as it doesnt exist, it crashes. This is to attempt to prevent that. I didnt want to go with a try catch
Try adding the new value instead of replacing the entire value:
resultBox.Text &= Environment.NewLine() & PaymentList.Items.Item(readListItem) + " costs " + enteredCost + "."
The expression &= is equivalent, in this case, to resultBox.Text = resultBox.Text & "...".
And once advice, you can simplify your loop by using this condition:
While readListItem < PaymentList.Items.Count
'...
End While

Exit a while loop in VBS/VBA

Is there a method of exiting/breaking a while in VBS/VBA?
Following code won't work as intended:
num = 0
while (num < 10)
if (status = "Fail") then
exit while
end if
num = num+1
wend
VBScript's While loops don't support early exit. Use the Do loop for that:
num = 0
do while (num < 10)
if (status = "Fail") then exit do
num = num + 1
loop
what about changing the while loop to a do while loop
and exit using
Exit Do
While Loop is an obsolete structure, I would recommend you to replace "While loop" to "Do While..loop", and you will able to use Exit clause.
check = 0
Do while not rs.EOF
if rs("reg_code") = rcode then
check = 1
Response.Write ("Found")
Exit do
else
rs.MoveNext
end if
Loop
if check = 0 then
Response.Write "Not Found"
end if}
Incredibly old question, but bearing in mind that the OP said he does not want to use Do While and that none of the other solutions really work... Here's something that does exactly the same as a Exit Loop:
This never runs anything if the status is already at "Fail"...
While (i < 20 And Not bShouldStop)
If (Status = "Fail") Then
bShouldStop = True
Else
i = i + 1
'
' Do Something
'
End If
Wend
Whereas this one always processes something first (and increment the loop variable) before deciding whether it should loop once more or not.
While (i < 20 And Not bShouldStop)
i = i + 1
'
' Do Something
'
If (Status = "Fail") Then
bShouldStop = True
End If
Wend
Ultimately, if the variable Status is being modified inside the While (and assuming you don't need i outside the while, it makes no difference really, but just wanted to present multiple options...
I know this is old as dirt but it ranked pretty high in google.
The problem with the solution maddy implemented (in response to rahul) to maintain the use of a While...Wend loop has some drawbacks
In the example given
num = 0
While num < 10
If status = "Fail" Then
num = 10
End If
num = num + 1
Wend
After status = "Fail" num will actually equal 11. The loop didn't end on the fail condition, it ends on the next test. All of the code after the check still processed and your counter is not what you might have expected it to be.
Now depending on what you are all doing in your loop it may not matter, but then again if your code looked something more like:
num = 0
While num < 10
If folder = "System32" Then
num = 10
End If
RecursiveDeleteFunction folder
num = num + 1
Wend
Using Do While or Do Until allows you to stop execution of the loop using Exit Do instead of using trickery with your loop condition to maintain the While ... Wend syntax. I would recommend using that instead.
While many have mentioned Do While...Loop, there are no examples showing the While is not necessary:
count = 0
Do
count = count + 1
wscript.echo count
If (count > 9) Then
Exit Do
End If
'...Some other logic that can be ended early...
wscript.sleep(1000)
Loop
If you already have the variable to compare against and it makes sense to complete the loop, Do While... is great. However, if you're doing something a little more granular, like the WScript.Sleep above that delays the script can be avoided.
Use Do...Loop with Until keyword
num=0
Do Until //certain_condition_to_break_loop
num=num+1
Loop
This loop will continue to execute, Until the condition becomes true
While...Wend is the old syntax and does not provide feature to break loop! Prefer do while loops