Lazarus

Programming => General => Topic started by: Pixy on May 20, 2019, 04:58:39 am

Title: [RESOLVED] Add integers to an array
Post by: Pixy on May 20, 2019, 04:58:39 am
I am using this:
Code: Pascal  [Select]
  1. var
  2.     IntAr: array of integer;
  3.  
  4. begin
  5.     IntAr[0] := 115;
  6.     IntAr[1] := 160;
  7.    ...
  8. end.
  9.  
but I get an access violation error. Any idea how I can add individual integers to the array?
Title: Re: Add integers to an array
Post by: RAW on May 20, 2019, 05:25:06 am
SetLength
Title: Re: Add integers to an array
Post by: 440bx on May 20, 2019, 05:30:09 am
RAW above is right, a little succinct but definitely right.   Here are some more details.

I am using this:
Code: Pascal  [Select]
  1. var
  2.     IntAr: array of integer;
  3.  
  4. begin
  5.     IntAr[0] := 115;
  6.     IntAr[1] := 160;
  7.    ...
  8. end.
  9.  
but I get an access violation error. Any idea how I can add individual integers to the array?
An "array of integer" is just a pointer to an array.  The array itself doesn't exist until you use the function "SetLength" to tell the compiler how many elements you want in the array.    (until you use SetLength there is no memory allocated for the array.)

if you do something along the lines of:
Code: Pascal  [Select]
  1. SetLength(IntAr, 10);
that will give you an array of 10 elements where the first element has index 0 and the last element has index 9.  To iterate through the array you can use
Code: Pascal  [Select]
  1. for I := low(IntAr) to high(IntAr) do ....
that way you don't have to hard code or remember the lower and upper bounds of the array (which will always be zero to count - 1.)

HTH.
Title: Re: Add integers to an array
Post by: valdir.marcos on May 20, 2019, 05:39:49 am
I am using this:
Code: Pascal  [Select]
  1. var
  2.     IntAr: array of integer;
  3. begin
  4.     IntAr[0] := 115;
  5.     IntAr[1] := 160;
  6.    ...
  7. end.
but I get an access violation error. Any idea how I can add individual integers to the array?
http://wiki.freepascal.org/Array
http://wiki.freepascal.org/Dynamic_array
Code: Pascal  [Select]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   ArraySize: Integer;
  4.   IntAr: array of Integer;
  5. begin
  6.   ArraySize := 0;
  7.  
  8.   ArraySize := ArraySize + 1;
  9.   setLength(IntAr, ArraySize);
  10.   IntAr[0] := 115;
  11.  
  12.   ArraySize := ArraySize + 1;
  13.   setLength(IntAr, ArraySize);
  14.   IntAr[1] := 160;
  15.  
  16.   ShowMessage('IntAr[0]: ' + IntToStr(IntAr[0]) + LineEnding +
  17.               'IntAr[1]: ' + IntToStr(IntAr[1]));
  18. end;
Title: Re: Add integers to an array
Post by: Pixy on May 20, 2019, 05:55:10 am
Thanks for the information guys RAW, 440bx, valdir.marcos.

I am using this:
Code: Pascal  [Select]
  1. var
  2.     IntAr: array of integer;
  3. begin
  4.     IntAr[0] := 115;
  5.     IntAr[1] := 160;
  6.    ...
  7. end.
but I get an access violation error. Any idea how I can add individual integers to the array?
http://wiki.freepascal.org/Array
http://wiki.freepascal.org/Dynamic_array
Code: Pascal  [Select]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   ArraySize: Integer;
  4.   IntAr: array of Integer;
  5. begin
  6.   ArraySize := 0;
  7.  
  8.   ArraySize := ArraySize + 1;
  9.   setLength(IntAr, ArraySize);
  10.   IntAr[0] := 115;
  11.  
  12.   ArraySize := ArraySize + 1;
  13.   setLength(IntAr, ArraySize);
  14.   IntAr[1] := 160;
  15.  
  16.   ShowMessage('IntAr[0]: ' + IntToStr(IntAr[0]) + LineEnding +
  17.               'IntAr[1]: ' + IntToStr(IntAr[1]));
  18. end;

