Home | Reviews | GUIpedia | Forum | Fun500
pharoah | A simple way to give your scripter nested arraysA lot of the scripting languages that I've seen people write seem to store everything as strings. Almost all of them at least have a string type and string parsing functions like instr(), left() mid(), etc... But they hardly ever have a nice array construct that you can use to actually do something useful. Fortunately, that's easy to fix. What we want to be able to do is to use a single string to store a list of strings (I'll be calling a one dimensional dynamic array a "list" from now on). How do we do this? Simple. Let's say you've got three strings that you want to store in one string: [ol] [li]Foo[/li] [li]Bar[/li] [li]plonk[/li] [/ol] We could just put these in one string, let's look at that: "FooBarplonk" Not very nice. You can see that there's no good way to pull the three list elements back out again, because you don't know where they stop and start. You could try delimiting them with something, () for example: "(Foo)(Bar)(plonk)" That works very well, until you have a string with parentheses in it. The trouble with delimiters is that, no matter what delimiter you choose, your string could potentially have that in it. If you're familiar with other languages, we could solve this problem by escaping (replacing "(" with "(" and "" with ""), but that gets messy fast. Fortunately, there is a solution. The key is to use a format called NetStrings or one of its variants. You first specify the length of the string, then some non-numeric character (to signal the end of the length part), then the string itself. There are several formats you could use for this: "3:Foo3:Bar5:plonk" (Bencode format) "3:Foo,3:Bar,5:plonk" (Netstrings standard) "3:Foo, 3:Bar, 5:plonk" "(3:Foo, 3:Bar, 5:plonk)" (My own invention, bracketed form) "3:'Foo', 3:'Bar', 5:'plonk'" "(3:'Foo', 3:'Bar', 5:'plonk')" The longer formats are more human readable (for, say, dumping into a storage file), but they also waste more space storing the same data. If you're brave, you could use something like cvi() to store the lengths in the string as binary, but I'd strongly advise against that. Now we can store a list of strings in a string, but what about multi-dimensional arrays? Well, notice that the list we just constructed is a string. Here it is, in bracketed form (you'll see why that makes it easier to read in a sec): "(3:Foo, 3:Bar, 5:plonk)" Okay, now I want to make a new list of strings that's totally unrelated, I promise: [ol] [li](3:Foo, 3:Bar, 5:plonk)[/li] [li](4:Spam)[/li] [li](4:Eggs)[/li] [/ol] See what I did there? You can put a list string INSIDE a list string! Not only does this let you do multi-dimensional arrays like what Qbasic and Freebasic have, but it also lets you make "jagged" arrays, that is arrays with containing arrays of different lengths. Here's the final list: "(23:(3:Foo, 3:Bar, 5:plonk), 8:(4:Spam), 8:(4:Eggs))" You can see why I used the bracketed notation, it makes it easier to see how these are nested without having to count. I'm not saying that this is the best way to do it (it's clearly not a space saver), but it worked best in this tutorial. You'll have to write the functions to build these strings and extract elements yourself, but trust me, it's worth it. Considering that FreeBasic still doesn't let you make arrays of arrays without fiddling with pointers, it might be nice even for non scripting tasks. If your scripter supports procedures, you can write an array library right in your language. You could always write it in QB or FB right off the bat as well. | 2009-12-02 | 5:15 PM |
SonicBrit | Re:A simple way to give your scripter nested arraysSo whats interesting is qbasic uses a notation called counted string, which basically has the length of the string(in binary) followed by the string itself. So when you call Len, it just grabs that value, (C it actually parses the string until it finds a 0 nul character) But I do like that you could stack them together, be interesting to see what methods you come up with, push, pop etc..? | 2009-12-02 | 6:10 PM |
2021 Brandon Cornell