26. juli 2010 - 07:44 Der er 20 kommentarer og
1 løsning

IF THEN - ELSE - else - else - else - else..... ?

HEJ

Jeg har et problem (det har vi vel alle men dette er af programmeringsmæssig art.. ) ..

Jeg har brug for at kunne vælge mellem 1 og N variable og tage en aktion på dette valg.

Altså:

IF N = V00 then
  Res := Funktion000 (P00)
ELSE
  IF N = V01 then
    Res := Funktion001 (P01)
  else
      ..
      ..
      ..   
      IF N = V99 then
        Res := Funktion99(V99);
 
V00, V01 .. V99 = Widestring;
P00, p01 .. P99 = Widestring (parameter)
RES            = Widestring (resultat);
N = Integer;

Antallet af søgninger vil være variabelt (i viste eksempel er antal = 100 ).

I stedet for at lave en søgefunktion på 100 IF THEN ELSE havde jeg forestillet mig noget i stil med en fil (TFileStream) med 100 linier (felt1 = Nummer (N ) felt2 = fukktionskald(Funktionxx), felt 3 = parameterfelt(Vxx) ).

(variablen N justeres (naturligvis) til korrekte antal )

Jeg har lavet lidt Fil-eksperimenter (CSV-typen) og det funker, men har nogen problemer med funktionskaldet (FunktionNNN(parameter NNN) .)

Hvordan gør jeg det ???

Kristian
Avatar billede gadensgaard Nybegynder
26. juli 2010 - 08:25 #1
Jeg må indrømme at jeg ikke er super skarp i Delphi, men skulle jeg selv lave den slags havde jeg gjort det i en switch statement. Jeg googlede for at se om jeg kunne finde noget tilsvarende i Delphi, og fandt dette:
http://www.delphibasics.co.uk/RTL.asp?Name=Case
26. juli 2010 - 08:59 #2
Hej,

Tak for responsen.

Jeg var faktisk selv inde på den side for at finde inspiration.

Der er imidlertid en ting, som gør at en Switch løsning ikke er særlig attraktiv. Nemlig den variable størrelse af antal søgemuligheder.

Switch-løsningen forudsætter (så vidt jeg er orienteret - korriger mig hvis jeg er galt afmarcheret ) at antalet af faste søgeparametre er fast.

Og det forudsætter igen, at jeg skal skive IF THE ELSE .... ELSE  de (i nævnte tilfælde 100 gange. Men hvad hvis søgeantallet ændres til 150 ? -- > Nyt program og ny kompilering...

Ergo Switch løsningen er ikke vejen frem.

Men tak for hjælpen.

Løsningen er mer i retning af Execute (variabelNNN) (eller hvordan den korrekt syntaks nu er.. )

KR(istian)
Avatar billede martinlind Nybegynder
26. juli 2010 - 13:09 #3
Du kan lave en StringList og smide din var i sting[] og en procedure kald i objects[]

Det ville nok være den løsning jeg ville vælge :-)
Avatar billede hrc Mester
26. juli 2010 - 15:15 #4
Hvorfor ikke bruge Case (antagende at Vxx er heltalskonstanter)?

case N of
  V00: func00();
  V01: func01();
  V02:;
  else
    assert(false,format('Værdi N=%d ikke håndteret',[N]));
end;

Men udover det, så er martins løsning også værd at overveje - om ikke andet så bare for at lære noget nyt. Objects-delen i lister er en overset funktionalitet
Avatar billede hrc Mester
26. juli 2010 - 15:28 #5
Har lige nærlæst tråden igen. Martins løsning er helt fin (måske endda den bedste, æv). Er dog ikke helt sikker på jeg forstår hele problemstillingen.

Her en variant af stringlist-løsningen. Listen læser alle Vxx'erne ind fra en fil og så er positionen i listen det der refererer til handlingen, dvs. V00 returnerer indeks 0 i listen.

var
  sl: TStringList;
  index: integer;
begin
  sl := TStringList.Create;
  try
    sl.LoadFromFile('fil.txt');
    index := sl.IndexOf(N);
    case index of
      0: func001(p01);
      1: func002();
      2:;
      else
        assert(false,format('Værdi N=%s ikke håndteret',[N]));
    end;
  finally
    sl.Free;
  end;
end;

