Можно ли назначить элементы в массиве одновременно в Delphi / Pascal?

17

Я хочу сделать что-то вроде 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'

Любая идея? Это школьная работа, но мой учитель не знал ответа.

    
задан Thomas O 27.06.2011 в 15:38
источник
  • См. также: stackoverflow.com/questions/2300912/delphi-array-initialization/... –  Gerry Coll 27.06.2011 в 22:46

9 ответов

19

Когда дело доходит до динамических массивов, да:

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 . (Записи и массивы - это не одно и то же.)

    
ответ дан Andreas Rejbrand 27.06.2011 в 15:40
источник
  • Спасибо за предложение, но это не сработало. Мой тип определен как HSVRealArray = массив [1..3] реального, тогда я пытаюсь это сделать: HSVtoRGB: = HSVRealArray.Create (0, 0, 0), но получая это: [DCC Error] Unit2.pas ( 45): E2018 Требуется запись, объект или тип класса. Есть идеи? –  Thomas O 27.06.2011 в 15:43
  • +1 Для решения статического массива он также может быть параметром открытого массива. –  Andriy M 27.06.2011 в 16:18
  • @David: В зависимости от ситуации избыточные элементы можно просто игнорировать или можно было бы вызвать исключение. Если было меньше элементов, чем требовалось, то, опять же в зависимости от ситуации, вы могли бы просто игнорировать его (оставьте конечные элементы массива неинициализированными) или обработайте отсутствующие элементы в поставляемом списке как некоторые значения по умолчанию. Или, опять же, создайте исключение. –  Andriy M 27.06.2011 в 17:00
  • @Andriy Поскольку вы знаете, сколько есть в массиве с фиксированным размером, просто лучше выполнить проверку во время компиляции. –  David Heffernan 27.06.2011 в 17:07
  • Еще одно преимущество «стандартной» вспомогательной функции (в отличие от вспомогательной функции открытого массива) заключается в том, что она сообщает программисту, в каком порядке должны быть указаны красные, зеленые и синие компоненты. –  Andreas Rejbrand 27.06.2011 в 17:57
Показать остальные комментарии
9

Это область, где 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);
    
ответ дан Dan Bartlett 27.06.2011 в 16:27
источник
  • +1 за то, что синтаксис Delphi слаб в этой области –  David Heffernan 27.06.2011 в 16:54
5

С некоторой дополнительной работой вы можете добиться чистой реализации:

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;
    
ответ дан markus_ja 27.06.2011 в 16:20
источник
  • +1. Вы также можете сделать его нормальной функцией (не функцией класса); то вы можете сделать x.Init. –  Andreas Rejbrand 27.06.2011 в 16:23
  • Если вы объявите его как конструктор Init (...); то у вас есть гибкость либо использовать его как функцию: x: = TRGB.Init (...); или как процедура для инициализации существующего экземпляра: x.Init (...); –  Craig Young 16.04.2014 в 17:28
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]);
    
ответ дан PA. 27.06.2011 в 17:32
источник
  • Это слишком много, если массив представляет собой трехкомпонентный массив RGB ... –  Andreas Rejbrand 27.06.2011 в 17:35
  • low (AnArray) = 0 –  kludg 27.06.2011 в 17:40
  • @serg, вы правы, спасибо. Однако компилятор избавляется от дополнительного цикла. –  PA. 27.06.2011 в 17:44
2

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;
    
ответ дан LU RD 20.09.2014 в 11:00
источник
1

Можете ли вы попробовать что-то вроде этого:

TRGB = record
      Red  : integer;
      Green: integer;
      Bklue: integer;
  end;

var Variable:TRGB;

Variable.Red:=0;
Variable.Green:=0;
Variable.Blue:=0;
    
ответ дан TreantBG 27.06.2011 в 15:42
источник
  • Это тот код, который OP хочет избежать. OP хочет чего-то более кратким. –  David Heffernan 27.06.2011 в 16:11
1

Я знаю, что это старый пост, но я столкнулся с этим, изучая технику автоматического назначения для Delphi. Это сообщение имеет очень хорошее объяснение, а также способ автоматического назначения массива записей:

Ссылка

К сожалению, инициализация может быть выполнена только с использованием родных или типов записей. Объектам класса нужна вспомогательная функция, как показано выше.

    
ответ дан James Jensen 06.06.2013 в 17:08
источник
  • Большое спасибо за эту информацию. Старый вопрос, новый искатель ответов. ;-) Но серьезно мы должны быть смущены тем, что вы не можете просто назначить предметы сразу в 2013 году. –  alcalde 14.08.2013 в 23:29
0

[0, 0, 0] - это набор в Delphi. (0, 0, 0) - постоянная массива в Delphi! Просто используйте:

HSVtoRGB := (0, 0, 0);

(Если HSVtoRGB не является динамическим массивом. Вы объявили его как var HSVtoRGB: array[1..3] of integer; или что-то подобное?

    
ответ дан Wim ten Brink 28.06.2011 в 11:09
источник
  • Не работает, Delphi XE2. "[DCC Error] ...: E2029 ')' ожидается, но ',' found ' –  user2091150 15.08.2013 в 12:46
0

Отложив общий вопрос, я хотел бы указать, что конкретный прецедент никогда не будет работать: Delphi не может вернуть в стек содержимое массива неизвестной длины.

Возвращаемый тип функции должен быть известен вызывающим кодом. Это может быть указатель на кучу: он может даже быть объектом, управляемым памятью в стеке: но не разрешено быть неопределенным количеством байтов в стеке, динамически определяемым целевой функцией.

И во многих других языках пример

return (0,0,0)  //return pointer to automatic allocation

будет неопределенным, даже если компилятор позволит вам это сделать.

Общим методом определения, использования и возврата значений const является

int myarray[8] = {128, 38459, 438 ... 23674};
memcpy (myparam, myArray, sizeof (myArray)); 

... и вы можете сделать это в Delphi

    
ответ дан david 11.09.2015 в 10:12
источник