Newsgroup: it.comp.lang.delphi
Titolo: Costrutto Case

Ciao a tutti,
notavo che il costrutto case of accetta solo tipi ordinali. Come posso 
ovviare il problema (escludendo le if then) nel caso in cui volessi 
confrontare delle stringhe?
Per intenderci qualcosa del tipo:
case miastringa of
  'stringa1' : fai questo;
  'stringa2 : fai questo;
  'stringa3 : fai questo;
  'stringa4 : fai questo;
 else
  'stringan : fai questo;
end;
C'è qualche soluzione?
Grazie in anticipo,
Cooper. 

 confrontare delle stringhe?
Tranne quella di usare il convenzionale *if*, direi di no, in generale.
Ma potresti sempre dichiarare una costante appartenente ad un tipo
   *array [<ordinal_type>] of string*
magari usando come tipo ordinale un "enumerativo" e, attraverso un 
ciclo, verificare se la stringa coincide con una delle stringhe costanti 
e, in caso affermativo, usare direttamente il tipo enumerativo per 
eseguire il *case*.
La possibilità di usare una soluzione del genere, sempre che si possa 
ritenere utile, dipende dal caso specifico reale in esame.
Ciao,
   Marco.
-- 
MARCO BREVEGLIERI
  (
http://www.marco.breveglieri.name
)


Grazie mille.
Cooper. 

>
Io faccio così:
s:='stringa1/stringa2/stringa3/ .....';
case POS(s,STRINGAX)
1: fai questo;
9: fai quello;
else
........
Ciao

........
... quindi se cambio una qualsiasi stringa che non sia l'ultima,
modificandone la lunghezza, devo riaggiornare gli indici di tutto il
serpentone... minchia che furbata! :)

confrontare delle stringhe?
type
  TStringArray = array of string;
  TStringCase = class
  private
    FStringArray: TStringArray;
    FStringList: TStringList;
  public
    constructor Create(const AStringArray: TStringArray);
    destructor Destroy; override;
    function IndexOf(const AString: String): Integer;
  end;
  function TStringCase.IndexOf;
  begin
    Result := FStringList.IndexOf(AString);
  end;
  destructor TStringCase.Destroy;
  begin
    FStringList.Free;
  end;
  constructor TStringCase.Create;
  var
    I: Integer;
  begin
    FStringList := TStringList.Create;
    FStringArray := AStringArray;
    for I := Low(FStringArray) to High(FStringArray) do
      FStringList.Add(FStringArray[I]);
  end;
// ..........
procedure TForm1.BitBtn1Click(Sender: TObject);
var
  I: Integer;
  S: String;
begin
  S := 'pluto';
  with TStringCase.Create(VarArrayOf(['pippo','pluto','paperino'])) do
    case IndexOf(S) of
     -1: ShowMessage('not found!');
      0: ShowMessage('aaa');
      1: ShowMessage('bbb');
      2: ShowMessage('ccc');
    end;
end;

 Io faccio così [...]
Mi sembra un metodo alquanto scomodo: oltre a dover ricalcolare gli 
indici ad ogni modifica, hai una probabilità del 99% di sbagliare, a 
meno che il numero di "sottostringhe" non rimanga limitato, tanto da 
giustificare a quel punto l'uso di un semplice *if*.
Forse questa ricerca del "Case con stringhe" proviene da qualche 
abitudine dura a morire data da VB? :-)
E' una possibilità che potrebbe risultare comoda, ma non la trovo 
indispensabile, soprattutto pensando al fatto che molto raramente mi 
capita di dover condizionare blocchi di codice a valori stringa; non 
saprei dire però se questo deriva da una organizzazione o da un modo 
diverso di scrivere codice a livello personale o dal fatto che non mi 
capiti frequentemente di incappare in un caso che lo richieda. :-)


Prova cosi'
n: Integer;
n:=StrToInt( copy(miastringa,8,length(miastringa)) );
Case n of
1: ...
2: ...
3: ...
else
..
end;
Ciao Giorgio 

 serpentone... minchia che furbata! :)
e tu non cambiare il serpentone, accontentati di quello he hai ...
:-)
Ciao

