Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Delphi Новый топик    Ответить
 Функция для замены местами переменных любого типа  [new]
delphiprog
Guest
Можно ли на Delphi сделать универсальную функцию для того, чтобы поменять местами 2 переменные любого типа данных (за исключением объектов, возможно)? Такой код не хочет работать:

procedure swap(a, b: pointer);
var c: pointer;
begin
    c^ := a^;
    a^ := b^;
    b^ := c^;
end;
19 май 17, 07:51    [20494659]     Ответить | Цитировать Сообщить модератору
 Re: Функция для замены местами переменных любого типа  [new]
DimaBr
Member

Откуда:
Сообщений: 10154
procedure swap(a, b: Variant);
19 май 17, 08:03    [20494675]     Ответить | Цитировать Сообщить модератору
 Re: Функция для замены местами переменных любого типа  [new]
Dmitry Arefiev
Member

Откуда:
Сообщений: 9486
type
  Swap = class
    class procedure It<T>(var a, b: T); static;
  end;

class procedure Swap.It<T>(var a, b: T);
var
  c: T;
begin
  c := a;
  a := b;
  b := c;
end;

var
  e1, e2: Double;
...
  Swap.It(e1, e2);
19 май 17, 08:34    [20494723]     Ответить | Цитировать Сообщить модератору
 Re: Функция для замены местами переменных любого типа  [new]
Maxim Rusov
Member

Откуда: Москва-Питер
Сообщений: 2387
Чет не работает.

Только если так:

Swap.It<Double>(A1, A2);
19 май 17, 10:42    [20495273]     Ответить | Цитировать Сообщить модератору
 Re: Функция для замены местами переменных любого типа  [new]
Dimonka
Member

Откуда:
Сообщений: 931
Dmitry Arefiev
...
  Swap.It(e1, e2);

А разве не надо тип указывать?
Swap<Double>.It(e1, e2);
19 май 17, 10:44    [20495288]     Ответить | Цитировать Сообщить модератору
 Re: Функция для замены местами переменных любого типа  [new]
Квейд
Member

Откуда: Kyiv, Ukraine
Сообщений: 4960
DimaBr
procedure swap(a, b: Variant);
этот вызов не свопнет две внешние переменные
19 май 17, 10:49    [20495324]     Ответить | Цитировать Сообщить модератору
 Re: Функция для замены местами переменных любого типа  [new]
Dmitry Arefiev
Member

Откуда:
Сообщений: 9486
Dimonka
А разве не надо тип указывать?
Swap<Double>.It(e1, e2);

Зависит от версии RAD Studio ...
19 май 17, 12:25    [20495840]     Ответить | Цитировать Сообщить модератору
 Re: Функция для замены местами переменных любого типа  [new]
DimaBr
Member

Откуда:
Сообщений: 10154
procedure swap(var a, b: Variant);
19 май 17, 12:54    [20496045]     Ответить | Цитировать Сообщить модератору
 Re: Функция для замены местами переменных любого типа  [new]
Квейд
Member

Откуда: Kyiv, Ukraine
Сообщений: 4960
DimaBr
procedure swap(var a, b: Variant);
Ага, только не забываем, что types of actual and formal var parameters must be identical, то есть не получится свопнуть невариантные переменные.
19 май 17, 13:02    [20496112]     Ответить | Цитировать Сообщить модератору
 Re: Функция для замены местами переменных любого типа  [new]
SimplTsar
Member

Откуда:
Сообщений: 35
procedure EXCHANGE(var v1,v2; size: LongWord); assembler; register;
asm
{     ->EAX     Pointer to v1    }
{       EDX     Pointer to v2    }
{       ECX     size             }

        PUSH    ESI
        PUSH    EDI
        PUSH    EBX

        MOV     ESI,EAX         { ESI - адрес v1 }
        MOV     EDI,EDX         { EDI - адрес v2 }
        MOV     EDX,ECX         { EDX - количество обмениваемых данных }

        SAR     ECX,2           { пересчет в двойный слова size DIV 4  }
        JZ      @@smal          { размер < 4 }

        CLD                     { автоинкремент }
        MOV     EBX,-4          { для адресации }
