#lang "qb" + Dim Varx as Byte

New to FreeBASIC? Post your questions here.
Post Reply
WAGNERLIP
Posts: 8
Joined: May 27, 2013 6:30

#lang "qb" + Dim Varx as Byte

Post by WAGNERLIP »

Okay, I am trying to make a big QBasic file works in FreeBasic.
It is 98% working, now just little bits of problems that is causing me to desperate.

First:
In QB I was using

Code: Select all

Open "filename" for Random as #1 len=1
Field #1, 1 as A$
Get #1
or  Get #1,,A$
So, the "random" filename could be read byte at a time into A$.

In FB, with #Lang qb

Open "filename" for Random as #1 len=1
Get #1,,A$

FB doesn't deal with [Field], so I can't define correctly what or how many bytes will be read in each "Get".
Even the "len=1" in the opening statement, [Get #1,,A$] will read as many bytes into A$ as it seems fit.
I don't know exactly what logic it uses, but it seems that if it only stops to "get" bytes from the file into A$, when the byte is not alpha-numeric, I mean, ASCII lower than "!" and higher than "z", or something like that.

It is impossible to make it work correctly.

So, well, it seems the GET just pull bytes according to the variable definition.
If I use

Code: Select all

Dim A as Integer
Open "filename" for random as #1 len=1
Get #1,,A
The GET will pull 4 sequential bytes into A, even that I want just the *next* byte.
Dim A as Short will pull 2 bytes

Well, [Dim A as Byte] should work, but it can't be used in #lang qb.
The literature say to use _byte instead.

I can't figure out how to use the _byte

Dim A as _byte ???
Compilation error: Expected End-of-Line, found '_BYTE'

Any help please?

Cheers,
counting_pine
Site Admin
Posts: 6323
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Re: #lang "qb" + Dim Varx as Byte

Post by counting_pine »

In lang qb, FB keywords are preceded by two underscores, eg __byte.
counting_pine
Site Admin
Posts: 6323
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Re: #lang "qb" + Dim Varx as Byte

Post by counting_pine »

I think instead of RANDOM ... LEN=1, I would recommend using BINARY for reading bytes.
This can be done using a __byte/__ubyte variable, or for a method that will also work in QB, a var-length string containing a single character.

Code: Select all

Dim A as String
Dim B as __UByte
Open "filename" for binary as #1
A = " ": Get #1, , A
Get #1, , B
Print "First two bytes: ###_, ###"; asc(A); B
Close #1
WAGNERLIP
Posts: 8
Joined: May 27, 2013 6:30

Re: #lang "qb" + Dim Varx as Byte

Post by WAGNERLIP »

counting_pine wrote:I think instead of RANDOM ... LEN=1, I would recommend using BINARY for reading bytes.
This can be done using a __byte/__ubyte variable, or for a method that will also work in QB, a var-length string containing a single character.

Code: Select all

Dim A as String
Dim B as __UByte
Open "filename" for binary as #1
A = " ": Get #1, , A
Get #1, , B
Print "First two bytes: ###_, ###"; asc(A); B
Close #1
Oh well, I spent 2 full days and nights to finally convert the huge QB code to FB Syntax, now I have all the bells and whistles, including the "as byte" and "as ubyte", now it is easy.

What took most time was converting a non structure code macarroni to one using [SUBs]. Some traps got me into oblivion for a while, like for example [sleep] is a thousand times shorter in FB than in QB (milliseconds vs seconds), and the horrible lack of [FIELD] of random files with strings.

That [FIELD] structure in regular Basic platforms is the grandfather of some actual database systems, where you tell the platform to get a certain quantity of bytes and pour over a line of strings, and the right quantity and exact bytes fall into such variables, easily. The lack of [FIELD] complicate things, but no problem, nothing that time and patience doesn't solve it.

Yes, to read bytes [Binary] is the right choice instead of [Random] when you do not have [FIELD] option.

Now, after some 40+ hours of labor, everything seems to work, except that [OPEN filename for OUPUT as #1] doesn't work if filename, anywhere in the harddisk, has hidden attribute set to on. It fails.

Cheers,
Theunis Jansen
Posts: 248
Joined: Jul 01, 2010 9:35

Re: #lang "qb" + Dim Varx as Byte

Post by Theunis Jansen »

for RANDOM files you should use Type... END TYPE it was already the QB alternative for FIELD.
BUT !! FB random is not the same as a QB RANDOM file
i.e
TYPE MyFILe
A as string * 10
B as string * 3
END TYPE
DIM MyMess as MyFile

FB was made compatible with C in this regards and not QB so the use of fixed length strings be they in a RANDOM file or not is not so good.
eg. A as string * 10 - if A$ is only 7 chars then it pads it with Null. while in QB it is padded with a space Chr$(32) and 10 chars are stored. However FB then stores 10 + a further NULL ie 11 chars are stored.
Now when it comes to concatenating strings if A is actually only 7 chars then it is a total flop if you relied on it for formatting. ie the normal padding by QB with three spaces is just not there.

However knowing this you can RTRIM the string and then add the missing spaces.
What I did was RTRIM$(MyMess.A) : MyMess.A = Left$(MyMess.A + STRING$(10,CHRS(32)),10). (OR....... + STRING$(10,32),10)

Furthermore in order to read an existing QB RANDOM file I had to write a small conversion program for BINARY access and then wrote it to a FB RANDOM file after converting it as mentioned in the preceding paragraph. FB totally messes up when it comes to reading a QB RANDOM file because of it's extra Char.

For a new as yet NO DATA FB RANDOM file this is of course not applicable. But if you want a proper padded file then I suggest do what I did.
Last edited by Theunis Jansen on Jun 02, 2013 10:06, edited 1 time in total.
counting_pine
Site Admin
Posts: 6323
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Re: #lang "qb" + Dim Varx as Byte

Post by counting_pine »

Lamentably with string*n, the best strategy is generally not to use them. It is rare to find a case where they work the way you'd want/expect them to.
Unfortunately, until we fix them, there is no foolproof way to use fixed-length strings in types.
Theunis Jansen
Posts: 248
Joined: Jul 01, 2010 9:35

Re: #lang "qb" + Dim Varx as Byte

Post by Theunis Jansen »

Umm bearing in mind how I bypassed it, it is quite a success and virtually foolproof.
Using this method I haven't had any bugs or strange results. Okay a few lines extra in a SUB but we got so used to finding solutions in QB that this is just another
"don't give up bypass."
counting_pine
Site Admin
Posts: 6323
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Re: #lang "qb" + Dim Varx as Byte

Post by counting_pine »

It's not foolproof. There is the complete compatibility break with QB, the potential for everything to break if/when we fix string*n, and the question of whether a null terminator will appear anywhere. If no null char appears in the data then reading the string could go outside the valid memory.

A more foolproof solution is to use byte arrays, and write a couple of conversion routines to/from strings.
Here's one way. A faster way would be to include crt.bi and use memcpy.

Code: Select all

function strfromarray(a() as ubyte) as string
    dim as integer lb = lbound(a), ub = ubound(a)
    dim as integer l = ub - lb + 1
    dim as string ret = space(l)
    for i as integer = 0 to l-1
        ret[i] = a(i + lb)
    next i
    return ret
end function

sub arrayfromstr(a() as ubyte, s as string, lb as integer, ub as integer)
    dim as integer l = len(s)
    if l > ub - lb + 1 then l = ub - lb + 1
    for i as integer = 0 to l-1
        a(i + lb) = s[i]
    next i
end sub

dim a() as ubyte, s as string
s = "Hello world"

redim a(1 to len(s))
arrayfromstr(a(), s, 1, len(s))
s = strfromarray(a())
print s

a(1) = asc("h")
s = strfromarray(a())
print s
EDIT: fixed some bugs that emerge when the lower bound is nonzero. Thanks fxm.
Theunis Jansen
Posts: 248
Joined: Jul 01, 2010 9:35

Re: #lang "qb" + Dim Varx as Byte

Post by Theunis Jansen »

Okay the "potential" to break may be there but I have been using it (after the conversion of the QB RANDOM file to a FB RANDOM file) for the past two-and-a-half months and it has not broken.
If you pad it with spaces before saving to a random file the final null is always there and the length is always correct. (And it still remains compatible with the standard QB (or FBlite) language.)

So this is as originally intended only a suggestion and a virtually foolproof, for my purposes, way to do it. I made the incompatibility compatible even if I used a bit of a shlep. (An Unnecessary bother)

As far as I can make out the final Null is more or less an indicator for the end of that String/Variable. I also did something similar when I, to bypass the DOS limitations re the number of entries per folder, wrote my own QB FAT file to write to a binary file. I have over twothousand club records in one file that I read in in bits and pieces. After twenty writes, to any record, I automatically rewrite the DATA file by using the FAT file and then walla I have an unfragmented DATA file and a New FAT file. (This is/was a massive shlep)
Post Reply