Random Access Procedures
Post by joker on Oct 20th, 2015, 8:08pm
Relating to my effort at creating my library of procedures relative to random access files, this question comes to mind.
Does one procedure (SUB, GOSUB, or FUNCTION) have precedence over another?
I tend to lean towards a procedure that doesn't surrender control until it is finished for file operations, but I don't know much about how Windows handles those processes.
Re: Random Access Procedures
Post by Richard Russell on Oct 20th, 2015, 8:48pm
on Oct 20th, 2015, 8:08pm, pnlawrence wrote:Does one procedure (SUB, GOSUB, or FUNCTION) have precedence over another? |
|
I'm not sure what you mean by 'precedence' in this context, can you give an example? GOSUBs should probably be avoided in a 'modern' program.
Richard.
Re: Random Access Procedures
Post by joker on Oct 20th, 2015, 9:08pm
Sorry, I'm thinking "preference" and write "precedence."
I'm thinking something like FileExists is a function where as OpenFile is a sub.
Re: Random Access Procedures
Post by Richard Russell on Oct 20th, 2015, 9:31pm
on Oct 20th, 2015, 9:08pm, pnlawrence wrote:I'm thinking something like FileExists is a function where as OpenFile is a sub. |
|
Because LB/LBB supports byref parameters, that is to say that both SUBs and FUNCTIONs can return values to the calling code, the choice of which to use is not always clear cut. A common recommendation is that if a single value (numeric or string) is returned then a FUNCTION is the best choice, but when zero or two or more values are returned then use a SUB.
But there can be circumstances when it makes sense to ignore that recommendation. SUBs and FUNCTIONs are substantially identical 'under the hood'; use whichever makes the program easier to write and easier to understand.
Richard.
Re: Random Access Procedures
Post by joker on Oct 20th, 2015, 9:59pm
I always liked the form ... n = function(a,b) .
I'm going to keep busy with this list:
Code:' Random Access File Library Procedures
'From "somewhere"
'Verify ODBC Version
'Create DB
'Create Table
'Delete Table
'Verify DB / Table Existance (and count number / verify name so that they can be re-created if missing)
'Add record
'Delete Record
'Previous Record
'Next Record
'Compact Records (DB)
'Insert Field
'Delete Field
'Cross Reference Records Between Tables
'Query (and or Search) Tables
'Back Up DB
'Restore DB (from back up)
'Then there are activities such as:
'Read data from table
'Save data to table
'Edit data in field
'Save edited field
'Delete data from field
'From justbasic.wikispaces.com "UncleBen" Random access files with arrays
'OpenRAF sub
'CloseRAF sub
'PutRAFrecord function
'GetRAFrecord function
'FindRAFrecord function
'GetRAFfield function
'PutRAFfield function
'EraseRAFrecord function
'FindEmptyRAFrecord function
'FitFieldRAFrecord function
Re: Random Access Procedures
Post by joker on Oct 21st, 2015, 02:34am
Now I know why no one has built a "standard" library for RAF.
Code:OPEN "HeadsOfState.dat" for RANDOM as #1 LEN = 70
"LEN" has to be fed a literal value. :-/
Stymied before starting.
Not completely, but on with the next one.
Re: Random Access Procedures
Post by Richard Russell on Oct 21st, 2015, 08:32am
on Oct 21st, 2015, 02:34am, pnlawrence wrote:"LEN" has to be fed a literal value. :-/ |
|
I don't believe that's true (in LBB). I tried this code in LBB v3.03 and it appears to work correctly as far as I can tell:
Code: reclen = 70
OPEN "HeadsOfState.dat" for RANDOM as #1 LEN = reclen
I entirely agree that accepting only a literal value as the length (LB 4.04 and LB 4.5.0: I'm looking at you!) would make it very difficult to write a library routine for opening a RAF database. Another LB shortcoming fixed in LBB!
Richard.
Re: Random Access Procedures
Post by joker on Oct 21st, 2015, 09:22am
As the cartoon guy says, "WooHoo!"
I learned a valuable lesson. Test with the whole package. Never forget to test with LBB!
Re: Random Access Procedures
Post by Richard Russell on Oct 21st, 2015, 1:25pm
on Oct 21st, 2015, 08:32am, Richard Russell wrote:Another LB shortcoming fixed in LBB! |
|
A quick test indicates that not only does LB require a literal value for the record length in the OPEN statement, but has the same restriction for the individual field lengths in the FIELD statement. Again, LBB has no such limitation:
Code: reclen = 70
OPEN "HeadsOfState.dat" for RANDOM as #1 LEN = reclen
FIELD #1, reclen/2 AS Field1$, reclen/2 AS Field2$
(In all fairness it has to be admitted that LBB imposes a limit of 8 concurrently open random files, whereas LB has no such restriction, so it's not entirely one-sided).
Richard.
Re: Random Access Procedures
Post by joker on Oct 22nd, 2015, 2:40pm
So, am I barking up the wrong tree and going to find out after I build a lot of stuff? I'd like to know the chances of success now! ;D
Code:
function(OpenRAF path$, filename$, fileHandle$, recordLen)
' file must exist?
open filename$ for random as #fileHandle$ len = recordLen ' open and define record
end function
sub CloseRAF fileHandle$
close #fileHandle$
end sub
function fileExists(path$, filename$)
'dimension the array info$( at the beginning of your program
'dim info$(10, 10)
'if fileExists(DefaultDir$, "users.dat") then
files path$, filename$, info$()
fileExists = val(info$(0, 0)) 'non zero is true
end function
function SetRAFfields(fileHandle$, recordLen)
'field lengths and field names have to be modified per program
'call after OpenRAF
'set the fields in RAF
if (1+2+3+4) = recordLen then ' something to make one think about field lengths
field #fileHandle$,_
1 as field1$,_
2 as field2$,_
3 as field3$,_
4 as field4$
SetRAFfields = 0
else
SetRAFfields = 1 ' error condition
endif
end function
Re: Random Access Procedures
Post by Richard Russell on Oct 22nd, 2015, 10:10pm
on Oct 22nd, 2015, 2:40pm, pnlawrence wrote: Code:
open filename$ for random as #fileHandle$ len = recordLen |
|
That doesn't work (even in LBB!), you must use MAPHANDLE:
Code: open filename$ for random as #1 len = recordLen
maphandle #1, fileHandle$
Richard.
Re: Random Access Procedures
Post by joker on Oct 23rd, 2015, 10:45am
Funny how the brain works! "#fileHandle$" has shown up in some of my searches, but not in that form.
I should have used/assumed the form fileHandle$ = "#" + {path} + fileName$.
Being generic is getting more difficult. I'm starting to wonder if its worth the time for my project.
Re: Random Access Procedures
Post by joker on Oct 23rd, 2015, 11:04am
Curses! That won't work either. Missing "#" in OPEN.
Re: Random Access Procedures
Post by Richard Russell on Oct 23rd, 2015, 11:21am
on Oct 23rd, 2015, 11:04am, pnlawrence wrote:Curses! That won't work either. Missing "#" in OPEN. |
|
The code I listed does work - I tested it before posting as I always try to do. Here's the entire earlier demo from the 'Numeric field length RAF' thread modified to use a handle variable to prove that it can be done (in LBB):
Code: handle$ = "#MyFileHandle" ' the handle variable
field1 = 1/3
field2 = 1/3
open "test.raf" for random as #1 len = 20
maphandle #1, handle$
field #handle$, 6 as field1, 14 as field2
put #handle$, 1
close #handle$
open "test.raf" for random as #2 len = 20
maphandle #2, handle$
field #handle$, 6 as field1$, 14 as field2$
get #handle$, 1
close #handle$
print chr$(34);field1$;chr$(34)
print chr$(34);field2$;chr$(34)
This doesn't work in LB 4.04 or 4.5.0 so without LBB you really would be screwed.
Richard.
Re: Random Access Procedures
Post by joker on Oct 23rd, 2015, 11:29am
Thanks, Richard. I am studying every word you write.
This "library" seems to pass the RUN test (no program), but with an "incompatibility" error message.
EDIT: Well, of course it doesn't "RUN", because it has an "ERROR". The error message implies that it was somehow corrected, but there's no output.
Code:
function OpenRAF(path$, filename$, fileHandle$, recordLen)
' file must exist?
open filename$ for random as #fileHandle$ len = recordLen ' open and define record
end function
sub CloseRAF fileHandle$
close #fileHandle$
end sub
function fileExists(path$, filename$)
'dimension the array info$( at the beginning of your program
'dim info$(10, 10)
'if fileExists(DefaultDir$, "users.dat") then
files path$, filename$, info$()
fileExists = val(info$(0, 0)) 'non zero is true
end function
function setRAFfields(fileHandle$, recordLen)
'field lengths and field names have to be modified per program
'call after OpenRAF
'set the fields in RAF
if (1+2+3+4) = recordLen then ' something to make one think about field lengths
field #fileHandle$,_
1 as field1$,_
2 as field2$,_
3 as field3$,_
4 as field4$
SetRAFfields = 0
else
SetRAFfields = 1 ' error condition
endif
end function
Re: Random Access Procedures
Post by joker on Oct 23rd, 2015, 11:32am
Let me paraphrase your comment ...
Quote: ... without LBB you really would be screwed. |
|
Without LBB you really are screwed!
Re: Random Access Procedures
Post by Richard Russell on Oct 23rd, 2015, 1:07pm
on Oct 23rd, 2015, 11:29am, pnlawrence wrote: I am studying every word you write. |
|
Apparently not acting upon however! :-)
Quote:This "library" seems to pass the RUN test (no program), but with an "incompatibility" error message. |
|
It still includes the line that doesn't work (either in LB or LBB):
Code: open filename$ for random as #fileHandle$ len = recordLen ' open and define record
I have twice listed the correct code, but for some reason you have failed to incorporate it.
You also have an endif where you meant end if.
Richard.
Re: Random Access Procedures
Post by joker on Oct 23rd, 2015, 7:19pm
At the risk of antagonizing Richard even further ... :D ... I do like to find the edges of proper operation.
LB reports a syntax error in the open line and LBB just says "Mistake!"
EDIT: Adding the "result =" bit-bucket for the FUNCTION makes the compilers happy.
Code:
path$ = ""
fileName$ = "myfile.txt"
fileHandle$ = "#file1"
recordLen = 10
field1$ = "1234"
field2$ = "1234"
field3$ = "1234"
field4$ = "1234"
' EDIT: openRAF(path$,fileName$,fileHandle$,recordLen)
result = openRAF(path$,fileName$,fileHandle$,recordLen)
put #fileHandle$, 1
call closeRAF fileHandle$
field1$ = ""
field2$ = ""
field3$ = ""
field4$ = ""
'EDIT: openRAF(path$,fileName$,fileHandle$,recordLen)
result = openRAF(path$,fileName$,fileHandle$,recordLen)
get #fileHandle$, 1
call closeRAF fileHandle$
print "1: "; field1$
print "2: "; field2$
print "3: "; field3$
print "4: "; field4$
end
sub closeRAF fileHandle$
close #fileHandle$
end sub
function fileExists(path$, filename$)
' dimension the array info$( at beginning of program
' dim info$(10, 10)
' e.g. if fileExists(DefaultDir$, "users.dat") then
files path$, filename$, info$()
fileExists = val(info$(0, 0)) 'non zero is true
end function
function openRAF(path$, filename$, fileHandle$, recordLen)
' file must exist?
' fileExists(path$, filename$)
' fileHandle$ = "#yourFileHandle"
open filename$ for random as #1 len = recordLen ' open and define record
maphandle #1, fileHandle$
openRAF = setRAFfields(fileHandle$, recordLen)
end function
function setRAFfields(fileHandle$, recordLen)
'field lengths and field names have to be modified per program
'call after openRAF
'set the fields in RAF
if (1+2+3+4) = recordLen then ' something to make one think about field lengths
field #fileHandle$,_
1 as field1$,_
2 as field2$,_
3 as field3$,_
4 as field4$
setRAFfields = 0
else
setRAFfields = 1 ' error condition
end if
end function
Re: Random Access Procedures
Post by Richard Russell on Oct 23rd, 2015, 9:32pm
on Oct 23rd, 2015, 7:19pm, pnlawrence wrote:LB reports a syntax error in the open line and LBB just says "Mistake!" |
|
It may be that you have previously used another language which allows a function to be called without assigning the returned value to anything, but Liberty BASIC doesn't. If you want to call a function, but ignore the value it returns, you must assign it to something, for example:
Code: ignoreThis = openRAF(path$,fileName$,fileHandle$,recordLen)
Richard.
Re: Random Access Procedures
Post by joker on Oct 24th, 2015, 09:51am
Now, there's a difference between SUB and FUNCTION that I missed. Thanks!
Re: Random Access Procedures
Post by Richard Russell on Oct 24th, 2015, 10:40am
on Oct 23rd, 2015, 9:32pm, Richard Russell wrote:If you want to call a function, but ignore the value it returns, you must assign it to something |
|
I occasionally use this construction, to avoid creating a dummy variable, but it's a bit ugly (and relies on a 'feature' of LB/LBB that rem and ' are not always equivalent):
Code: if openRAF(path$,fileName$,fileHandle$,recordLen) then rem
Richard.