@@loop1:
        MOV     EAX,DWORD PTR [EDI]      { 4al:=v1[j] }
        MOVSD                            { v2[j]:=v1[j], j:=j+4, i:=i+4 }
        MOV     DWORD PTR [ESI][EBX],EAX { v1[i-4]:=4al }
        LOOP    @@loop1

@@smal:
        MOV     ECX,EDX         { опредлеление оставшихся }
        AND     ECX,03H         { байт }
        JZ      @@exit          { нечего обменивать }
        MOV     EBX,-1
@@loop2:
        MOV     AL,BYTE PTR [EDI]       { al:=v1[j] }
        MOVSB                           { v2[j]:=v1[j], j:=j+1, i:=i+1 }
        MOV     BYTE PTR [ESI][EBX],AL  { v1[i-1]:=al }
        LOOP    @@loop2
@@exit:
        POP     EBX
        POP     EDI
        POP     ESI
end; { EXCHANGE }


PS Кнопка src почему-то не работает
19 май 17, 13:21    [20496254]     Ответить | Цитировать Сообщить модератору
 Re: Функция для замены местами переменных любого типа  [new]
DimaBr
Member

Откуда:
Сообщений: 10154
procedure Swap(var A,B; AType: byte);
var Z: Variant;
begin
  case AType of
    vtInteger : begin
      Z := integer(A);
      integer(A) := integer(B);
      integer(B) := Z;
    end;
    vtString : begin
      Z := string(A);
      string(A) := string(B);
      string(B) := Z;
    end;

  end;
end;


procedure TForm1.FormClick(Sender: TObject);
var A,B: integer;
    C,D: string;
begin
  A := 1; B := 2;
  C := 'A'; D := 'B';
  Swap(A,B,vtInteger);
  Swap(C,D,vtString);
  ShowMessage(Format('%d %d %s %s',[A,B,C,D]));
end;
19 май 17, 13:52    [20496400]     Ответить | Цитировать Сообщить модератору
 Re: Функция для замены местами переменных любого типа  [new]
_Vasilisk_
Member

Откуда: Украина, Харьков
Сообщений: 9602
Dmitry Arefiev
Зависит от версии RAD Studio ...
Круто! А когда сделали автоматический вывод типа?
19 май 17, 14:19    [20496537]     Ответить | Цитировать Сообщить модератору
 Re: Функция для замены местами переменных любого типа  [new]
Гаджимурадов Рустам
Member

Откуда:
Сообщений: 56820
ОФФ
SimplTsar
PS Кнопка src почему-то не работает
Какая-то ошибка выдаётся?
19 май 17, 14:25    [20496557]     Ответить | Цитировать Сообщить модератору
 Re: Функция для замены местами переменных любого типа  [new]
errorsoft
Member

Откуда: Санкт-Петербург
Сообщений: 159
Dmitry Arefiev
Dimonka
А разве не надо тип указывать?
Swap<Double>.It(e1, e2);

Зависит от версии RAD Studio ...


А вот здесь поподробнее...)
19 май 17, 14:26    [20496564]     Ответить | Цитировать Сообщить модератору
 Re: Функция для замены местами переменных любого типа  [new]
SimplTsar
Member

Откуда:
Сообщений: 35
Гаджимурадов Рустам
ОФФ
SimplTsar
PS Кнопка src почему-то не работает
Какая-то ошибка выдаётся?


Ошибка не выдаётся. Теги не добавляются. Проверял на "Konqueror - 4.14.8" и "Firefox - 50.1.0"
19 май 17, 14:35    [20496599]     Ответить | Цитировать Сообщить модератору
 Re: Функция для замены местами переменных любого типа  [new]
