Well, this has been quite an exercise, and for me as well. After looking at your snippets and some thought (some of which I did while I was trying to answer my Analysis test!) I came up with my own fixed snippet. It doesn't do away with the "accept" variable but it refrains from calling "Exit For" or "Exit" anything, for that matter:
Code: Select all
Declare Function GetInt(ByVal l As Integer, ByVal h As Integer) As Integer
Dim As Integer i, j, accept
Dim As Integer nums(1 To 8)
nums(1) = GetInt(1, 100)
For i = 2 To 4
Do
nums(i) = GetInt(1, 100)
j = i - 1
accept = 1
Do
If nums(i) = nums(j) Then accept = 0
j -= 1
Loop Until j = 0
If accept = 0 Then Print "You already picked that! Try again."
Loop While accept = 0
Next i
Print nums(1), nums(2), nums(3), nums(4)
End
Function GetInt(ByVal l As Integer, ByVal h As Integer) As Integer
Dim As Integer i, bounded
bounded = 0
Do
Input i
If (i < l) Or (i > h) Then
Print "Out of bounds; ";
Print "type a number between"; l; " and"; h; "."
Else
bounded = 1
End If
Loop While bounded = 0
GetInt = i
End Function
You can also see the GetInt function I wrote (whose absence in my original post caused a small controversy ^_^), which involves another flag "bounded". My code is full of flags like this; you use what you see, I guess, and I saw lots of flag variables.
Anyway, I now have a greater appreciation of the tradeoffs involved in writing code. The snippets so far seem to fall into two categories:
- using a flag variable (such as j_milton's "valid_count" and my "accept")
- using a flag array (such as adhay's "flag()", agamemnus' "picked()", and KristopherWindsor's "used()")
There are the mavericks, of course: KristopherWindsor's snippet manipulates the value of the counter variable (i) within the For loop, and HD_'s example does without For loops and uses only 2 variables (against my 3).
When I compare my "before" and "after" snippets, I realize that I got loop "closedness" while sacrificing time. In my new code, after the user enters the 4th number, the innermost Do loop will run 3 times, whereas if I had just done "Exit Do" as soon as I got a match, I would have saved a few instruction cycles. Granted, it is microscopic savings in terms of today's processors, but still a savings. (Apologies are in order as I am a mathematician by training, so a small number is still a number. ^_^)
Also, after looking at the examples, while having a flag array would become more economical if more numbers need to be entered, I decided that the flag variable is the way to go. The savings in this case are considerable: Why set aside space for 100 integers when you can enforce uniqueness on the inputs by using one integer? Again, I realize that it depends on the situation. With a flag array, the uniqueness check only runs once no matter how many numbers are needed. Under the flag variable situation, if I instead asked for 50 numbers, when the user enters the 50th number, the program will have to check the nums array 49 times!
Thanks again for all the inputs. I feel I've learned a great deal in this thread.
P.S. Not the least of which is the interesting idea from KristopherWindsor's snippet for GetInt. ^_^ I never would have thought of using recursion in this manner, yet it is intriguing! My only worry would be running out of stack space if the user couldn't get his or her act together and come up with a bounded integer after umpteen tries. ^_^ There needs to be another use for this; I will keep this in mind for later.