Alternativt, hvis du skal køre med Martins løsning, så kan du lave dine funktioner i den klassens protected-sektion og så løbe den igennem via RTTI - men så bliver det mere langhåret.
Avatar billede hrc Mester
26. juli 2010 - 15:38 #6
For nu at fortsætte RTTI-løsningen så kan du angive dine Vxx i tekstfilen sådan her:

XX02=Func001
XX02=Func002
XX03=Func003
XX04=Func004

Hvis alle dine funktioner er defineret i protected-delen så kan du søge efter deres pointere via navnet i tekstfilen. Så kan du nøjes med at sende ny tekstfil ud (altså såfremt der ikke kommer nye funktioner til).
26. juli 2010 - 16:24 #7
HEJ ,

Tak for de mange fine forslag.

På arbejdet havde jeg en 1/2 times tid, hvor jeg ikke havde noget at lave. I den tid lagde jeg lige vejen ind forbi vores programmør (han er C++ ekspert (men bortset fra det, er han meget flink (!) ) og han gav mig en ide, jeg har arbejdet lidt videre med og det ser ud til at der faktisk er kød på ideen.

Den er basert på at Object- ideen, som Martin Lind er lidt inde på.

Skal prøve den noget senere i aften. Og melder tilbage.

KR(istian)
Avatar billede hrc Mester
26. juli 2010 - 16:39 #8
Flink C++ programmør (et oxymoron?)? Der er stadig håb; selv Darth Vader så jo lyset til sidst.
Avatar billede martinlind Nybegynder
26. juli 2010 - 17:00 #9
Jeg formoder det er et fast defineret antal rutiner du skal bruge til at behandle dine data i listen, så du definerer dine procedure i din form-klasse og lægger den rigtige procedure-ref i objects[x] og så kan du derefter kalde den der er puttet ind når du lopper rundt i din liste, det tror jeg helt klart er det nemeste

HUSK dinne procedure til at lægge i objects skal være en del af en klasse så slipper du for en masse med pointer dit og dat, dem kan delphi håndtere på samme måde som en event-procedure.

:-)
26. juli 2010 - 17:59 #10
HEJ,

Specielt til HRC:

Min C++ kollega arbejder i udviklingsafdelingen, jeg i arkivet. Vi hjælper hinanden lidt asynkront når problemerne opstår så han har set LYSET (OG Herren sagde "Lad der blive ... " ). Men at vi "smådriller" hianden når han C+R (= "ser") lyset er et faktum. 

Et Oxymoron ? - Tja, jeg ved ikke om "man" (hvem det nu engang er ?) kan sammenligne det med en kontrafaktisk hypotese ... uden at det dog skal give anledning til en debat a la følgende udsagn:

"Konsekvensen heraf (af billedteorien og ekstensionalitetstesen) bliver dels at vi vrøvler hvis vi prøver at redegøre for de logiske formers natur, og dels at et hvilket som helst udsagn vi fremkommer med vil kunne karakteriseres som enten 1) en tautologi, der altid og overalt er sand og derfor intet siger om nogen verden, 2) en kontradiktion, der altid og overalt er falsk og der heller intet siger om nogen verden, eller 3) en kontingent sætning, der enten er sand eller falsk og derfor siger noget om verden, og hvor vi til afgørelse af sandhedsværdien er afhængige af vore sanser.  "

Sakset fra " http://www.filosofiske-essays.dk/artikler/sproganalyse.htm "

PS: (he he !)

Nå, spøg til side (og hofter fat:)

EFter lidt bøvlen og (nogen hjælp) lykkedes det mig at få mikset dette her sammen:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    ComboBox1: TComboBox;
    procedure Button1Click(Sender: TObject);
    procedure Test1(Sender: TObject);
    procedure Test2(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    procedure ExecMethod(OnObject: TObject; MethodName: string) ;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

type
  TExec = procedure of object;

implementation

{$R *.dfm}

procedure TForm1.ExecMethod(OnObject: TObject; MethodName: string) ;
var
  Routine: TMethod;
  Exec: TExec;
begin
  Routine.Data := Pointer(OnObject) ;
  Routine.Code := OnObject.MethodAddress(MethodName) ;
  if NOT Assigned(Routine.Code) then
      Exit;
  Exec := TExec(Routine) ;
  Exec;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  IF Combobox1.Text <> '' then
      ExecMethod(Form1, Combobox1.Text);
end;

procedure TForm1.Test1(Sender: TObject) ;
begin
  ShowMessage('Dette er test 1 ') ;
end;

procedure TForm1.Test2(Sender: TObject) ;
begin
  ShowMessage('Dette er test 2 ') ;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Combobox1.Clear;
  Combobox1.Items.Add('Test1');
  Combobox1.Items.Add('Test2');
end;

END.

Det funker, og med en hel del tilpasning til den faktiske problemstilling vil jeg kunne løse problemet.

Så jeg har osse lært noget af det ..

KR(istian)
Avatar billede hrc Mester
27. juli 2010 - 08:41 #11
Ja, ja. Jeg begyndte at hade C++ efter jeg prøvede at læse en bog af Stoustrup himself. Fattede ikke ret meget inden kedsomheden overtog. Har stadig bogen da ingen vil købe den.

Qua det softwaren der er udviklet gennem tiden, må jeg dog erkende at de, C++ udviklerne, er menneskets bedste ven (for nu at genbruge den med kvinderne).

Tak for du postede din løsning. Jeg vil lege lidt med din ExecMethod
Avatar billede hrc Mester
27. juli 2010 - 20:36 #12
Det tog mig lidt til at forstå hvorfor det skulle gennem en TMethod, men det er for at få parameteren med over (Sender: TObject).

Nu forstår jeg det - og jeg MÅ da kunne bruge det et eller andet sted...
Avatar billede martinlind Nybegynder
27. juli 2010 - 23:13 #13
hehe.. hej i to, det er da godt gået, hvis du er newbee...

tror måske du kan lave det lidt enklere hvis du kan gøre lige som componenter har event-handlere, evt. lur på en af delphi componenter i sourcen.... eller du kan fortsætte med din kode, du har jo nok kæmpet lidt, så fuldt forståeligt hvis du bruger DIN kode, det ville jeg nok også selv gøre :-) fortsat godt kamp
Avatar billede martinlind Nybegynder
28. juli 2010 - 09:24 #14
ved nærmere efter tanke og en natssøvn, kan den lidt simplere måde være at lægge din execute procedure ind i en lille klasse og så lave en instans af den og lægge i objects

TmyClass(L.Objects[x]).myExecute

Det kræver bare en hoved-klasse en en virtuel myexecute og nogle nedarvede klasser hvor du overrider myexecute, det var nok sådan noget jeg tænkte på :-)
Avatar billede martinlind Nybegynder
28. juli 2010 - 11:31 #15
Så har jeg lavet et eks. som efter min smag er lidt mere overskueligt og ikke helt så langhåret :-)

Form-dfm filen :
--------------

object Form1: TForm1
  Left = 372
  Top = 134
  Width = 431
  Height = 169
  Caption = 'Form1'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  OnCreate = FormCreate
  OnDestroy = FormDestroy
  PixelsPerInch = 96
  TextHeight = 13
  object Button1: TButton
    Left = 165
    Top = 20
    Width = 131
    Height = 25
    Caption = 'Tilføj Til Liste'
    TabOrder = 0
    OnClick = Button1Click
  end
  object RadioGroup1: TRadioGroup
    Left = 40
    Top = 15
    Width = 116
    Height = 81
    Caption = ' Vælg execute '
    ItemIndex = 0
    Items.Strings = (
      'Execute proc1'
      'Execute proc2')
    TabOrder = 1
  end
  object Button2: TButton
    Left = 170
    Top = 70
    Width = 126
    Height = 25
    Caption = 'Udfør Liste'
    TabOrder = 2
    OnClick = Button2Click
  end
end


Form-pas filen :
----------------

unit uExecuteTest;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    RadioGroup1: TRadioGroup;
    Button2: TButton;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    L : TStringList;
  end;

var
  Form1: TForm1;

implementation

uses uExecute;

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  L := TStringList.Create;
end;

procedure TForm1.FormDestroy(Sender: TObject);
VAR
  I : Integer;
begin
  for I := 0 to L.Count-1 do L.Objects[I].Free;
  L.Free;
end;

procedure TForm1.Button1Click(Sender: TObject);
VAR
  B : TmyBaseExecute;
begin
  case RadioGroup1.ItemIndex of
      0 : B := Tmy1Execute.Create;
      1 : B := Tmy2Execute.Create;
  end;
  L.AddObject('Metode :'+IntToStr(RadioGroup1.ItemIndex+1),B);
end;

procedure TForm1.Button2Click(Sender: TObject);
VAR
  I : Integer;
begin
  for I := 0 to L.Count-1 do
    TmyBaseExecute(L.Objects[I]).MyExecute(I,L[I]);