DimaBr
Member

Откуда:
Сообщений: 10154
Ошибка не выдаётся. Теги не добавляются. Проверял на "Konqueror - 4.14.8" и "Firefox - 50.1.0"

А что религия не позволяет написать тег вручную ? Или не барское это дело :
19 май 17, 14:43    [20496640]     Ответить | Цитировать Сообщить модератору
 Re: Функция для замены местами переменных любого типа  [new]
SimplTsar
Member

Откуда:
Сообщений: 35
DimaBr
А что религия не позволяет написать тег вручную ? Или не барское это дело :

Если знать какой - то никаких проблем. Но, к сожалению, мой "хрустальный шар" в ремонте :)
19 май 17, 15:10    [20496763]     Ответить | Цитировать Сообщить модератору
 Re: Функция для замены местами переменных любого типа  [new]
Гаджимурадов Рустам
Member

Откуда:
Сообщений: 56820
SimplTsar> Ошибка не выдаётся. Теги не добавляются.
SimplTsar> Проверял на "Konqueror - 4.14.8" и "Firefox - 50.1.0"

Странно. Про первый не знаю, а в 50-м FF точно работало.
Сообщите, пожалуйста, все подробности (включая ОС) в
тех.разделе: http://sql.ru/forum/sqlru

Posted via ActualForum NNTP Server 1.5

19 май 17, 16:22    [20496999]     Ответить | Цитировать Сообщить модератору
 Re: Функция для замены местами переменных любого типа  [new]
Kazantsev Alexey
Member

Откуда:
Сообщений: 2273
_Vasilisk_
Круто! А когда сделали автоматический вывод типа?

Появилось в XE8.
errorsoft
А вот здесь поподробнее...)

http://docwiki.embarcadero.com/RADStudio/XE8/en/Declaring_Generics#Parameterized_Methods
19 май 17, 17:04    [20497137]     Ответить | Цитировать Сообщить модератору
 Re: Функция для замены местами переменных любого типа  [new]
Guest2013
Member

Откуда:
Сообщений: 508
Dmitry Arefiev
+
type
  Swap = class
    class procedure It<T>(var a, b: T); static;
  end;

class procedure Swap.It<T>(var a, b: T);
var
  c: T;
begin
  c := a;
  a := b;
  b := c;
end;

var
  e1, e2: Double;
...
  Swap.It(e1, e2);



а если в качестве парметра Record, процедурный тип с параметрами?
19 май 17, 19:28    [20497474]     Ответить | Цитировать Сообщить модератору
 Re: Функция для замены местами переменных любого типа  [new]
Dimonka
Member

Откуда:
Сообщений: 931
Один из вариантов:
procedure Swap(var A, B; Length: integer);
var
  Temp: TBytes;
begin
  SetLength(Temp, Length);
  Move(A, Temp[0], Length);
  Move(B, A, Length);
  Move(Temp[0], B, Length);
end;

  I := 1;
  K := 2;
  Swap(I, K, SizeOf(I));

Правда без типизации..
19 май 17, 19:41    [20497501]     Ответить | Цитировать Сообщить модератору
 Re: Функция для замены местами переменных любого типа  [new]
Dmitry Arefiev
Member

Откуда:
Сообщений: 9486
Dimonka
Один из вариантов

* Работает пока типы не требуют магию компилятора
* SizeOf однажды заставит ошибиться
* 3 * Move = тормоза
А казалось бы ...
19 май 17, 20:37    [20497633]     Ответить | Цитировать Сообщить модератору
 Re: Функция для замены местами переменных любого типа  [new]
Bred eFeM
Member

Откуда:
Сообщений: 501
* SetLength(Temp, Length); = Тормоза )

Dmitry Arefiev
* Работает пока типы не требуют магию компилятора
например ?
19 май 17, 21:15    [20497698]     Ответить | Цитировать Сообщить модератору
Все форумы / Delphi Ответить