For...Next loop with Arrays

New to FreeBASIC? Post your questions here.
Kot
Posts: 336
Joined: Dec 28, 2006 10:34

For...Next loop with Arrays

Postby Kot » Jan 30, 2008 19:01

Why doesn't it work? Is it intentionally or is it a bug? What should I do if I want to nest some for...next loops? New variable for each loop doesn't sound good to me, besides in VB it works. And for...Next works good with UBound(Counter) for example, so what's wrong?

Code: Select all

Dim Counter(5) As Integer
For Counter(0)=1 To 22
   'some code
Next Counter(0)
anonymous1337
Posts: 5494
Joined: Sep 12, 2005 20:06
Location: California

Postby anonymous1337 » Jan 30, 2008 19:40

The code after next is ignored, so it doesn't really matter what next works with :-)

This might be a good feature request, however. It just seems to be a feature that isn't existent yet, or maybe something FBC intentionally won't allow, for whatever reason.
vdecampo
Posts: 2982
Joined: Aug 07, 2007 23:20
Location: Maryland, USA
Contact:

Postby vdecampo » Jan 30, 2008 19:47

This was discussed in a different thread. The iterator is not supposed to have scope outside of the for-next loop. This is "Best Practice" when coding because the value of the iterator after the loop is "undefined". So why would you want to store it?

-Vince
notthecheatr
Posts: 1759
Joined: May 23, 2007 21:52
Location: Cut Bank, MT
Contact:

Postby notthecheatr » Jan 30, 2008 20:25

That's correct, and in fact most of the time the iterator shouldn't be a regular variable at all. We usually do

Code: Select all

For i As Integer = 1 to 10
  '...
Next i


rather than

Code: Select all

Dim i As Integer

For i = 1 to 10
  '...
Next i


because with the first the scoping is more based on how the variable will actually be used (i.e., the variable does not exist outside of the loop itself) while in the second who knows what the value of i will be after the loop is over? This is why it's preferable not to use regular variables for looping.

Besides, as noted in the other thread (you may find it if you do a search for "iterator"), array index access or UDT member access will be slower than a regular variable because various numbers have to be added together to find the address where the iterator is. Much faster to use a regular variable (or better, a variable created by the For as in the first example above - this isn't going to be any faster, but it's better for the aforementioned scoping issues).
anonymous1337
Posts: 5494
Joined: Sep 12, 2005 20:06
Location: California

Postby anonymous1337 » Jan 30, 2008 22:29

Be careful when trying to make portable C++ code, however, based on your FB code. Mozilla Standards say not to depend on that scope of the iterator. /asifanyonecares...
cha0s
Site Admin
Posts: 5317
Joined: May 27, 2005 6:42
Location: Illinois
Contact:

Postby cha0s » Jan 31, 2008 6:21

It's good practice to confine your iterator to the for...next scope, but not obligatory.

The behavior of not allowing any but 'scalar' variables is more of a performance issue than anything. Either you'd have to store an address, and dereference every call, or think of if your array was indexed with a variable that could change during the loop itself. That would require a calculation into the index of the array every loop, a potential performance killer.
DrV
Site Admin
Posts: 2116
Joined: May 27, 2005 18:39
Location: Midwestern USA
Contact:

Postby DrV » Jan 31, 2008 7:48

In fact, the value of the iterator after a FOR loop is well defined: it is always the value that puts the iterator beyond the bounds given. For example, after 'for i = 0 to 3: next i', i will be 4.
notthecheatr
Posts: 1759
Joined: May 23, 2007 21:52
Location: Cut Bank, MT
Contact:

Postby notthecheatr » Jan 31, 2008 18:14

That may be what it's supposed to be, perhaps even what the variable is left at every time, but the point is that if a variable is being used specifically as an iterator in a loop it doesn't make much logical sense to use the variable for anything outside of the loop. That's why it's preferable (though not, as cha0s pointed out, obligatory) to confine it inside the scope of For.
Richard
Posts: 3029
Joined: Jan 15, 2007 20:44
Location: Australia

Postby Richard » Jan 31, 2008 20:06

Any of the three following examples may do the job you want. The For Next loop is designed for speed while the Do Loop is much more flexible.

Code: Select all

Dim Counter(5) As Integer

