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 |