I think that this is going to work. I'll try that.
Title: Re: Add integers to an array
Post by: lucamar on May 20, 2019, 06:11:26 am
Thanks for the information guys RAW, 440bx, valdir.marcos.

Code: Pascal  [Select]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   ArraySize: Integer;
  4.   IntAr: array of Integer;
  5. begin
  6.   ArraySize := 0;
  7.  
  8.   ArraySize := ArraySize + 1;
  9.   setLength(IntAr, ArraySize);
  10.   IntAr[0] := 115;
  11.  
  12.   ArraySize := ArraySize + 1;
  13.   setLength(IntAr, ArraySize);
  14.   IntAr[1] := 160;
  15.  
  16.   ShowMessage('IntAr[0]: ' + IntToStr(IntAr[0]) + LineEnding +
  17.               'IntAr[1]: ' + IntToStr(IntAr[1]));
  18. end;

I think that this is going to work. I'll try that.

That's ... wasteful, to be mild. If you know the exact number of items in the array do it like this:

Code: Pascal  [Select]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. const
  3.   ArraySize = 2;
  4. var
  5.   IntAr: array of Integer;
  6. begin
  7.   setLength(IntAr, ArraySize);
  8.   IntAr[0] := 115;
  9.   IntAr[1] := 160;
  10.   ShowMessageFmt('IntAr[0]: %d' + LineEnding + 'IntAr[1]: %d', ,[IntAr[0], IntAr[1]);
  11. end;

Each time you use SetLength() a new block of memory has to be allocated, the existing array copied over and the old memory block disposed. Call SetLength() as few times as you possible can.
Title: Re: Add integers to an array
Post by: Pixy on May 20, 2019, 06:19:09 am
Thanks for the information guys RAW, 440bx, valdir.marcos.

Code: Pascal  [Select]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   ArraySize: Integer;
  4.   IntAr: array of Integer;
  5. begin
  6.   ArraySize := 0;
  7.  
  8.   ArraySize := ArraySize + 1;
  9.   setLength(IntAr, ArraySize);
  10.   IntAr[0] := 115;
  11.  
  12.   ArraySize := ArraySize + 1;
  13.   setLength(IntAr, ArraySize);
  14.   IntAr[1] := 160;
  15.  
  16.   ShowMessage('IntAr[0]: ' + IntToStr(IntAr[0]) + LineEnding +
  17.               'IntAr[1]: ' + IntToStr(IntAr[1]));
  18. end;

I think that this is going to work. I'll try that.

That's ... wasteful, to be mild. If you know the exact number of items in the array do it like this:

Code: Pascal  [Select]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. const
  3.   ArraySize = 2;
  4. var
  5.   IntAr: array of Integer;
  6. begin
  7.   setLength(IntAr, ArraySize);
  8.   IntAr[0] := 115;
  9.   IntAr[1] := 160;
  10.   ShowMessageFmt('IntAr[0]: %d' + LineEnding + 'IntAr[1]: %d', ,[IntAr[0], IntAr[1]);
  11. end;

Each time you use SetLength() a new block of memory has to be allocated, the existing array copied over and the old memory block disposed. Call SetLength() as few times as you possible can.

The array size depends on how many times you use it. Now I get another violation error. I am using:
Code: Pascal  [Select]
  1. var
  2.     ars: integer;
  3.     IntAr: array of integer;
  4.  
  5. begin
  6.     for ars := 0 to 2 do
  7.     begin
  8.         SetLength(IntAr, ars);
  9.         IntAr[ars] := 115;
  10.     end;
  11. end;
  12.  

If I use SetLength(IntAr, 3); it works but if I use ars instead of 3 I get the violation error. How can I get around that?

EDIT: Nevermind, I used another variable and it worked.
Title: Re: Add integers to an array
Post by: valdir.marcos on May 20, 2019, 08:34:23 am
Code: Pascal  [Select]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   ArraySize: Integer;
  4.   IntAr: array of Integer;
  5. begin
  6.   ArraySize := 0;
  7.  
  8.   ArraySize := ArraySize + 1;
  9.   setLength(IntAr, ArraySize);
  10.   IntAr[0] := 115;
  11.  
  12.   ArraySize := ArraySize + 1;
  13.   setLength(IntAr, ArraySize);
  14.   IntAr[1] := 160;
  15.  
  16.   ShowMessage('IntAr[0]: ' + IntToStr(IntAr[0]) + LineEnding +
  17.               'IntAr[1]: ' + IntToStr(IntAr[1]));
  18. end;
That's ... wasteful, to be mild. If you know the exact number of items in the array do it like this:
You could be more polite and less arrogant.
How could you know if Pixy needs a limited or dynamic quantity of elements by the array on his question?
I am using this:
Code: Pascal  [Select]
  1. var
  2.     IntAr: array of integer;
  3.  
  4. begin
  5.     IntAr[0] := 115;
  6.     IntAr[1] := 160;
  7.    ...
  8. end.
but I get an access violation error. Any idea how I can add individual integers to the array?
I had provided some wiki information about limited and dynamic arrays and then a very simple solution that could address both cases.
I was not trying to be comprehensive, but simply educative. I still don't know how much Pixy knows about Pascal or Arrays.

Quote
Code: Pascal  [Select]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. const
  3.   ArraySize = 2;
  4. var
  5.   IntAr: array of Integer;
  6. begin
  7.   setLength(IntAr, ArraySize);
  8.   IntAr[0] := 115;
  9.   IntAr[1] := 160;
  10.   ShowMessageFmt('IntAr[0]: %d' + LineEnding + 'IntAr[1]: %d', ,[IntAr[0], IntAr[1]);
  11. end;
Each time you use SetLength() a new block of memory has to be allocated, the existing array copied over and the old memory block disposed. Call SetLength() as few times as you possible can.
You are correct, but again I believe Pixy is searching for a basic solution, so far. As times goes by, he will learn better solutions.
Title: Re: [RESOLVED] Add integers to an array
Post by: mangakissa on May 20, 2019, 08:37:00 am
You can't create a setlength of 0. That's freeing the array in the memory.
Code: [Select]
var
    ars: integer;
    IntAr: array of integer;
 
begin
    for ars := 1 to 3 do
    begin
        SetLength(IntAr, ars);
        IntAr[ars - 1] := 115;
    end;
end;
Title: Re: Add integers to an array
Post by: lucamar on May 20, 2019, 08:57:24 am
You could be more polite and less arrogant.

Youre right. It wasn't my intention to sound arrogant but my phrasing was unfortunate. Sorry.
Title: Re: [RESOLVED] Add integers to an array
Post by: PascalDragon on May 20, 2019, 04:08:01 pm
The upcoming FPC 3.2.0 also allows this  :-[
Code: Pascal  [Select]
  1. IntAr := [115, 160];
Title: Re: Add integers to an array
Post by: valdir.marcos on May 20, 2019, 09:09:53 pm
You could be more polite and less arrogant.
Youre right. It wasn't my intention to sound arrogant but my phrasing was unfortunate. Sorry.
You're welcome.
Title: Re: [RESOLVED] Add integers to an array
Post by: Pixy on May 21, 2019, 01:40:28 am
@valdir.marcos, @lucamar, Ideally I would like to use a dynamic array that adds integers, however, I will have to test whether using setlength multiple times within a period of milliseconds works without trouble. I started Pascal/Delphi 1 month ago and I think that I've learnt all the basics. Mostly, my areas are web dev languages and .net.

The upcoming FPC 3.2.0 also allows this  :-[
Code: Pascal  [Select]
  1. IntAr := [115, 160];

Interesting.

You can't create a setlength of 0. That's freeing the array in the memory.
Code: [Select]
var
    ars: integer;
    IntAr: array of integer;
 
begin
    for ars := 1 to 3 do
    begin
        SetLength(IntAr, ars);
        IntAr[ars - 1] := 115;
    end;
end;

That makes sense. I will try that, very useful.
Title: Re: [RESOLVED] Add integers to an array
Post by: valdir.marcos on May 21, 2019, 01:58:15 am
@valdir.marcos, @lucamar, Ideally I would like to use a dynamic array that adds integers, however, I will have to test whether using setlength multiple times within a period of milliseconds works without trouble.

I started Pascal/Delphi 1 month ago and I think that I've learnt all the basics. Mostly, my areas are web dev languages and .net.
Just curious.
Coming from web programming languages and Microsoft .Net, why are you interested in Free Pascal and Lazarus?
Title: Re: [RESOLVED] Add integers to an array
Post by: lucamar on May 21, 2019, 02:02:35 am
@valdir.marcos, @lucamar, Ideally I would like to use a dynamic array that adds integers, however, I will have to test whether using setlength multiple times within a period of milliseconds works without trouble. I started Pascal/Delphi 1 month ago and I think that I've learnt all the basics. Mostly, my areas are web dev languages and .net.

There shouldn't be (much) trouble if the arrays are reasonably short, say up to about a hundred integers. It depends also on how many times is "multiple times".

There are solutions even for high update rates and huge arrays but without knowing more of what you are doing they may be a little overkill for you.
Title: Re: [RESOLVED] Add integers to an array
Post by: Pixy on May 21, 2019, 02:11:40 am
There shouldn't be (much) trouble if the arrays are reasonably short, say up to about a hundred integers. It depends also on how many times is "multiple times".

There are solutions even for high update rates and huge arrays but without knowing more of what you are doing they may be a little overkill for you.

I think that more than 210 indexes wont be needed. So, anywhere between 3 to 210 (each index with integer of up to 6-7 digits) within let's say a second or as fast as it can be done.
Title: Re: [RESOLVED] Add integers to an array
Post by: valdir.marcos on May 21, 2019, 03:08:38 am
There shouldn't be (much) trouble if the arrays are reasonably short, say up to about a hundred integers. It depends also on how many times is "multiple times".
There are solutions even for high update rates and huge arrays but without knowing more of what you are doing they may be a little overkill for you.
I think that more than 210 indexes wont be needed. So, anywhere between 3 to 210 (each index with integer of up to 6-7 digits) within let's say a second or as fast as it can be done.
Less than 1 second here for 300,000 ten-digit elements.

Code: Pascal  [Select]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   TimeLapsed: TTime;
  4.   Number: Integer;
  5.   i, Elements, ArraySize: Integer;
  6.   IntAr: array of Integer;
  7. begin
  8.   TimeLapsed := Time;
  9.   Elements   := 300000;
  10.   Number     := 1234567890;
  11.  
  12.   for i := 1 to Elements do
  13.   begin
  14.     ArraySize := i;
  15.     setLength(IntAr, ArraySize);
  16.     IntAr[ArraySize - 1] := Number + i;
  17.   end;
  18.  
  19.   TimeLapsed := Time - TimeLapsed;
  20.   ShowMessage('Time-lapsed: ' + TimeToStr(TimeLapsed) + LineEnding +
  21.               'IntAr[' + IntToStr(Elements - 1) + '] = ' + IntToStr(IntAr[Elements - 1]) + LineEnding +
  22.               'Array Size: ' + IntToStr(Length(IntAr)));
  23. end;[code]
Title: Re: [RESOLVED] Add integers to an array
Post by: lucamar on May 21, 2019, 04:02:12 am
I think that more than 210 indexes wont be needed. So, anywhere between 3 to 210 (each index with integer of up to 6-7 digits) within let's say a second or as fast as it can be done.

Test it and see how much time it takes using SetLength(Length+1) each time you want to add one item in your target platform. A maximum of 210 item/second doesn't sound as much for current OS/hardware.

Of course, depends on what else the application must do :)
Title: Re: [RESOLVED] Add integers to an array
Post by: howardpc on May 21, 2019, 09:57:05 am
If an upper limit is known in advance, simply SetLength(arry, 210); at the outset.
Keep a count of the number of indexes allocated, and when all indexing is complete, call SetLength(arry, count).
Of course, the difference in speed compared to multiple calls to SetLength() may be negligible. Timing the two alternative implementations is the only way to know if there is any significant speed gain.  It is surprising how often  optimisations which in theory would be expected to make a difference in practice make little difference, or even have a negative effect with certain data. Compilers are getting ever more sophisticated, and low level caching/pipelining etc. over which the high level programmer has little or no control may ultimately prove to be the determinative factor.
Title: Re: [RESOLVED] Add integers to an array
Post by: Pixy on May 21, 2019, 02:42:54 pm
I think that more than 210 indexes wont be needed. So, anywhere between 3 to 210 (each index with integer of up to 6-7 digits) within let's say a second or as fast as it can be done.

Test it and see how much time it takes using SetLength(Length+1) each time you want to add one item in your target platform. A maximum of 210 item/second doesn't sound as much for current OS/hardware.

Of course, depends on what else the application must do :)

It's basically a script for a bot and the array adds coordinates as needed. Despite that I am also looking at the bigger picture by learning and testing out Pascal for the purpose of understanding its capacity, applicability and potential use. I could already make what I wanted to do to work, I am just trying to figure out betterment and optimization to do the same thing by combining your ideas guys. Thanks for your input.

There shouldn't be (much) trouble if the arrays are reasonably short, say up to about a hundred integers. It depends also on how many times is "multiple times".
There are solutions even for high update rates and huge arrays but without knowing more of what you are doing they may be a little overkill for you.
I think that more than 210 indexes wont be needed. So, anywhere between 3 to 210 (each index with integer of up to 6-7 digits) within let's say a second or as fast as it can be done.
Less than 1 second here for 300,000 ten-digit elements.

Code: Pascal  [Select]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. var
  3.   TimeLapsed: TTime;
  4.   Number: Integer;
  5.   i, Elements, ArraySize: Integer;
  6.   IntAr: array of Integer;
  7. begin
  8.   TimeLapsed := Time;
  9.   Elements   := 300000;
  10.   Number     := 1234567890;
  11.  
  12.   for i := 1 to Elements do
  13.   begin
  14.     ArraySize := i;
  15.     setLength(IntAr, ArraySize);
  16.     IntAr[ArraySize - 1] := Number + i;
  17.   end;
  18.  
  19.   TimeLapsed := Time - TimeLapsed;
  20.   ShowMessage('Time-lapsed: ' + TimeToStr(TimeLapsed) + LineEnding +
  21.               'IntAr[' + IntToStr(Elements - 1) + '] = ' + IntToStr(IntAr[Elements - 1]) + LineEnding +
  22.               'Array Size: ' + IntToStr(Length(IntAr)));
  23. end;[code]

Wow. I'll definitely test that.

If an upper limit is known in advance, simply SetLength(arry, 210); at the outset.
Keep a count of the number of indexes allocated, and when all indexing is complete, call SetLength(arry, count).
Of course, the difference in speed compared to multiple calls to SetLength() may be negligible. Timing the two alternative implementations is the only way to know if there is any significant speed gain.  It is surprising how often  optimisations which in theory would be expected to make a difference in practice make little difference, or even have a negative effect with certain data. Compilers are getting ever more sophisticated, and low level caching/pipelining etc. over which the high level programmer has little or no control may ultimately prove to be the determinative factor.

Are you suggesting to use setlength one time with the upper limit (210) and then as integers are added to the array's indexes within the loop, finally return the number of indexes that have been occupied and then reduce the length from 210 to the number of indexes occupied by integers? If so it is not a bad idea. It went by my head, but I didn't give this idea a shot.
Title: Re: Add integers to an array
Post by: Kays on May 21, 2019, 03:07:35 pm
[…] but I get an access violation error. […]
[…] An "array of integer" is just a pointer to an array. […]
Just to explain the error message: Your IntAr (as a “managed” type (https://www.freepascal.org/docs-html/ref/refse20.html)) is initialized as a nil pointer, i. e. it points to the address 0. The “access violation” occurs, because your program accesses a block that isn’t in its purview. If you coincidentally happen to access IntAr[1234567] and that block belongs to your program, you could alter its content without an error.

Only a {$rangeCheck on} will trigger appropriate run-time errors. {$checkPointer on} will still grant access via a nil-pointer (https://en.wikipedia.org/wiki/Segmentation_fault#Null_pointer_dereference) if the indices are within the program’s bounds.