Type..End Type QB/FBlite bug ?

General FreeBASIC programming questions.
Post Reply
Theunis Jansen
Posts: 248
Joined: Jul 01, 2010 9:35

Type..End Type QB/FBlite bug ?

Post by Theunis Jansen »

This looks like a Bug
I have a TYPE OrderIt...END TYPE With 15 STRING * x elements.
Dim Order as OrderIt
I open the file as RANDOM ......... Len = Len(Order).
Using #Lang "fblite" when displaying the records they are all screwed up.

After much searching I said Print Len(Order) which printed 304. When I manually total them I get 289
which explains why the records are all messed up.
I get the impression that every field gets 1 added to it. Ie Item1 AS STRING * 10 ends up as STRING * 10 + 1 etc.

The prog starts off with - DEFINT A-Z.

I am using the latest FBC and FBide
At this stage my program compiles without errors, but.....
Last edited by Theunis Jansen on Mar 22, 2013 13:58, edited 1 time in total.
fxm
Moderator
Posts: 12108
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Type..End Type QB/FBlite bug ?

Post by fxm »

Theunis Jansen wrote:I get the impression that every field gets 1 added to it. Ie Item1 AS STRING * 10 ends up as STRING * 10 + 1 etc.
Yes:

Code: Select all

Dim As String * 10 s

Print Sizeof(s)

Code: Select all

Type UDT
  Dim As String * 10 s
End Type

Print Sizeof(UDT)
For the consequences inside an UDT, the explaination is in the documentation about Type:
.....
Special note on fixed length strings
Currently, fixed-length string fields of String * N type have an extra null terminator at their end, for compatibility with C strings, making them incompatible with QB strings inside Types, because they actually use up N+1 bytes, instead of just N bytes. A possible work-around is to declare the field As String * (N-1), though this will not work in future releases if the null terminator is removed. Another alternative is to use a Byte array with the proper size.
.....
See also the second example.
Theunis Jansen
Posts: 248
Joined: Jul 01, 2010 9:35

Re: Type..End Type QB/FBlite bug ?

Post by Theunis Jansen »

Thanks FXM

I will try the (N - 1) suggestion.

But this is a rather major incompatibility
Theunis Jansen
Posts: 248
Joined: Jul 01, 2010 9:35

Re: Type..End Type QB/FBlite bug ?

Post by Theunis Jansen »

@FXM

when you come to STRING * 1 then it cannot be done because of the default string length. So this only works of the N-x is 2 or more.

Looks like I will have to figure out a BINARY read of the DATA, but then another problems shows up when I put the DATA unless I Also do it in BINARY.
My one program has 22 elements and the one I am busy with has 15.

Oh well to get past the Old DOS number of files per directory I wrote my own FAT type file but that was about 15 years ago. (There were over 2000 Club members)
fxm
Moderator
Posts: 12108
Joined: Apr 22, 2009 12:46
Location: Paris suburbs, FRANCE

Re: Type..End Type QB/FBlite bug ?

Post by fxm »

The other alternative is to use Ubyte arrays with the proper sizes, and procedures to convert string->ubyte() and ubyte()->string:

Code: Select all

Type UDT Field = 1
  Dim As Ubyte b1 (0 To 9)
  Dim As Ubyte b2 (1 To 15)
End Type

Function UbyteToString (ub() As Ubyte) As String
  Dim As String s = Space(Ubound(ub) - Lbound(ub) + 1)
  For I As Integer = Lbound(ub) To Ubound(ub)
    s[I - Lbound(ub)] = ub(I)
  Next I
  Return s
End Function

Sub StringToUbyte (Byref s As String, ub() As Ubyte)
  For I As Integer = 0 To Len(s) - 1
    If I <= Ubound(ub) Then
      ub(I + Lbound(ub)) = s[I]
    End If
  Next I
  For I As Integer = Len(s) To Ubound(ub) - Lbound(ub)
    ub(I + Lbound(ub)) = 0
  Next I
End Sub


Dim As UDT u
Print Sizeof(u)
Print
StringToUbyte("0123456789", u.b1())
StringToUbyte("ABCDEFGHIJKLMNO", u.b2())
Print UbyteToString(u.b1())
Print UbyteToString(u.b2())
Sleep
[Edit]
Code modified as proposed by counting_pine below.
Last edited by fxm on Mar 22, 2013 19:15, edited 1 time in total.
counting_pine
Site Admin
Posts: 6323
Joined: Jul 05, 2005 17:32
Location: Manchester, Lancs

Re: Type..End Type QB/FBlite bug ?

Post by counting_pine »

Ubyte arrays are the preferred method for several reasons, including the fact that if we remove the null terminator in the future, all the types using them will break again!

When making an array of a specific size, a good idiom is to use 'arrayname(0 to size-1)' or 'arrayname(1 to size)'. This makes it obvious how large the array is.

If you use a lower bound of 1 (i.e. something that's not 0), then UbyteToString() will need to be updated as follows:

Code: Select all

Function UbyteToString (ub() As Ubyte) As String
  Dim As String s = Space(Ubound(ub) - Lbound(ub) + 1)
  For I As Integer = Lbound(ub) To Ubound(ub)
    s[I - Lbound(ub)] = ub(I)
  Next I
  Return s
End Function
EDIT: fixed oversight pointed out by fxm
Theunis Jansen
Posts: 248
Joined: Jul 01, 2010 9:35

Re: Type..End Type QB/FBlite bug ?

Post by Theunis Jansen »

I fixed my problem. Opened two files - 1 as BINARY 2. as RANDOM
Calculated the number of files used For i=1 to NumberRecords...Next
Read the BINARY file using A$=INPUT$(289,i) (289 = Total for the elements). Converted the String with Mid$... to the TYPE... END TYPE elements and saved it to the Random file.
Set the Seek Position for the next record etc etc. until the FOR...NEXT ended
Post Reply