Author Topic: Subscript Out of Range Error  (Read 4722 times)

0 Members and 1 Guest are viewing this topic.

Offline davidshq

  • Newbie
  • Posts: 55
    • View Profile
Subscript Out of Range Error
« on: November 03, 2018, 10:12:48 pm »
Hi All,

So I'm running into a strange problem...I've got the following very simple code:

Code: QB64: [Select]
  1. OPEN "I", 1, "cwslead.dat"
  2. FOR i = 1 TO 40
  3.     INPUT #1, lname$(i), rating(i)
  4.     PRINT lname$(i), rating(i)

The contents of cwslead.dat are as follows:
Quote
McDowell,4
McClellan,5
Fremont,5
Buell,7
Pope,3
Grant,8
Banks,4
Burnside,1
Sherman,8
Rosecrans,7
Hooker,6
Meade,5
Thomas,7
Grierson,7
Custer,5
Sheridan,9
Halleck,5
Banks,1
Butler,3
McPherson,7
J.E. Johnston,8
Jackson,10
A.S. Johnston,10
Pemberton,2
Beauregard,7
R.E. Lee,10
J.E.B. Stuart,9
Ashby,8
Bragg,4
Longstreet,8
Early,6
Van Dorn,8
Hardee,7
Pickett,8
Forrest,10
Hood,8
Polk,7
Breckenridge,8
Zollicoffer,7
McCulloch,6

The above code succesfully reads out the first several:

Quote
McDowell,4
McClellan,5
Fremont,5
Buell,7
Pope,3
Grant,8
Banks,4
Burnside,1
Sherman,8
Rosecrans,7

But then errors out with, "Subscript out of range"...and continues to do so.

Any thoughts? I'm sure this is stupidly simple...but I'm not seeing it!

FellippeHeitor

  • Guest
Re: Subscript Out of Range Error
« Reply #1 on: November 03, 2018, 10:14:20 pm »
Non-defined arrays can hold up to 10 items (eleven actually, 0-10).

DIM lname$(1 TO 40), rating(1 TO 40)

