|
After filling 'Dlr', I wanted to remove any 'empty' elements so that when it was sorted using 'sorta' there would not be a bunch of empty elements at the start.
VARYING won't help you here. VARYING only applies to character strings, it doesn't apply to arrays.
I've worked with that same problem many times. There are two solutions to it... one is to use the QSort() API (or another API) to do the sorting, and the second is to use the %SubArr() BIF that was introduced in V5R3.
Both solutions require you to declare a variable that your code uses to keep track of how many elements are in the array.
I made 'Dlr1' varying because when it was not, and 'Dlr' was varying, executing: %SubArr(Dlr:1:Idx) = %SubArr(Dlr1:1:Idx); caused each sub-field in 'Dlr' to be 'mis-positioned' by 2 characters.
yes, but I think you're misinterpreting what VARYING does. VARYING doesn't make your array variable-sized. It makes a character string variable sized.
Bob Cozzi indicated that this was (probably) caused by the 'hidden' index to the varying data structure.
There's no such thing as a varying data structure. Just a varying field -- and, of course, Bob is absolutely correct that the first 2 bytes contain the length of the string. This does not affect the length of the data structure, just the character string.
I really hate the fact that IBM implemented VARYING as a keyword. I think that all of the confusion surrounding VARYING is because it's really a data type, but you define in on a D-spec with a keyword. (and if the number of questions I get is any indication, there's a lot of confusion indeed)
But really, VARYING is a data type. Just as packed, zoned, binary and integer are all different data types that store numbers, alphanumeric and varying are both data types that store character strings.
Consider a simple example: D Test s 100A D Dlr s 100A varyingTest occupies 100 bytes of memory. No matter what you do with Test, it always occupies 100 bytes of memory, and the opcodes will always think that there's 100 bytes of data in it. If I type this:
Test = 'Hello Tim';Do you think that I've just assigned 9 bytes to Test? Nope. I've assigned 100 bytes. The characters 'Hello Tim' plus 91 blanks. The CPU will write every single character position every time I assign a value to "test". There's no way to make it be anyting other than 100 bytes long.
On the other hand: Dlr = 'Hello Tim';This Dlr variable is VARYING. It occupies 102 bytes of memory (100 bytes are reserved for data, and 2 bytes are reserved to keep track of the current length). It will always take up 102 bytes of physical memory, but when I use it, it only changes 11 bytes of memory. It first assigns the length of 9 (in the format x'0009') in the first 2 bytes, and then sets bytes 3-11 to the string 'Hello Tim'. The remaining 91 bytes are not changed, and if you use this string with RPG opcodes and BIFs they won't try to look at those 91 bytes, they'll only use the first 9 because they ignore anything after the length that was stored in the first 2 bytes.
So, IMHO, it's just a different type of variable for storing alpanumeric data. And a very useful one too... I rarely use fixed with strings anymore, to be honest.
VARYING doesn't have anything to do with data structures or arrays. consider this array: D Dlr s 100A varying dim(2500) That array isn't varying. Just as the following array isn't packed: D Test s 9P 2 dim(2500)The array isn't packed... rather it's a collection of 2500 fields, and each field contains a packed number. The same is true of the VARYING data type. In the first example, I don't have one varying-length array, I have 2500 varying-length character fields.
here's another example: D MyStruct ds D first 20A varying D last 20A varyingThis data structure isn't varying. However, it does contain two varying fields. The one called "first" occupies positions 1-22 of the DS, and the one called "last" occupies positions 23-44 of the DS.
IMHO, it would've been clearer if instead of making a "varying" keyword, they simply made a "V" data type.
D Dlr s 100v dim(2500) or D MyStruct ds D first 20v D last 20vIn my mind, anyway, that syntax is easier to follow. However, that's not the way IBM did it, so the above syntax won't work.
If they had done it that way, it also would've put an end to the continual questions and confusion abotu the difference between "varying" and "options(*varsize)" on a prototype. I get that question a lot. People don't udnerstand that VARYING is telling you the data type of the parameter, whereas options(*varsize) is telling the compiler not to do validity checking on the length.
But anyway... enough complaining about IBM for the moment. (The people in Toronto already hate me, why exacerbate it, right...)
D Ds Based(DlrBase) D Dlr 100A Varying D Dim(2500) D Ascend D DlrIdx Like(DlrDs.Idx) D Overlay(Dlr : 1) D DlrCode Like(DlrDs.Code) D Overlay(Dlr : *Next) D DlrType Like(DlrDs.Type) D Overlay(Dlr : *Next) [snip]So what do we have here? You've declared a character string that's 100A VARYING. Again, the VARYING doesn't apply to the array or the DS, ti applies to the length of each field in the Dlr array. Each field will be 102 bytes long. The first 2 bytes specify the length, the remaining 100 bytes are a character string.
DlrIdx, overlaying from position 1 of Dlr. Remember, the first two bytes of Dlr are that hidden length field -- so you've overlaid that field. Anything you assign to DlrIdx will change the length of Dlr. If the binary value of the first 2 bytes of DlrIdx happens to be higher than x'0064' (which in decimal is 100) then you'll get a "Length of varying length variable is out of range" error.
Since Dlr's only purpose (as far as I can tell) is to make it possible for all of the subfields to be stuck in the same array, there's absolutely no sense in making it VARYING. You aren't using it as an alphanumeric field, anyway, it's just a holding space for the array. Since the subfields are a fixed-length, it doesn't make sense for the field their defined on to be VARYING, does it?
Instead, I'd declare your DS as follows: D Ds Based(DlrBase) D Dlr Dim(2500) D Ascend D DlrIdx Like(DlrDs.Idx) D Overlay(Dlr : 1) D DlrCode Like(DlrDs.Code) D Overlay(Dlr : *Next) D DlrType Like(DlrDs.Type) D Overlay(Dlr : *Next) ... additional fields here...What did I change? I removed the word VARYING because, as I (hopefully) explained well enough, it doesn't make sense.
I also removed the 100A definition. There's no reason to hard-code the length of Dlr, because the compiler will figure it out for you based on the length of the subfields.
When you add elements to this array, have another field called "Dlr_Count" or something like that.
D Dlr_Count s 10I 0 Each time you add a new element to Dlr (or Dlr1 or whatever) do this: Dlr_Count = Dlr_Count + 1;The idea is, Dlr_Count will always have a count of what's stored in the Dlr_Array.
When it's time to sort it, if you don't want the blanks, do this: sorta %subarr(Dlr:1:Dlr_Count); Simple enough, eh?If you're not on V5R3, or would prefer to use an array of qualified data structures rather than an (ugly) overlay array, use the qsort() API instead of sorta.
qsort( %addr(Dlr): Dlr_Count: %size(Dlr): %paddr(CompProc) );
Because I had previously received the RNX0115 message, I evalledDlr1(2501)and it was displayed as empty.
That's the way the debugger has always worked, and has nothing to do with the VARYING keyword or anything else in your code. It doesn't verify that the number you type for an index is within the bounds of the array. If you specify a higher number, it'll calculate the spot in memory that WOULD be used if your array was large enough, and it'll look in that spot (very possibly viewing memory that's used for something else entirely.)
But that's a "bug" in the debugger -- not the RPG compiler or language.
The next statement: %SubArr( Dlr : 1 : Idx ) = %SubArr ( Dlr1 : 1 : Idx ); Resulted in the following error: Message ID . . . . . . : RNX0115 Severity . . . . . . . : 50
[SNIP] Hopefully you now understand why you got that error.I don't understand why you're doing this, however... if Dlr is based on a pointer, why not just point it to the memory where Dlr1 is sitting? Copying the data from one array to the other seems like an awful waste of CPU cycles.
Of course,I don't know where the pointer points to. If you need it to point to some other area of memory for some reason, I guess copying the data might be the right thing to do.
Why does Dlr1 now have 9834 elements?
It doesn't... the debugger just didn't try to stop you. Your code won't be able to access any data beyond the 2500th element.
Does DIMming an array not limit the maximum number of elements it canhave?
The debugger is just looking at the underlying memory for your variable. Remember, variables are an illusion! The computer doesn't understand variables, they're just for human convienience. At run time, everything is just space in the system's "main storage". Since the debugger has to display the contents of your variable at runtime, it looks at the memory behind the variable and reformats it to display it on the screen so you can read it.
Although RPG forces you to stay between 1 - 2500 when referencing indexes in your array, the debugger has no such safeguards (probably because there are other programming languages that don't have these safeguards) and will display elements that don't exist.
But, that's just an aspect of the debugger, it's not an aspect of your program or the RPG language.
As an Amazon Associate we earn from qualifying purchases.
This mailing list archive is Copyright 1997-2024 by midrange.com and David Gibbs as a compilation work. Use of the archive is restricted to research of a business or technical nature. Any other uses are prohibited. Full details are available on our policy page. If you have questions about this, please contact [javascript protected email address].
Operating expenses for this site are earned using the Amazon Associate program and Google Adsense.