Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Преобразовать множество в строку  (Прочитано 9308 раз)
0 Пользователей и 1 Гость смотрят эту тему.
SCRIBE
Гость
« : 20-08-2015 15:00 » 

Есть тип:
Код: (Delphi)
type
TMyType = set of (set1, set2, set3, set4, set5);

Например в процедуре:
Код: (Delphi)
var
  F: TMyType;
Begin
  F:= [set1, set5];

Хочу лаконично узнать что там в F в виде строки.
Есть такое как IN (напр. if set1 in F then....)
Но если их десятки? Не писать же громадину с такой вот проверкой?
Пошурстел, нашел SetToString из TypInfo, но прочитав далее вроде с такими сетами не работает, если да то буду благодарен за помощь и пример=).

Задача на конвертацию.
« Последнее редактирование: 21-08-2015 06:30 от ..::SCRIBE::.. » Записан
SCRIBE
Гость
« Ответ #1 : 21-08-2015 05:50 » 

такое:

Код: (Delphi)
if TMyType(0) in F then

тоже не работает.
« Последнее редактирование: 21-08-2015 06:36 от ..::SCRIBE::.. » Записан
SCRIBE
Гость
« Ответ #2 : 21-08-2015 06:28 » 

Нашел вот рабочий пример, честно сказать просто перечислить наверно получится меньше писанины, но зато штука универсальная=)

Код: (Delphi)
function GetOrdValue(Info: PTypeInfo; const SetParam): Integer;
begin
  Result := 0;

  case GetTypeData(Info)^.OrdType of
    otSByte, otUByte:
      Result := Byte(SetParam);
    otSWord, otUWord:
      Result := Word(SetParam);
    otSLong, otULong:
      Result := Integer(SetParam);
  end;
end;

procedure SetOrdValue(Info: PTypeInfo; var SetParam; Value: Integer);
begin
  case GetTypeData(Info)^.OrdType of
    otSByte, otUByte:
      Byte(SetParam) := Value;
    otSWord, otUWord:
      Word(SetParam) := Value;
    otSLong, otULong:
      Integer(SetParam) := Value;
  end;
end;

function SetToString(Info: PTypeInfo; const SetParam; Brackets: Boolean): AnsiString;
var
  S: TIntegerSet;
  TypeInfo: PTypeInfo;
  I: Integer;
begin
  Result := '';

  Integer(S) := GetOrdValue(Info, SetParam);
  TypeInfo := GetTypeData(Info)^.CompType^;
  for I := 0 to SizeOf(Integer) * 8 - 1 do
    if I in S then
    begin
      if Result <> '' then
        Result := Result + ',';
      Result := Result + GetEnumName(TypeInfo, I);
    end;
  if Brackets then
    Result := '[' + Result + ']';
end;

procedure StringToSet(Info: PTypeInfo; var SetParam; const Value: AnsiString);
var
  P: PAnsiChar;
  EnumInfo: PTypeInfo;
  EnumName: AnsiString;
  EnumValue, SetValue: Longint;

  function NextWord(var P: PAnsiChar): AnsiString;
  var
    I: Integer;
  begin
    I := 0;
    // scan til whitespace
    while not (P[I] in [',', ' ', #0,']']) do
      Inc(I);
    SetString(Result, P, I);
    // skip whitespace
    while P[I] in [',', ' ',']'] do
      Inc(I);
    Inc(P, I);
  end;

begin
  SetOrdValue(Info, SetParam, 0);
  if Value = '' then
    Exit;

  SetValue := 0;
  P := PAnsiChar(Value);
  // skip leading bracket and whitespace
  while P^ in ['[',' '] do
    Inc(P);
  EnumInfo := GetTypeData(Info)^.CompType^;
  EnumName := NextWord(P);
  while EnumName <> '' do
  begin
    EnumValue := GetEnumValue(EnumInfo, EnumName);
    if EnumValue < 0 then
    begin
      SetOrdValue(Info, SetParam, 0);
      Exit;
    end;
    Include(TIntegerSet(SetValue), EnumValue);
    EnumName := NextWord(P);
  end;
  SetOrdValue(Info, SetParam, SetValue);
end;

Использование:

Код: (Delphi)
type
  TMySet = set of (set1, set2 , set3);

....

var
  MSet: TMySet;
  outer: string;
begin
  MSet:= [set1, set3];
  outer:= SetToString(TypeInfo(TMySet), MSet, True);
  ShowMessage(Format('%s ($%x)', [outer, Byte(MSet)]));

Ссыль где нашел:
http://tondrej.blogspot.com/2007/10/settostring-stringtoset.html
« Последнее редактирование: 21-08-2015 06:33 от ..::SCRIBE::.. » Записан
x77
Модератор

ro
Offline Offline
Пол: Мужской
меняю стакан шмали на обратный билет с Марса.


« Ответ #3 : 21-08-2015 09:59 » new

а если так:

Код: (Delphi)
type
  TMyType = (set1, set2, set3, set4, set5);
  TMyTypeSet = set of TMyType;

var
  Form1: TForm1;

implementation

uses
  TypInfo;

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);

var
  F: TMyTypeSet;
  i: TMyType;
begin
   F:= [set1, set5];
   for i := Low (TMyType) to High (TMyType) do begin
     if TMyType (i) in F then
       Memo1.Lines.Add(GetEnumName(TypeInfo(TMyType),Ord (i)));
   end;
end;
 

Added after 6 minutes:
c TypeInfo нюанс заключается в том, что она "не видит" типы, объявленные в имплементэйшн, их надо засовывать в интерфейсную секцию модуля.
« Последнее редактирование: 21-08-2015 10:05 от x77 » Записан

SCRIBE
Гость
« Ответ #4 : 21-08-2015 13:10 » 

Моя проблема как я вижу в объявлении типа.
Ваш пример работает, жаль я все уже под массивы переделал Улыбаюсь
Спасибо большое за помощь, хорошая и четкая информация, думаю кому-то еще точно пригодится.
Записан
x77
Модератор

ro
Offline Offline
Пол: Мужской
меняю стакан шмали на обратный билет с Марса.


« Ответ #5 : 21-08-2015 13:52 » 

Аминь Улыбаюсь
Записан

Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines