Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Case of для строк


Страницы:   1 2 3

ford ©   (2010-03-31 17:24:00) 

Здравствуйте!
в программу передается параметр от которого зависит какая из процедур должна быть выполнена. Значений параметра около десятка.

я сделал следующим образом

if ParamStr(1)='create' then createnewfile(paramstr(2))
 else if ParamStr(1)='send' then sendfile(paramstr(2))
       else ....


подскажите, можно ли реализовать это как Case of
т.е. примерно так:


Case ParamStr(1) of
'create' : createnewfile(paramstr(2));
'send'   : sendfile(paramstr(2));
...
else
...
end;


понятно что Case не работает для строк
но все же :)


  (2010-04-02 17:07:00) [1]

Удалено модератором


Игорь Шевченко   (2010-04-02 16:45:00) [2]

oxffff ©   (02.04.10 16:19) [43]

так вопрос был про строки...
вот в oracle есть case по строкам ;)


oxffff   (2010-04-02 16:19:00) [3]


> Игорь Шевченко ©   (02.04.10 15:42) [42]
> oxffff ©   (02.04.10 15:35) [40]
>
> if SameText(foo,'FOO') then
>  ShowMessage('FOO')
> else if SameText(foo,'BAR') then
>  ShowMessage('BAR')
> else
>  ShowMessage('Not FOO nor BAR')
>
> Чутка короче получилось ;)


Только с подтипами у Вас дополнительные раздумья будут.
Например Mycase можно написать, чтобы обрабатывал конструкции вида

var a:Tobject;

a:=Tform.create;

case a.classtype of
Tobject: ...
TComponent: ...
TCustomForm: ..
TForm:  ...      <-выполняется это.
end;

А с if выстраивать порядок сравнения придется программисту. ;)


Игорь Шевченко   (2010-04-02 15:42:00) [4]

oxffff ©   (02.04.10 15:35) [40]

if SameText(foo,'FOO') then
 ShowMessage('FOO')
else if SameText(foo,'BAR') then
 ShowMessage('BAR')
else
 ShowMessage('Not FOO nor BAR')


Чутка короче получилось ;)


oxffff   (2010-04-02 15:38:00) [5]

Повторюсь.
Если у delphi компилятор  чуть лучше. то можно было написать так.

with Stuff do
MyCase('2',
  [
  ['4',procedure
            begin
            showmessage('Option 1');
            end],
  ['2',procedure
            begin
            showmessage('Option 2');
            end]
  ],procedure
    begin
    showmessage('Else option');
    end);


oxffff   (2010-04-02 15:35:00) [6]

Ну и естественно обобщенная версия

TPAIRTYPE<T>=record
Value:T;
Proc:TProc;
end;

CaseAnyTypeClassSupport<T>=class
private
class function GetCaseOption(Value:T;Action:TProc):TPAIRTYPE<T>;static;
public
class procedure MyCase(const Value:T;const Pairs:array of TPAIRTYPE<T>;ElseProc:TProc=nil);static;
class property CaseOption[Value:T;Action:TProc]:TPAIRTYPE<T> read GetCaseOption;default;
end;

uses generics.defaults;

class procedure CaseAnyTypeClassSupport<T>.MyCase(const Value:T;const Pairs:array of TPAIRTYPE<T>;ElseProc:TProc=nil);
var Pair:TPAIRTYPE<T>;
   Comparer:IComparer<T>;
begin
Comparer:=TComparer<T>.Default;
for Pair in Pairs do
  if Comparer.Compare(Value,Pair.Value)=0 then
    begin
    Pair.Proc();
    exit;
    end;
if Assigned(ElseProc) then ElseProc();
end;
class function CaseAnyTypeClassSupport<T>.GetCaseOption(Value:T;Action:TProc):TPAIRTYPE<T>;
begin
Result.Value:=Value;
Result.Proc:=action;
end;

