Могу ли я назначать элементы в массиве сразу в Delphi/Pascal?
Я хочу сделать что-то вроде PHP, Python и большинства других языков программирования:
my_array_name = [128, 38459, 438, 23674...]
Итак, я попытался воспроизвести это в Delphi/Pascal, насколько мог:
HSVtoRGB := [0, 0, 0];
(это для функции, которая возвращает массив RGB с заданными значениями HSV.)
Но я получаю ошибки:
[DCC Error] Unit2.pas(44): E2001 Ordinal type required
[DCC Error] Unit2.pas(45): E2010 Incompatible types: 'HSVRealArray' and 'Set'
Любая идея? Это школьная работа, но мой учитель не знал ответа.
Ответы
Ответ 1
Когда дело доходит до динамических массивов, да:
type
TIntArray = array of integer;
procedure TForm1.Button1Click(Sender: TObject);
var
MyArr: TIntArray;
begin
MyArr := TIntArray.Create(10, 20, 30, 40);
end;
Когда речь заходит о статических массивах, вам нужно написать вспомогательную функцию:
type
TIntArray = array[0..2] of integer;
function IntArray(const A, B, C: integer): TIntArray;
begin
result[0] := A;
result[1] := B;
result[2] := C;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
MyArr: TIntArray;
begin
MyArr := IntArray(10, 20, 30);
end;
Это напоминает, как функция Point
создает запись TPoint
. (Записи и массивы - это не одно и то же.)
Ответ 2
Это область, где Delphi превращает что-то, что является простым однострочным присваиванием в большинстве языков, в нечто более сложное.
Один подход должен был бы объявить значение как типизированную константу:
type
HSVRealArray = array[1..3] of real;
const
constHSVVal: HSVRealArray = (0, 0, 0);
var
currentValue: HSVRealArray;
begin
currentValue := constHSVVal;
end;
Другой подход заключается в создании служебных функций, возвращающих нужный тип:
function MakeHSVRealArray(H, S, V: Real): HSVRealArray;
begin
Result[1] := H;
Result[2] := S;
Result[3] := V;
end;
currentValue := MakeHSVRealArray(0,0,0);
Ответ 3
С некоторой дополнительной работой вы можете добиться чистой реализации:
var
x: TRGB;
begin
x := TRGB.Init(0,0,0);
end;
TRGB = record
Red, Green, Blue: real;
class function Init(r,g,b: real): TRGB; static;
end;
class function TRGB.Init(r, g, b: real): TRGB;
begin
Result.Red := r;
Result.Green := g;
Result.Blue := b;
end;
Ответ 4
Для обработки массива, инициализации массива и деклараций констант массива Delphi не упрощает простые вещи.
В некоторых ситуациях, подобных вашим, я инициализирую массив с помощью функции утилиты, принимающей один открытый параметр массива и возвращающий соответствующую статическую строку.
const
MaxArray = 10;
type
TRealStaticArray = array[0..MaxArray] of Real;
function RealArray(const AnArray: array of real):TRealStaticArray;
const DefaultValue=0.0;
var i: integer;
begin
// EDIT: commented out, thanks Serg. for i:= 0 to low(AnArray)-1 do result[i]:=DefaultValue;
for i:= High(AnArray)+1 to MaxArray do
result[i]:=DefaultValue;
for i:= Low(AnArray) to High(AnArray) do
if (i>=0) and (i<=MaxArray) then
result[i]:=AnArray[i];
end;
Используйте его следующим образом:
var MyArray: TRealStaticArray;
...
MyArray := RealArray([10.0, 20.0, 30.0]);
Ответ 5
Delphi-XE7 ввел новый синтаксис для инициализации dynamic array
.
// compile time const declaration of dynamic array
const
my_ConstArray_name: TArray<Integer> = [128, 38459, 438, 23674];
// compile time var declaration of dynamic array
var
my_VarArray_name: TArray<Integer> = [128, 38459, 438, 23674];
Назначение времени выполнения динамических массивов:
var
a : TArray<Integer>;
begin
a := [1,2,3];
К сожалению, этот синтаксис не может использоваться на обычных статических массивах:
Type
TMyArray = array[0..3] of Integer;
const
cMyArray: TMyArray = [0,1,2,3]; // E2010 Incompatible types: 'TMyArray' and 'Set'
cMyArray: TMyArray = (0,1,2,3); // Works, as in all Delphi versions
var
MyArray: TMyArray;
begin
// This fails as well
MyArray := [0,1,2,3]; // E2010 Incompatible types: 'TMyArray' and 'Set'
MyArray := (0,1,2,3); // E2029 ')' expected but ',' found
//-----------^-------
// This works in all Delphi versions !
MyArray := cMyArray;
Ответ 6
Можете ли вы попробовать что-то вроде этого:
TRGB = record
Red : integer;
Green: integer;
Bklue: integer;
end;
var Variable:TRGB;
Variable.Red:=0;
Variable.Green:=0;
Variable.Blue:=0;
Ответ 7
Я знаю, что это старый пост, но я столкнулся с этим, изучая технику автоматического назначения для Delphi. Это сообщение имеет очень хорошее объяснение, а также способ автоматического назначения массива записей:
http://delphi.about.com/od/adptips2006/qt/const_array.htm
К сожалению, инициализация может быть выполнена только с использованием родных или типов записей. Объектам класса нужна вспомогательная функция, как показано выше.
Ответ 8
[0, 0, 0]
- это набор в Delphi. (0, 0, 0)
- постоянная массива в Delphi! Просто используйте:
HSVtoRGB := (0, 0, 0);
(Если HSVtoRGB не является динамическим массивом. Вы объявили его как var HSVtoRGB: array[1..3] of integer;
или что-то подобное?
Ответ 9
Отложив общий вопрос, я хотел бы указать, что конкретный прецедент никогда не будет работать: Delphi не может вернуть в стек содержимое массива неизвестной длины.
Возвращаемый тип функции должен быть известен вызывающим кодом. Это может быть указатель на кучу: он может даже быть объектом, управляемым памятью в стеке: но не разрешено быть undefined числом байтов в стеке, динамически определяемым целевой функцией.
И во многих других языках пример
return (0,0,0) //return pointer to automatic allocation
будет undefined, даже если компилятор позволит вам это сделать.
Общим методом определения, использования и возврата значений const является
int myarray[8] = {128, 38459, 438 ... 23674};
memcpy (myparam, myArray, sizeof (myArray));
... и вы можете сделать это в Delphi