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?
Reading tabled data
BlitzMax Forums/BlitzMax Beginners Area/Reading tabled data what exactly do you mean by tabled data?
perhaps you can give an example of the file you want to read?
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.
--
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...
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:
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:
Something like this:
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 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):
File Test.txt:
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