procedure TForm2.FormCreate(Sender: TObject);
var Stuff:CaseAnyTypeClassSupport<string>;
begin
Stuff.MyCase('2',
   [
   Stuff['4',procedure
             begin
             showmessage('Option 1');
             end],
   Stuff['2',procedure
             begin
             showmessage('Option 2');
             end]
   ],procedure
     begin
     showmessage('Else option');
     end);
end;


Anatoly Podgoretsky   (2010-04-02 15:15:00) [7]

> oxffff  (02.04.2010 14:56:37)  [37]

Причины конечно были, но они остались в голове идеолога. Да и какая разница, когда case это особая форма it then else if


oxffff   (2010-04-02 15:07:00) [8]


> Sha ©   (02.04.10 13:07) [35]
> > oxffff ©   (02.04.10 12:28) [34]
> > Не могу найти в интернете, но были какие причины на отсутствие
> case для строк.
>
> Целочисленная оптимизация?


Вроде после прочтения этого.

http://www.delphifeeds.com/go/s/62355


oxffff   (2010-04-02 14:56:00) [9]


> Sha ©   (02.04.10 13:07) [35]
> > oxffff ©   (02.04.10 12:28) [34]
> > Не могу найти в интернете, но были какие причины на отсутствие
> case для строк.
>
> Целочисленная оптимизация?


Честное слово не помню. Но какое то ощущение осталось.
Пытался найти. Не нашел.
Возможно неоднозначность сравнения например при case sensitive.
То ли unicode. Честное слово не помню.


Dfcz Gegrby   (2010-04-02 14:22:00) [10]


> oxffff ©   (02.04.10 12:02) [30]

Извращенец. (в хорошем смысле ;) )


Sha   (2010-04-02 13:07:00) [11]

> oxffff ©   (02.04.10 12:28) [34]
> Не могу найти в интернете, но были какие причины на отсутствие case для строк.

Целочисленная оптимизация?


oxffff   (2010-04-02 12:28:00) [12]


> Игорь Шевченко ©   (02.04.10 12:25) [33]
> oxffff ©   (02.04.10 12:02) [30]
>
> Круть! Только зачем ?


Отдохнуть от Oracle. И возможно взять некоторые идеи к себе в компилятор.
Не могу найти в интернете, но были какие причины на отсутствие case для строк.


Игорь Шевченко   (2010-04-02 12:25:00) [13]

oxffff ©   (02.04.10 12:02) [30]

Круть! Только зачем ?


oxffff   (2010-04-02 12:11:00) [14]

Поддержка else. :)

procedure MyCase(const Value:string;const Pairs:array of TPair;ElseProc:TProc=nil);
var Pair:TPair;
begin
for Pair in Pairs do if Pair.Value=Value then
  begin
  Pair.Action();
  exit;
  end;
ElseProc();
end;


oxffff   (2010-04-02 12:03:00) [15]


>  здесь он совсем гибок.


не совсем гибок. :)


oxffff   (2010-04-02 12:02:00) [16]

Решил отдохнуть от Oracle. Написал только что. Сильно не бить.

Идея была свести до использования  

MyCase('1',[
          ['1',procedure  
                   begin
                   showmessage('Fuck stuff by oxffff. Option 1');
                   end],
          ['2',procedure  
                   begin
                   showmessage('Fuck stuff by oxffff. Option 2');
                   end]
          ]);    

Но!Есть ограничения у компилятора Delphi, здесь он совсем гибок.

Придется так

MyCase('1',[
          self['1',procedure  
                   begin
                   showmessage('Fuck stuff by oxffff. Option 1');
                   end],
          self['2',procedure  
                   begin
                   showmessage('Fuck stuff by oxffff. Option 2');
                   end]
          ]);    

Код

TPair=record
Value:string;
Action:TProc;
end;

 TForm2 = class(TForm)
   procedure FormCreate(Sender: TObject);
 private
   { Private declarations }
 protected
 Function GetCaseOption(Value:string;Action:TProc):TPair;
 public
   { Public declarations }
 property CaseOption[Value:string;Action:TProc]:TPair read GetCaseOption;default;
 end;

var
 Form2: TForm2;

procedure MyCase(const Value:string;const Pairs:array of TPair);
var Pair:TPair;
begin
for Pair in Pairs do if Pair.Value=Value then
  begin
  Pair.Action();
  exit;
  end;
end;

function TForm2.GetCaseOption(Value: string; Action: TProc): TPair;
begin
result.Value:=Value;
result.Action:=action;
end;

procedure TForm2.FormCreate(Sender: TObject);
begin
MyCase('1',[
          self['1',procedure  
                   begin
                   showmessage('Fuck stuff by oxffff. Option 1');
                   end],
          self['2',procedure  
                   begin
                   showmessage('Fuck stuff by oxffff. Option 2');
                   end]
          ]);        
end;


Leonid Troyanovsky   (2010-04-02 09:48:00) [17]


> _Юрий   (01.04.10 19:54) [28]

> Требуется создать дочерний объект нужного класса в зависимости
> от имени узла, и вызвать его загрузку.

Т.е., имена, все же, поступают извне.
Я б обратил внимание на 1 метод by Vladimir Titov.

И еще, тут стоило б подумать об использовании
Delphi streaming system.

--
Regards, LVT.


_Юрий   (2010-04-01 19:54:00) [18]


> Leonid Troyanovsky ©   (31.03.10 22:10) [22]



> Если импорт строк исключен, то мне немного сложно представить
> необходимость их пользования в данном случае.
>


Приведу пример:
грузимся их XML
Начинаем обработку очередного узла
var  Node: IXMLNode;

Требуется создать дочерний объект нужного класса в зависимости от имени узла, и вызвать его загрузку.

Как решать задачу...
Можно сделать регистрацию классов, и искать нужный класс в цикле, сравнивая имя Node с результатом какого-нибудь классового виртуального метода общего предка:

for I:=0 to ClassList.Count -1 do
 if TMyClass(ClassList[I]).GetXMLNodeName = Node.NodeName then
 begin
   Result:=TMyClass(ClassList[I]).Create();
...

но если дочерних классов немного, то городить регистрацию может быть нецелесообразно. Кроме того, общего предка может не быть.
Тогда пишем так:
case IndexStr(Node.NodeName, [TMyClass1.GetXMLNodeName,     TMyClass2.GetXMLNodeName, TMyClass3.GetXMLNodeName]) of
0: Result:=TMyClass1.Create();
1: Result:=TMyClass2.Create(param1);
2: Result:=TMyClass3.Create(param2, param3);
else NotFound();

то есть сами значения строк могут приходить и снаружи, но именно массив  полностью заполняется прямо в теле case

Я правда погорячился, когда сказал, что паттерн используется в хвост и в гриву. Используется он изредка, часто используется другой паттерн, похожий

case IndexOfObject(MyObj, [TMyClass1, TMyClass2, TMyClass2]) of
0: //MyObj is TMyClass1
1: //MyObj is TMyClass2
2: //MyObj is TMyClass3

вместо многократных
if MyObj is TMyClass1 then ...
else  if MyObj is TMyClass2...

Но это уже оффтоп.

И на месте автора я бы для данного примера сделал по-другому, а именно - объявил бы тип-перечисление, и завел бы констатарный массив строк.

type
 TMyOperation = (moOpen, moSend, moETC);

const
 Commands: array[TMyOperation] of string = ('Open', 'Send', 'ETC');

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


ford   (2010-04-01 09:26:00) [19]

спасибо за предложенные варианты :)


Leonid Troyanovsky   (2010-04-01 08:15:00) [20]


> Германн ©   (01.04.10 01:46) [25]

> У меня была, да и сейчас существует и продаётся (вот только
> вчера-позавчера обновил инсталляторы) ПО, в котором две
> программы обмениваются информацией по TCP/IP.

Если они обмениваются, то у обеих есть импорт (строк).
А тут извне строки не поступают.

Кто там у нас  не в теме? :)

--
Regards, LVT.


Страницы:   1 2 3

Наверх

Титульная страница Поиск, карта сайта Написать письмо