SB BBC @ GBR Oldie hints/tips #125-129 Hints and tips from the archives of Wakefield BBC Micro User Group... 125. DIM oddity ~~~~~~~~~~ If you have already dimensioned a numeric or string array in a program, such as A$(100), FRED(55) or mem%(300), then any attempt to redimension it will result in the error message "Bad DIM". In some versions of BASIC, though sadly not BBC BASIC, you can legally redimension an array, or reclaim the memory it occupies, provided you 'kill' it first, eg KILL A$ , ERASE A$ etc, (the syntax varies). However, if you dimension an area of memory with the syntax DIM mem% 100 , as one might do if reserving memory for some data or machine code, then it can be redimensioned without killing it first, and without generating any error message. If this sounds too good to be true, then you're dead right! Every time you redimension the area, even if you are reserving the same or less space than before, the old area is 'thrown away', and new space reserved. If you don't do this too often, then it may be useful to you, but try the short program below and see how it rapidly gobbles up all the memory. This applies equally to all versions of BBC BASIC that I have come across. 10 REPEAT:DIM A% 50:UNTIL FALSE 20 END 126. Alphabetic comparison ~~~~~~~~~~~~~~~~~~~~~ ALPHABETIC COMPARISON. Most of you will be familiar with the use of the "<" and ">" operators to compare numbers, but not everyone may be aware that it can be used on strings, thus forming the basis of an alphabetic sort. It is quite legitimate to use an expression like IF A$>B$ THEN GOTO 240 This can be used to compare "SMITH" with "BROWN", and it will decide that "BROWN" is less than "SMITH", because it comes sooner in alphabetical order. Lower case comes after upper, so "SMITH" is less than "Smith" for example. In other words, the comparison is made in ASCII code order. This does mean that when you compare numbers in the form of strings, you get odd results if they do not both contain the same number of digits in front of the decimal point. For example "12" is less than "3" because it starts with a "1" rather than a "3", but "03" will correctly be found to be less than "12". Similarly, ".2" will be less than "0.1", because a fullstop comes before "0" in ASCII code order, but "0.2" rather than ".2" will be compared correctly. 127. ON-ERROR tip ~~~~~~~~~~~~ An ON-ERROR statement can take several forms other than just simply ON ERROR GOTO . Here are a few ideas: 10 ON ERROR GOTO 140 10 ON ERROR RUN (or END or STOP) 10 ON ERROR PROCboob:GOTO 550 10 ON ERROR IF ERR=17 THEN 140 ELSE REPORT:PRINT" at line ";ERL:END 128. Date compression ~~~~~~~~~~~~~~~~ When large numbers of dates need to be stored in a database, file space can very quickly be used up unless some economies are made. The first Function below accepts a date as its input, in the form of a six-character string, (eg 230286 for 23rd Feb 1986), checks that the date is valid, and compresses it to an integer. The Function returns the value zero (or FALSE) if an impossible date is entered, (eg 310985 or 290286), and this should be tested by the program. If the date is OK the resulting integer can be stored in just two bytes, (it ranges from 33 to 51103), and can easily be sorted chronologically. (NB This routine does not do this conversion for you.) The date as a string needs six bytes, and would not sort properly unless it had been entered backwards! (eg 860225.) The second Function converts the stored integer back to a six-character string. 1000 DEFFNdate_to_number(Z$):LOCAL D%,M%,Y%,N% 1010 IF LEN(Z$)<>6 THEN=FALSE 1020 D%=VAL(LEFT$(Z$,2)):M%=VAL(MID$(Z$,3,2)):Y%=VAL(RIGHT$(Z$,2)) 1030 IF M%>12 OR M%<1 THEN=FALSE 1040 N%=30-(M%<8)*(M%MOD2)-(M%>7)*((M%+1)MOD2) 1050 IF M%=2 THEN N%=28-(Y%MOD4=0) 1060 IF D%<1 OR D%>N% THEN=FALSE ELSE=D%+32*M%+512*Y% 1070 : 2000 DEF FNnumber_to_date(Z%):LOCAL D%,M%,Y% 2010 D%=Z%MOD32:Z%=Z%DIV32:M%=Z%MOD16:Y%=Z%DIV16:Z%=D%*10000+M%*100+Y% 2020 =RIGHT$("0"+STR$(Z%),6) 129. Number compression ~~~~~~~~~~~~~~~~~~ Further to tip 128, here is a way of storing that compressed date as a 2-byte integer. You must dimension some memory space twice the size of the number of dates to be stored. In the example below, I have assumed that 1000 dates are to be stored. The first Procedure places the already compressed date Z% in position N% out of the list of 1000. Eg PROCstore(44119,500) actually places 23rd Feb 1986 in position 500 out of 1000. To read a stored date, the Function will return the compressed date stored at position N%. Eg PRINT FNfind(450) will print the compressed date stored in position 450 out of 1000. You can then use the second Function to turn it into a sensible date string. Using these Functions and Procedures as building blocks, you can incorporate them into your own programs. 100 DIM array% 2000 200 REM Program somewhere here. 3000 DEFPROCstore(Z%,N%) 3010 array%?(N%*2-1)=Z%:array%?(N%*2)=Z%DIV256:ENDPROC 3020 : 4000 DEFFNfind(N%):=array%?(N%*2-1)+(array%?(N%*2))*256 73 Rick G4BLT @ GB7WRG