×
The internal search function is temporarily non-functional. The current search engine is no longer viable and we are researching alternatives.
As a stop gap measure, we are using Google's custom search engine service.
If you know of an easy to use, open source, search engine ... please contact support@midrange.com.
Hello,
In using VB and C I have the ability to dynamically increase an array's size
from say 50 to 100 without losing the existing data, is this possible in
RPG?
RPG protects you from errors with validity checking, C does not. For
example, what's wrong with this C code?
int test[10];
int x;
for (x=1; x<=10; x++) {
test[x] = x;
}
At first glance it looks like it might even be valid -- but it's not.
This simple code will write data past the end of the array, causing
memory corruption! Neither the compiler nor the runtime will catch
mistakes like this because it doesn't do any bounds checking on the array
index. You could referrence test[500] if you wanted, it wouldn't report
any error, it'll just happily corrupt memory.
RPG is smarter than that. If you declare an array with 10 elements, it'll
only let you access those 10! The following program will crash when it
tries to access test(11):
D test s 10I 0 dim(10)
D x s 10I 0
c for x = 2 to 11
c eval test(x) = x
c endfor
So that's a GOOD thing because mistakes are found when the code is tested,
rather than random errors that are hard to track down because they only
occur sporadically.
At first glance you might be thinking "but, that means that I can't do
dynamic arrays!" Indeed, in C you could do the following:
int *test;
int maxelem;
int x;
maxelem = 10;
test = malloc((maxelem+1) * sizeof(int));
for (x=1; x<=maxelem; x++) {
test[x] = x;
}
maxelem = 20;
test = realloc(test, (maxelem+1) * sizeof(int));
for (; x<=maxelem; x++) {
test[x] = x;
}
free(test);
And that'll work, because there's no bounds checking on the array, so you
can change the number of elements in it at any time, and it'll let you
access those elements. You can do the same thing in RPG, but in order to
do so, you must declare the array with the MAXIMUM number of elements
you'll ever use. That way, the system won't stop you from accessing
them... best of both worlds:
D int s 10I 0
D p_test s *
D test s dim(32767)
D like(int)
D based(p_test)
D max s 10I 0
D x s 10I 0
c eval max = 10
c eval p_test = %alloc(%size(int) * max)
c for x = 1 to max
c eval test(x) = max
c endfor
c eval max = 20
c eval p_test = %realloc( p_test
c : %size(int) * max)
c dow x < max
c eval x = x + 1
c eval test(x) = max
c enddo
c dealloc p_test
Basically, declaring the array out to 32767 elements gives you the same
sort of flexibility that C has, you can use any number you like. Since the
array is BASED, it only uses as much memory as you've allocated, anyway.
Of course, the one problem that remains is when you need to handle more
than 32767 elements! At this point, you might start considering whether
an array is the right tool for the job. Other people have suggested
embedded SQL and work files, both good suggestions.
If you do decide to stay with an array, you can do that, too... well, sort
of. Stop and consider what an array is -- it's merely a spot in memory
where there are many fields of the same type repeating. test(1) is
immediately followed by test(2), which is followed by test(3), etc. Under
the covers the system says "hmm... he wants element #12. Since each
element is 4 bytes long, that means he wants to look at bytes 45-48!"
Well, okay, the CPU probably doesn't actually say "hmm"
You can do that logic manually, as well. When you do that, you completely
eliminate array bounds checking, so you can make your array as large as
you want. It's called pointer math :)
H DFTACTGRP(*NO)
D SetArrayPos PR
D Index 10I 0 value
D max s 10I 0
D p_test s *
D p_elem s *
D elem s 10I 0 based(p_elem)
D max s 10I 0
D x s 10I 0
c eval max = 10
c eval p_test = %alloc(%size(elem) * max)
c for x = 1 to max
c callp SetArrayPos(x)
c eval elem = x
c endfor
c eval max = 20
c eval p_test = %realloc( p_test
c : %size(elem) * max)
c dow x < max
c eval x = x + 1
c callp SetArrayPos(x)
c eval elem = max
c enddo
c dealloc p_test
c eval *inlr = *on
P SetArrayPos B
D SetArrayPos PI
D Index 10I 0 value
c eval p_elem = p_test
c + (Index-1) * %size(Elem)
P E
Using that approach, you're still limited to 16mb of space, but changing
the code to use TS_malloc() and TS_realloc() (instead of %alloc and
%realloc) would make it possible to bypass that limit as well.
The only thing I'd like to caution you on if you use these techniques is
that %realloc (or TS_realloc or the REALLOC op-code... whatever) actually
allocates a new spot in memory and copies the data to it. (If you've done
this in C, you should already know that!) You should take care to keep the
re-allocating to a minimum. Maybe allocate 1000 elements at a time or
something like that so that so that the code doesn't spend TOO much time
copying stuff in around in memory.
Good luck
As an Amazon Associate we earn from qualifying purchases.