Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
DYNAMIC FIXED LENGTH STRING ARRAYS
#1
Can someone tell me why this gives me an 'Expected Constant'
error on compiling:

'$DYNAMIC

X=1000
Y=27

DIM MyArray(X) AS STRING * Y

But this does not give the error:

DIM MyArray(X) AS STRING


I am reading a file to determine the number of elements I
will need to load into the array and the width of the field
in the file before I DIM the array so that I don't allocate
more memory than necessary. So I prefer to have both
the array's number of elements and the size of the string to
be variables. If I don't define the string size, what are the
implications?

Dean
Reply
#2
I'm not sure, but as far as I remember, you must use REDIM to properly dimention dynamic arrays and variables

EDIT: Duh, I didn't notice the * variable. Listen to him.
Reply
#3
No, thats only if you're not using '$DYNAMIC

Strings cant be variable fixed lenght


Y is a variable.

If the strings are always 27, then just replace Y with 27, or do:
Const y = 27

Or even:
#define y 27
Reply
#4
I just gave the values of X & Y for the example here.

I will not know either of the values until I open a database file,
get the number of records, and determine the width of the field
that I have to load into the array.

So, I will not be able to define either X or Y as constants.
X would be # of elements = # of records, Y would be width of record
or field in the database.

Since I'm not getting an error by just DIM'ing X and leaving out
* Y, I'm wondering if I do that just to get past this, what memory
issues am I creating. Either I will not have enough memory since
I didn't allocate enough in the DIM statement, or perhaps I am
using up more by not limiting the width to only what I need.

What is the default size for a string array where the width is not
defined in the DIM statement?

Dean
Reply
#5
I think strings internally is a byte pointer and a length integer. They are both null (or possibly the byte pointer is pointing to some global empty zero delimited string), but anyway, variable length strings are empty at first, thus initially sizeof(string) = sizeof(string descriptor).

When you change the string, it will need a byte for each character in the string + an additional byte for it to be null terminated + the string descriptor. In other words, you are maybe wasting lenght + pointer + byte = 4 + 4 + 1 = 9 bytes per string.

If this is unsuitable (ie. you have a huge bunch of strings), I suggest you use a byte array:
redim MyArray(X, Y) as byte

That way you don't need additional space.

Happy coding
Reply
#6
try a 2d byte array... wasnt this just posted somewhere??

dim (x, y) as byte ' or ubyte

edit: beat me ;)
Reply
#7
I guess you will have to do an array of variable length strings, initializing them with spaces to the correct size
Antoni
Reply
#8
I'm not sure how the 2d byte array helps me -- I need to store
alpha numeric character strings -- BYTE is a numeric data type.
Are you suggesting I store the ascii values of each character
of my string? That would be too much for me to manage.
Not sure I'm following the 2d example. Maybe you could give
me a sample piece of code that stores "ABC" and "XYZ" in
a 2d byte array.

I could always resort to the worst case scenario, of having
a huge case statement with a case for each possible string
length and each case having its own hard coded DIM with
a different constant based on the string length
(what a ridiculous thing to do).

But, now I have another issue with how much memory is
being consumed even if I do have a constant for the string
length, and how to calculate what I can handle with available
memory. Losing around 9 bytes is a huge waste because I
have millions of short strings usually < 30 characters.

What I need to do is sort the data after I load it into memory,
and what I had in mind was to load it into an array, then
use QSORT to sort the array. If it's going to take another 9
bytes or so for each element of the array, I'm going to waste
a lot of memory. Any more ideas, or specific examples of how
best I can accomplish this objective, would be greatly appreciated.

Finally, in trying to figure out how much memory I have to
work with, I think I may have found a bug in FRE. Whenever you
call FRE, the first time you get a different value than the ubsequent
times:

PRINT FRE
PRINT FRE
PRINT FRE
PRINT FRE

The first time FRE is called it always gives a different number than
the subsequent times. The first time its value is always 4096
or 8192 bytes more than the second and subsequent times.

Dean
Reply
#9
if you give an example of a full function using this method in qb, ill show u how to convert it into byte arrays. cant be asked to write it from scratch :P
Reply
#10
Hi:

If a variable length string is what suits your needs best, then you can still use the C runtime qsort to sort the array. You create an array of pointers, and sort the array using a user function, which you pass to qsort. You can expect this to be a bit slower (30% in my one test) than sorting fixed length strings, but it is still faster than any other sorting routine I have seen. If this is what you want then I can show you how to use qsort.

Are you reading the data from disk? If so consider opening it for binary access and reading the whole lot into memory in one go. Replace the CR+LF with NULLs and indexing it in one pass. Then sort the array of pointers using qsort. I did not try this in FreeBASIC, but it is very, very fast in C and it should be workable.

Have fun

Garvan
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)