' method 1
Counter(0) = 1
Do While Counter(0) <= 22
    ' some code
    counter(0) += 1
Loop

' method 2
Counter(0) = 1
Do
    ' some code
    counter(0) += 1
Loop Until Counter(0) > 22

' method 3
For i As Integer = 1 to 22
    counter(0) = i
    ' some code
next i

notthecheatr
Posts: 1759
Joined: May 23, 2007 21:52
Location: Cut Bank, MT
Contact:

Postby notthecheatr » Jan 31, 2008 22:26

Yeah. Once again, it will be much less efficient, but you can do this if you need to.


If what DrV says is true though, technically method 3 should actually do this:

Code: Select all

' method 3
For i As Integer = 1 To 22
    counter(0) = i
    ' some code
Next i

counter(0) = 23


since the iterator will be one more than the upper limit of the For loop.

Once again though, all this is going to be less efficient than just using a regular scalar variable.
Kot
Posts: 336
Joined: Dec 28, 2006 10:34

Postby Kot » Feb 02, 2008 14:33

I just wanted to create a primitive dictionary file, like this:

Code: Select all

Dim Counter(5) As Integer, SomeWord As String
For Counter(0)=65 To 90
   For Counter(1)=65 To 90
      ...
      For Counter(5)=65 To 90
         SomeWord=Chr(Counter(0))+Chr(Counter(1))+...+Chr(Counter(5))
      Next Counter(5)
      ...
   Next Counter(1)
Next (Counter(0)

but I think using arrays as iterators can be useful in some other fields.
Lachie Dazdarian
Posts: 2338
Joined: May 31, 2005 9:59
Location: Croatia
Contact:

Postby Lachie Dazdarian » Feb 02, 2008 16:09

Maybe you are trying to do this. I don't know.

Code: Select all

DIM counter(30) AS INTEGER

' adds counter(1) to counter(30) to someword
For i AS INTEGER = 1 To 30
        someword = someword + Chr(counter(i))
Next i
counting_pine
Site Admin
Posts: 6221
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Postby counting_pine » Feb 02, 2008 16:52

Recursion is a useful solution in situations like this. It also helps keep repetition to a minimum - it's not much fun reading through arbitrarily nested blocks all containing basically the same thing.

The code below prints out all the four-letter words consisting of the characters A and B. The length of the word and variety of characters can easily be changed, but they are kept small so it all prints quickly and fits in one screen.

Code: Select all

declare sub recursesub( SomeWord as string, i as integer, n as integer )

const jmin = 65, jmax = 66
const numletters = 4

recursesub "", 1, numletters


sub recursesub( SomeWord as string, i as integer, n as integer )
   
    if i > n then
       
        print SomeWord
       
    else
       
        for j as integer = jmin to jmax
           
            recursesub( SomeWord + Chr(j), i + 1, n )
           
        next j
       
    end if
   
end sub
Kot
Posts: 336
Joined: Dec 28, 2006 10:34

Postby Kot » Feb 07, 2008 16:15

vdecampo wrote:The iterator is not supposed to have scope outside of the for-next loop. This is "Best Practice" when coding because the value of the iterator after the loop is "undefined". So why would you want to store it?

-Vince

For example:

Code: Select all

For Num=1 to Max
'search some database
   If Found then exit For
Next Num
if Num>Max then NotFound else Found
notthecheatr
Posts: 1759
Joined: May 23, 2007 21:52
Location: Cut Bank, MT
Contact:

Postby notthecheatr » Feb 07, 2008 16:21

That's easily emulated other ways. After all, For is just a special case of Do...Loop or While...Wend. For is used for specifically counting things, such as all the numbers from 1 to 100. But if you want to search through records in a database, you could use

Code: Select all

Dim As uInteger Num = 1

Do  While Num <= Max And Not Found
  'search some database
Loop


which achieves the same result and is cleaner code anyways since all the conditionals are part of the Do...Loop construct.



By the way...
anonymous1337 wrote:The code after next is ignored, so it doesn't really matter what next works with :-)

this is wrong. As of quite recently, the SVN builds (and therefore all future releases) check the iterator after Next and give an error if it's incorrect.

Return to “Beginners”

Who is online

Users browsing this forum: No registered users and 3 guests