capiti frequentemente di incappare in un caso che lo richieda. :-)
Credo derivi dal fatto che una stringa literal difficilmente viene
usata per identificare qualcosa (il case è fondamentalmente un
costrutto che consente di selezionare un ramo di elaborazione in base
a un valore identificativo di quel ramo).  
Il fatto che il Pascal scoraggi questa attitudine, non supportando il
case tra stringhe, induce a pensare che sia un linguaggio progettato
molto bene.  
Il C# e il VB supportano questa caratteristica, ma sarebbe orribile
vedere in Delphi qualcosa del tipo:
case operazione of
 'inserimento': ...
 'modifica': ...
 'cancellazione': ...
end;
Significherebbe incoraggiare una pessima pratica di programmazione.

n:=StrToInt( copy(miastringa,8,length(miastringa)) );
Immagino che "stringa1", "stringa2", "stringa3" fossero solo degli
esempi...

 ha scritto nel messaggio 
news:sp4u021bra2gjbllg...@4ax.com...

Molto interessante questa soluzione :)
Grazie mille,
Cooper. 


La mia esigenza nasceva dal fatto che estraendo l'estensione da un nome di 
file, volevo identificare questa non tramite i soliti tre caratteri 
preceduti dal punto ma attraverso un nome piu esplicito.
Qualcosa del tipo:
'.exe' => 'Executable file'
'.dll' => 'Dynamic Link Library'
...
'.zip' => 'Zip File'
e cosi via.
Grazie a tutti per l'interessamento.
Cooper. 

 preceduti dal punto ma attraverso un nome piu esplicito.
Ottimo, un buon pretesto per poter sfruttare i suggerimenti ricevuti e 
costruire un "elenco dinamico" di coppie "estensione=descrizione" senza 
scriverlo letteralmente nel codice, anzi magari caricandolo da un file 
esterno a runtime.
In caso contrario, credo che potresti comunque risolverlo con un array 
di costanti, magari record, aventi due campi di cui uno contiene 
l'estensione e l'altro la descrizione; ti basta scorrerlo con un ciclo 
e, laddove trovi l'estensione cercata, restituire la descrizione 
corrispondente.
Credo che un *case* si possa comunque evitare tranquillamente. :-)



Uhm ho capito, però non devo visualizzare le estensioni, ma devo 
visualizzare su una campo testo al posto della estensione, la sua 
descrizione.
Per cui assegno a x il nome del file, estraggo l'estensione con 
extractfileext e l'assegno a una variabile, a questo punto interveniva il 
case per convertire l'estensione rilevata nella relativa descrizione per 
visualizzarla in un campo testo all'interno del form.
Cmq a titolo di esercizio, ritornando al discorso di sopra, consigli la 
creazione di un file xml e la relativa lettura?
Grazie ancora,
Cooper. 

descrizione.
procedure TForm1.Button1Click(Sender: TObject);
var
  L: TStringList;
  Index, I: Integer;
begin
  L := TStringList.Create;
  L.Add('.exe=Applicazione');
  L.Add('.bmp=Bitmap');
  L.Add('.txt=File di testo');
  Index := -1;
  for I := 0 to L.Count-1 do
    if L.Names[I] = '.bmp' then
    begin
      Index := I;
      Break;
    end;
  if Index<>-1 then
    ShowMessage(L.ValueFromIndex[Index]);
end;

 end;
Grazie ancora, per il tuo aiuto
Cooper 

Un mio piccolo contributo (confesso che ho rielaborato una routine trovata
su internet, spero di non aver fatto pasticci ;-)
Unit TestoDaEstensione;
interface
uses Sysutils, Dialogs;
function StringToCaseSelect (Selector : string; CaseList: array of string):
Integer;
procedure EstraiEstensione;
implementation
function StringToCaseSelect (Selector : string; CaseList: array of string):
Integer;
var cnt: integer;
  begin
    Result := -1;
    for cnt := 0 to Length(CaseList)-1 do
      begin
      if CompareText(Selector, CaseList[cnt]) = 0 then
        begin
        Result:=cnt;
        Break;
        end;
      end;
  end;
procedure EstraiEstensione;
var estensione, selector : string;
  begin
    selector := ........;    //qui l'estensione da verificare;
      case StringToCaseSelect(selector, ['zip', 'exe', 'txt']) of
      0   : estensione := 'file compresso';
      1   : estensione := 'eseguibile';
      2   : estensione := 'file di testo';
      end;
    showmessage(estensione);
  end;
end.
-- 
F&R