end;

end.

og sidst Unit-pas filen :
-------------------------

unit uExecute;

interface

uses
  Windows, SysUtils, Classes, Dialogs;

type
  TmyBaseExecute = Class(TObject)
  public
    procedure MyExecute( aParam1 : Integer; aParam2 : String ); virtual; abstract;
  end;

  Tmy1Execute = Class(TmyBaseExecute)
  public
    procedure MyExecute( aParam1 : Integer; aParam2 : String ); override;
  end;

  Tmy2Execute = Class(TmyBaseExecute)
  public
    procedure MyExecute( aParam1 : Integer; aParam2 : String ); override;
  end;


implementation


{ Tmy1Execute }

procedure Tmy1Execute.MyExecute(aParam1: Integer; aParam2: String);
begin
  ShowMessage(Format('aParam1 : %d aParam2 : %s',[aParam1,aParam2]));
end;

{ Tmy2Execute }

procedure Tmy2Execute.MyExecute(aParam1: Integer; aParam2: String);
begin
  ShowMessage(Format('aParam1 : %d aParam2 : %s',[aParam1,aParam2]));
end;


end.
Avatar billede hrc Mester
28. juli 2010 - 19:48 #16
Martin: Kristians løsning er da ikke langhåret. Den er elegant og enkel - og derfor ikke store risici i den (ikke mange steder ting kan gå galt) - har endnu ikke fundet et sted hvor jeg kan bruge løsningen.
Kristian kunne undlade at sende self med over, men det er vel fordi han holder døren åben for kald af funktioner forme på samme tid??
28. juli 2010 - 20:29 #17
HEJ

(martinlind og hrc)

HRC - skriver:

" Kristian kunne undlade at sende self med over, men det er vel fordi han holder døren åben for kald af funktioner forme på samme tid??  "

Det er korrekt. Det er meningen at jeg skal kunne starte en funktion på flere forme.

Har ikke så megen tid til mine private program-udviklinger. På Job skal jeg teste/lave noget XML-overførsel (se nyt EKSPERT-spørgsmål ) fra min "lokale srbejds-PC " til en Central SQL / XML Server. Og det har 1. prioritet (skulle være færdig forrige år - ifølge chefen, selv om opgaven blev defineret i formiddags (nyt oxymoron (hæ hæ ! ) .. (suk og suk og atter suk - Er der noget at sige til at jeg er og (for-) bliver gråhåret ???

END.

KR(istian)
Avatar billede hrc Mester
28. juli 2010 - 20:54 #18
Kristian: Ikke Oxymoron denne gang, bare Moron (om chefer). Mine grå hår kom samtidig med mine 3 børn (omtrent samtidig med jeg holdt op med at smile, et sammenfald?)

Hvis det er to SQL-databaser du skal udveksle data mellem, kan du overveje replikering. Det er godt nok lidt besværligt at sætte op, men når det kører, er det næsten transparent.
Avatar billede martinlind Nybegynder
28. juli 2010 - 21:20 #19
hehe... synes nu stadig mit er mere oop-agtigt og delphi-like ....

God vind, i to gamle mænd :-)
28. juli 2010 - 21:44 #20
HEJ.

martinlind:  Gamle mænd... ?

(Hvis du ikke opper dig, kommer jeg med min hvide stok og slår dig...  )..  (he he (gnækker som Windows ( i baggrunden).. ))

HRC:

Lyder som en glimrende ide, men umulig at implementere -- fordi cheferne (DE STORE MORONER !) har besluttet at vi almindelige dødelige (os små MORONER ?) IKKE må få adgang (direkte adgang) men ALT (  A L T  ) skal foregå via XML-scripts ..

(#¤#¤#"#"#"#"¤#" og FAND(censur) ..)

OG med hensyn til børn:

Da Anne Louise (min store datter ) var 4 år væltede hun ved et uheld et glas vand ned i min daværende STORE PC (486dx med FPU) 8 MB ram og 120 MB harddisk.

Så er det man med sammenbidte tænder og meget hårdt udtryk i øjnene hvisler:

"Børn er en velsignelse, børn er en velsignelse,  børn er en velsignelse,  børn er en velsignelse, .... ).

Så Martin glæd dig til du får dit første barn ( men hold ham/hende fra din PC og en vandhane (samtidig)....

KR ( mange ) (Istian)
19. september 2010 - 01:16 #21
LUKKER LINK
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester