I have 2 2-dimensional arrays and a function.
I would like that function to take the array as an argument.
I tried code like this:
var array1:array[1..10,1..10] of integer;
array2:array[1..20,1..10] of integer;
function name(var my_array:array of array of integer, n:integer);
function name(var my_array:array[1..n,1..10] of integer;const n:integer);
But I got errors while trying to compile the code. Any tips?
If you would like me to paste error codes for each version please leave a comment with a request.
For
function name(var my_array:array of array of integer, n:integer);
The error code is: "Incompatible type for arg no. : Got "Array[0..10] of Array[0..10] of SmallInt", expected "Open array od SmallInt" every time I call the function.
You need to declare your own type, and then use that type as the parameter to your function. Instead of passing the array dimensions, use the Low and High functions from the System unit; they will work with both static (pre-declared) and dynamic arrays, and avoid hard-coding array sizes and iterators.
You want to avoid hard-coding integer indexes, becaue static arrays in Pascal don't have to start with index 0; the following is a perfectly legal Pascal array declaration, where the array bounds are from index -3 to 3:
var
Arr: array[-3..3] of Integer;
Here's an example using a dynamic array (array of array of Integer) that loops through the two dimensional array and sums the values; it initializes a 5 x 5 array, populates it with data, and then calls the SumTwoDimIntArray function to sum the values.
program Project2;
{$APPTYPE CONSOLE}
uses
SysUtils;
type
TTwoDimIntArray = array of array of Integer;
function SumTwoDimIntArray(Arr: TTwoDimIntArray): Integer;
var
i, j: Integer;
begin
Result := 0;
for i := Low(Arr) to High(Arr) do
for j := Low(Arr[i]) to High(Arr[i]) do
Result := Result + Arr[i][j];
end;
var
MyArr: TTwoDimIntArray;
i, j: Integer;
begin
SetLength(MyArr, 5);
for i := Low(MyArr) to High(MyArr) do
begin
SetLength(MyArr[i], 5);
for j := Low(MyArr[i]) to High(MyArr[i]) do
MyArr[i][j] := j + 1;
end;
WriteLn(Format('Sum is %d', [SumTwoDimIntArray(MyArr)]));
ReadLn;
end.
You shuld use a new type in these situations . like the following:
Type
vector = array [1..20,1..20] of integer;
var array1:vector;
array2:vector;
function name(var my_array:vector, n:integer);
function name(var my_array:vector;const n:integer);
Related
I use this function in Delphi 10.3.3:
function StrTrimCharsLeft(const S: string; const Chars: array of Char): string;
var
I, L: SizeInt;
begin
I := 1;
L := Length(S);
while (I <= L) and ArrayContainsChar(Chars, S[I]) do
Inc(I);
Result := Copy(S, I, L - I + 1);
end;
When I use the function in this way I get an error:
[dcc32 Error]: E2250 There is no overloaded version of 'StrTrimCharsLeft' that can be called with these arguments
const
BomChars = ['ï', '»', '¿'];
...
s := JclStrings.StrTrimCharsLeft(s, BomChars);
But when I use it in this way, all works well without an error:
s := JclStrings.StrTrimCharsLeft(s, ['ï', '»', '¿']);
So how can I define and use an array of Char as a constant?
When you write
const
BomChars = ['ï', '»', '¿'];
you have declared a set named BomChars -- not an array!
If you instead declare BomChars as a static array,
const
BomChars: array[0..2] of Char = ('ï', '»', '¿');
it will work. (See Declared Constants § Array Constants.)
(StrTrimCharsLeft(s, ['ï', '»', '¿']); works because here the brackets are part of the open array syntax. Specifically, the brackets are part of an "open array constructor".)
I am trying to make an array of unconstrained mutable type elements; but, as the element is unconstrained, I get this error: "unconstrained element type in array declaration".
Here is my square type declaration :
type C_square(size : bRange) is tagged record
private
type C_square(size : bRange) is tagged record
bConstaint : uint8 := size;
coord : T_coord;
color : e_color := unknown;
end record;
And here comes the error:
type C_board(size : bRange) is tagged limited private;
type square_matrix is array (uint8 range <>, uint8 range <>) of C_square; -- here is the problem C_square is unconstrained
private
type C_board(size : bRange := MIN_SIZE) is tagged limited record
bSize : uint8 := size;
square_m : square_matrix(1..size, 1..size);
end record;
Is there any solution that allow me to have an array of unconstrained mutable elements?
You can't have an array of unconstrained elements.
Some alternatives:
Use an indefinite vector. (Good!)
Create an array of access to your indefinite type. (Bad!)
I would like to know if it is possible to pass a declared type (in this case a record) to my function. I would not even ask if it was not for the SizeOf() function, because it can take a type as a parameter.
I'm translating code from C and I would like to keep it as close to the original as possible.
The C program declares PushArray and PushStruct as macros. Since Delphi does not have macro support, I'm trying to turn them into functions.
I've googled this a bit and it seems that I could possible use generic types.
Like function PushStruct<T>(Arena : Pmemory_arena; dtype : <T>) but you can only use this in an OOP type application.
function PushSize_(Arena : Pmemory_arena; Size : memory_index) : pointer;
begin
Assert((Arena^.Used + Size) <= Arena^.Size);
Result := Arena^.Base + Arena^.Used;
Arena^.Used := Arena^.Used + Size;
end;
function PushStruct(Arena : Pmemory_arena; dtype : ?) : pointer;
begin
result := PushSize_(Arena, sizeof(dtype));
end;
function PushArray(Arena : Pmemory_arena; Count: uint32; dtype : ?) : pointer;
begin
result := PushSize_(Arena, (Count)*sizeof(dtype))
end;
Here is the original C code:
#define PushStruct(Arena, type) (type *)PushSize_(Arena, sizeof(type))
#define PushArray(Arena, Count, type) (type *)PushSize_(Arena, (Count)*sizeof(type))
void *
PushSize_(memory_arena *Arena, memory_index Size)
{
Assert((Arena->Used + Size) <= Arena->Size);
void *Result = Arena->Base + Arena->Used;
Arena->Used += Size;
return(Result);
}
The C code isn't passing a type to the function. The pre-processor is expanding the macro and computing the size. You can see that from the prototype of the function:
void *PushSize_(memory_arena *Arena, memory_index Size)
Since you don't have macros in Delphi, you cannot arrange a direct translation. Personally, if it were me I would not attempt to match the C code exactly. I'd pass the size and leave it to the caller to use SizeOf. I don't think that's a terrible burden. It still leaves you with something very close to a literal translation – all you are missing is the convenience macros.
If you wanted to use generics, you could do so, but it would require you to use a static method. For instance:
type
TMyClass = class
class function PushSize(Arena: Pmemory_arena; Size: memory_index): Pointer; static;
class function PushStruct<T>(Arena: Pmemory_arena): Pointer; static;
end;
....
class function TMyClass.PushSize(Arena: Pmemory_arena; Size: memory_index): Pointer;
begin
Result := ....;
end;
class function TMyClass.PushStruct<T>(Arena: Pmemory_arena): Pointer;
begin
Result := PushSize(Arena, SizeOf(T));
end;
If you want to return a typed pointer that would look like this:
type
TMyClass<T> = class
type P = ^ T;
class function PushSize(Arena: Pmemory_arena; Size: memory_index): Pointer; static;
class function PushStruct(Arena: Pmemory_arena): P; static;
end;
....
class function TMyClass<T>.PushSize(Arena: Pmemory_arena; Size: memory_index): Pointer;
begin
Result := ....;
end;
class function TMyClass<T>.PushStruct(Arena: Pmemory_arena): P;
begin
Result := PushSize(Arena, SizeOf(T));
end;
Obviously you'd know what name to use instead of TMyClass!
I'm not convinced that generics are a good fit here because I guess you are wanting as literal a translation as possible. I would not choose to use generics in this scenario.
You could "expand the macros" by simply declaring your own Push* funtions for each record type as needed:
type
// just guessing here...
PMemoryArena = ^TMemoryArena;
TMemoryArena = record
Base: Pointer;
Used: Cardinal;
Size: Cardinal;
end;
TMemoryIndex = Cardinal;
// 1st example record type
PMyRecord1 = ^TMyRecord1;
TMyRecord1 = record
I1: Integer;
I2: Integer;
end;
// 2nd example record type
PMyRecord2 = ^TMyRecord2;
TMyRecord2 = record
D1: Double;
D2: Double;
end;
function PushSize_(Arena: PMemoryArena; Size: TMemoryIndex): Pointer; inline;
begin
Assert(Arena^.Used + Size <= Arena^.Size);
Result := Pointer(NativeUInt(Arena^.Base) + Arena^.Used);
Inc(Arena^.Used, Size);
end;
function PushMyRecord1(Arena: PMemoryArena): PMyRecord1;
begin
Result := PMyRecord1(PushSize_(Arena, SizeOf(TMyRecord1)));
end;
function PushMyRecord2(Arena: PMemoryArena): PMyRecord2;
begin
Result := PMyRecord2(PushSize_(Arena, SizeOf(TMyRecord2)));
end;
It does seem kind of unnecessary.
why not, for example
function PushStruct(Arena : Pmemory_arena) : pointer;
begin
result := PushSize_(Arena, sizeof( Arena ));
end;
I would like to have an array / slice in Go with a variadic number of elements (not known at compile time) and be able to dinamically add new elements of different types, for instance:
data[0] := "string"
data[1] // slice
data[1][0] := "another string"
data[1][1] := 42 // int
Is this possible somehow?
It's a bit ugly but possible using empty interfaces, interface{}:
package main
import "fmt"
func main() {
variadic := []interface{}{}
variadic = append(variadic, "foo")
variadic = append(variadic, []interface{}{"bar", 42})
//this will print "foo"
fmt.Println(variadic[0])
//note that you have to cast variadic[1] to an array before accessing it
fmt.Println(variadic[1].([]interface{})[0])
}
If you allow the assumption that each element must be an array of anything with varying length, it's a bit less ugly:
package main
import "fmt"
func main() {
variadic := [][]interface{}{}
variadic = append(variadic, []interface{}{"foo"})
variadic = append(variadic, []interface{}{"bar", 42})
fmt.Println(variadic[0])
fmt.Println(variadic[1][0])
fmt.Println(variadic[1][1])
}
I am statically importing a dynamic library (DLL) within Delphi and attempting to access its functions.
Here is the specific C function deceleration that I am trying to access:
int flann_radius_search_double (flann_index_t index_ptr, /* the index */
double* query, /* query point */
int* indices, /* array for storing the indices found (will be modified) */
double* dists, /* similar, but for storing distances */
int max_nn, /* size of arrays indices and dists */
float radius, /* search radius (squared radius for euclidian metric) */
struct FLANNParameters* flann_params);
Here is my deceleration in Delphi:
function flann_radius_search_double(index_ptr: flann_index_t;
var query: double; var indices: longint; var dists: double;
max_nn: longint; radius: single; var flann_params: FLANNParameters): longint;
cdecl; external External_library Name 'flann_radius_search_double';
And I accessed the function like this:
type
TDoubleArray = array[0..1000] of double;
PDoubleArray = ^TDoubleArray;
TIntArray = array[0..1000] of Integer;
PIntArray = ^TIntArray;
...
... <other unrelated code>
var
Indicies:TIntArray;
PIndicies:PIntArray;
Dists:TDoubleArray;
PDists:PDoubleArray;
...
begin
...
PIndicies:=#Indicies;
PDists :=#Dists;
radius_s:=flann_radius_search_double(idx ,&PMyArray^[0,0],Pindicies^[0],&PDists^[0],1000,10,&DEFAULT_FLANN_PARAMETERS);
It is not working, and looks way off :*(
I would really appreciate some assistance!
Edit: I fixed the double/single mistake, but when I attempt to use #Indicies[0] instead of Indicies[0] I get an error:
Error: Call by var for arg no. 3 has to match exactly: Got "Pointer"
expected "LongInt"
Disclaimer: what is written below refers to the original version of the question before it was completely changed. In the original version the floating point parameters were all float. I would urge Mike to post the real code using copy/paste in order to avoid wasting people's time.
C float is equivalent to Delphi Single, the 4 byte floating point type. That's the main problem you have.
I personally would declare the arrays as PSingle or PInteger in the import declaration, rather than using var parameters. When passing single values by reference then var parameters is appropriate.
When calling the function I wouldn't use fixed dimensioned arrays. I would use dynamic arrays and SetLength. Pass the array then with PSingle(MyArray), or #MyArray[0], whichever you prefer.
I would prefer Integer to Longint since I believe that Integer most closely matches C int.
Your arrays are 1001 elements in size, you only need them to be 1000.
The struct is best passed by var as you have it in the import declaration, but not as you have it in the call. Since the code in your question doesn't quite match up I don't want to say anything more.
function flann_radius_search_double(
index_ptr: flann_index_t;
var query: Single;
indices: PInteger;
dists: PSingle;
max_nn: Integer;
radius: Single;
var flann_params: FLANNParameters
): Integer; cdecl; external External_library Name 'flann_radius_search_double';
...
var
indices: array of Integer;
dists: array of Single;
...
SetLength(indices, 1000);
SetLength(dists, 1000);
radius_s := flann_radius_search_double(
idx,
MyArray[0,0],
#indicies[0],
#dists[0],
1000,
10.0,
DEFAULT_FLANN_PARAMETERS
);
In Delphi, float maps to Single, not Double. So it becomes:
function flann_radius_search_double(index_ptr: flann_index_t;
var query: Single;
indices: PInteger; // array, so NOT a var parameter
dists: PSingle; // array, so NOT a var parameter
max_nn: Integer;
radius: Single;
var flann_params: FLANNParameters): Integer;
cdecl; etc...
You call it like:
const
CArraySize = 1000;
...
var
Indices: array[0..CArraySize - 1] of Integer;
Dists: array[0..CArraySize - 1] of Single;
begin
...
x := flann_radius_search_double(idx, yourQuery,
#Indices[0], #Dists[0], Length(Dists), yourRadius, yourFlannParams);