Add OPTION _EXPLICIT to the top of your program and this type of error will become less often (if you're willing to declare all variables - far from mandatory, but highly efficient).
« Last Edit: November 03, 2018, 10:18:59 pm by FellippeHeitor »

Offline TerryRitchie

  • Seasoned Forum Regular
  • Posts: 495
  • Semper Fidelis
    • View Profile
Re: Subscript Out of Range Error
« Reply #2 on: November 04, 2018, 02:05:00 pm »
If you REDIM an array you can change its size "on the fly" to meet your needs.

You can increase the array size by using the current size (UBOUND) and adding 1:

Code: QB64: [Select]
  1. OPTION _EXPLICIT '              must declare variables
  2.  
  3. REDIM Lname(0) AS STRING '      last name
  4. REDIM Rating(0) AS INTEGER '    rating system
  5. DIM Count AS INTEGER '          generic counter
  6.  
  7. OPEN "I", #1, "cwslead.dat" '                       open file for input
  8. FOR Count = 1 TO 40 '                               cycle 40 times
  9.     REDIM _PRESERVE Lname(UBOUND(Lname) + 1) '      increase array index by 1
  10.     REDIM _PRESERVE Rating(UBOUND(Rating) + 1) '    increase array index by 1
  11.     INPUT #1, Lname(Count), Rating(Count) '         get the data
  12.     PRINT Lname(Count), Rating(Count) '             verify the data
  13. NEXT Count '                                        leave after 40 cycles
  14. CLOSE #1 '                                          close the file
  15.  

Or you can increase the array size by using a counter (Count) if you wish:

Code: QB64: [Select]
  1. OPTION _EXPLICIT '              must declare variables
  2.  
  3. REDIM Lname(0) AS STRING '      last name
  4. REDIM Rating(0) AS INTEGER '    rating system
  5. DIM Count AS INTEGER '          generic counter
  6.  
  7. OPEN "I", #1, "cwslead.dat" '               open file for input
  8. FOR Count = 1 TO 40 '                       cycle 40 times
  9.     REDIM _PRESERVE Lname(Count) '          increase array index to match Count
  10.     REDIM _PRESERVE Rating(Count) '         increase array index to match Count
  11.     INPUT #1, Lname(Count), Rating(Count) ' get the data
  12.     PRINT Lname(Count), Rating(Count) '     verify the data
  13. NEXT Count '                                leave after 40 cycles
  14. CLOSE #1 '                                  close the file
  15.  

REDIM allows you to vary the index size of an array while _PRESERVE preserves the data contained in the indexes that already exist.

Note: One other thing worth mentioning is to try not to use FOR-NEXT loops as much as possible because they are very slow. You can easily replace FOR-NEXT with DO-LOOP structures.

Code: QB64: [Select]
  1. OPTION _EXPLICIT '              must declare variables
  2.  
  3. REDIM Lname(0) AS STRING '      last name
  4. REDIM Rating(0) AS INTEGER '    rating system
  5. DIM Count AS INTEGER '          generic counter
  6.  
  7. OPEN "I", #1, "cwslead.dat" '               open file for input
  8. DO '                                        cycle 40 times
  9.     Count = Count + 1 '                     increment count
  10.     REDIM _PRESERVE Lname(Count) '          increase array index to match Count
  11.     REDIM _PRESERVE Rating(Count) '         increase array index to match Count
  12.     INPUT #1, Lname(Count), Rating(Count) ' get the data
  13.     PRINT Lname(Count), Rating(Count) '     verify the data
  14. LOOP UNTIL Count = 40 '                     leave after 40 cycles
  15. CLOSE #1 '                                  close the file
  16.  
« Last Edit: November 04, 2018, 02:21:10 pm by TerryRitchie »
In order to understand recursion, one must first understand recursion.

Offline Pete

  • Forum Resident
  • Posts: 2361
  • Cuz I sez so, varmint!
    • View Profile
Re: Subscript Out of Range Error
« Reply #3 on: November 04, 2018, 03:03:07 pm »
I've always used REDIM, exclusively. I don't think I can come up with a reason to use DIM in its place, at least not for anything I program.

REDIM lname$(40), rating(40)

Pete
Want to learn how to write code on cave walls? https://www.tapatalk.com/groups/qbasic/qbasic-f1/

Offline davidshq

  • Newbie
  • Posts: 55
    • View Profile
Re: Subscript Out of Range Error
« Reply #4 on: November 04, 2018, 03:08:00 pm »
Thanks all! Just what I needed!

Offline TerryRitchie

  • Seasoned Forum Regular
  • Posts: 495
  • Semper Fidelis
    • View Profile
Re: Subscript Out of Range Error
« Reply #5 on: November 04, 2018, 03:11:35 pm »
I still find DIM handy for fixed tables of data, perhaps something like a SIN/COS table with 360 degrees of accuracy:

DIM SinCosTable(359)

I read somewhere (I think it was on [abandoned, outdated and now likely malicious qb64 dot net website - don’t go there]) that using DIM to make static sized arrays is faster than REDIM's dynamic structure. I've never tested this using code so I can't attest to its accuracy, but in some cases I think DIM still has its uses. But as you said Pete, a vast majority of my coding uses REDIM exclusively as well.
In order to understand recursion, one must first understand recursion.

Offline SMcNeill

  • QB64 Developer
  • Forum Resident
  • Posts: 3972
    • View Profile
    • Steve’s QB64 Archive Forum
Re: Subscript Out of Range Error
« Reply #6 on: November 04, 2018, 03:36:57 pm »
The only thing about REDIM is you really shouldn't make it incremental inside a loop -- it slows execution too much.

FOR I = 1 TO 100000
   REDIM x(I) AS LONG
NEXT

The above is a bad practice and will lag your code considerably as it builds a new block of memory and frees the old one, over and over and over.  Add _PRESERVE to the mix and it gets even worse as it moves data from one block to the other, over and over...

A much better process is:

FOR I = 1 TO 100000
  IF I > UBOUND(X) THEN REDIM X(I + 1000) AS LONG
NEXT

With the above, you'll move and free memory 1/1000th as many times as before -- which will save you a ton of lag/slowdown in your programs.

(And, if total memory is an issue, resize the array down to the size you need once you exit the loop.)

Resizing inside loops work for small loops, but it's a bad habit to get into.  It's better to raise your bounds a lot once, and then resize down, than it is to resize them over and over and over and over again...
https://github.com/SteveMcNeill/Steve64 — A github collection of all things Steve!