Reading tabled data
BlitzMax Forums/BlitzMax Beginners Area/Reading tabled data
| ||
| I've asked this question before, but at that time there wasn't a ready answer. Consequently, I had decided to wait until the full version was released with documentation. However, today after downloading the most recent update I noticed the stdc module, which includes fopen but not fscanf or fprintf. Anyway with some two months having passed, is there an easy way to read tabled data into a struct? |
| ||
| what exactly do you mean by tabled data? perhaps you can give an example of the file you want to read? |
| ||
| Take the following as an example, -- smith 34 160 jones 26 176 blake 29 166 --- In C, #define MAXRECORDS 100 typedef struct { char name[30]; int age; int height; }DATA; DATA *users = malloc(MAXRECORDS * sizeof(DATA)); then read the file so that individual records can be easily accessed using a numerical index. I use fscanf in this case and fprintf for the opposite. These functions have made it relatively easy to manage my data in C. As Blitzmax evolves I wouldn't mind migrating. |
| ||
| hmmm. I thought someone might have given you a good answer, as I think there might be a clever solution to this.. But from what I can gather, you should be able to do the same thing in 'Max relatively easy.. Say using banks or (RAM)streams... |
| ||
| [edit] DOH! Not what you asked :D Something like this, might work: Const MAXRECORDS = 100 Type Data Field name:String Field age:Int Field height:Int Method WhoIs() Print "Name: "+self.name+", Age: "+self.age+", Height: "+self.height+"cm" EndMethod EndType Local users:Data[MAXRECORDS] For Local i = 0 Until MAXRECORDS users[i] = New Data users[i].name = "Bob "+i users[i].age = Rand(0,100) users[i].height = Rand(100,200) Next users[10].WhoIs() users[45].WhoIs() users[89].WhoIs()You wouldn't need a max number of records, as you can easily resize the array if you need to. |
| ||
| Ok, I assume you will want to read the file, which has certain seperators to show, when a new entry is there? So something like this should work:
Function ReadDString:String(stream:TStream,seperator:Byte[])
If stream = Null
Return ""
EndIf
Local b:byte
Local s:String
While Eof(stream) = False
b = ReadByte(stream)
For Local i = 0 Until seperator.length
If b = seperator[i]
Return s
EndIf
Next
s :+ Chr(b)
Wend
End FunctionYou then need to open a file, and supply that and a list of seperator values to it...Something like this: myfile = ReadFile("hello.txt")
Repeat
Local s:string = ReadDString(myfile,[Asc(" "),10])
Print s
Until s = ""
CloseFile(myfile)It's not tested, so it might be buggy :) |
| ||
| Thank you for the examples. I tend to use space separated variables and read until not EOF. I believe that fscanf is flexible in that the number of spaces dosn't matter. Hardcoding the separator would be less tolerant in this case. |
| ||
I've created some code for you (with comments):
Type Data
Global DataArray:Data[]
Field Name$
Field Age%
Field Height%
Function ReadTabledData(DFH%)
Local LineFromFile$ = ReadLine$(DFH%) ' Read a line from the given filehandle
Local a:Data = New Data ' Create a new "Data"-object
' Store the name without ending spaces
a.Name$ = LineFromFile$[..10] ' Copy the first 10 characters from the line into field Name$ (0..9)
' Remove spaces at the end of the name
While Chr(a.Name$[a.Name$.length - 1]) = Chr(32)
a.Name$ = a.Name$[..(a.Name$.length - 1)]
Wend
a.Age% = Int(LineFromFile$[10..15]) ' Copy the characters 10..14 to the Age-field and convert to Int
a.Height% = Int(lineFromFile$[15..20]) ' Copy characters 15..19 to the Height-field and convert to Int
' Resize the array to hold one more object
DataArray = DataArray[..(DataArray.length + 1)]
' Add the new Data-object to the array
DataArray[DataArray.length - 1] = a
End Function
End Type
' Open a file for reading (DFH = DataFileHandle)
Local DFH% = ReadFile("c:\Test.txt")
' Keep reading until EndOfFile
While Not Eof(DFH%)
Data.ReadTabledData(DFH%)
Wend
' Close the file
CloseFile(DFH%)
' Print all names and ages
For i = 0 Until Data.DataArray.length
Print "Name = " + Chr(34) + Data.DataArray[i].Name$ + Chr(34)
Print " Age = " + Chr(34) + Data.DataArray[i].Age% + Chr(34)
Print " Height = " + Chr(34) + Data.DataArray[i].Height% + Chr(34)
Print
Next
End
File Test.txt: Johnny 20 185 Piet 27 170 Geert 26 182 Gert 28 120 Cornelis 50 150 |