Switch case mit string

#2000887
Lesenswert?

Hallo,
ich habe c++ porgramm entwickelt, dass ich jetzt mit Hilfe von 
Parametern aus der Console aus aufrufen möchte.

also z.B.: "myprog.exe -reset"
Dann soll der reset ausgeführt werden und vieles mehr.
Da es hier mindestens 15 fälle gibt wollte ich das mit einer Switch case 
realisieren, dass will aber nicht funktionieren.

Hat jmd. eine sinnvolle Idee, wie ich das realisieren kann. Switch case 
kann nur char oder int. Also habe ich versucht das zu mappen, aber das 
hat nicht richtig funktioniert.

Des weiteren bin ich auch getopt gestoßen, aber das bekomme ich iwie 
nicht richtig zum laufen (windows).

Hat jmd. eine Idee? Hat jmd. schonmal ein ähnliches problem gehabt?

Ich hab also mehrere Anstäze und keiner hat auf Anhieb funktionier ;) 
Jetzt wollte ich mich erstmal umhören, bevor ich mich auf einen 
festlege.

Vielen dank für die Ideen schonmal.

Grüße tom
#2000944
Lesenswert?

Es kann ja nicht sein, dass ich 15 IF abfragen hintereinander machen 
muss oder liege ich da falsch?

Bei fast bei jedem Befehl in der cmd gibt es die Parameter, welche 
einfach angehängt werden. Ich dachte eben, dafür gibt es eine Art 
Standard wie das im allgemeinen gelöst wird.

Würdet ihr das etwa mit IF-ELSE lösen?
#2000947
Lesenswert?

Mach dir ein Array, wo du alle "Vergleichsstrings" ablegst und mach vor 
dem Switch ein strcmp und werte die Zahl aus. Also etwa so
1
#include <stdlib.h>
2
#include <stdio.h>
3

4
#define NR_STRINGS 5
5
char cmp_strings[][20] = {"scheisse","mit","erdbeeren","ihh", "erdbeeren!"};
6

7
int main(){
8
   int cmp_str,i;
9
   char buffer[]="mit";
10
   
11
   //string_abfragen(buffer);
12
   
13
   for(i=0; i < NR_STRINGS; i++){
14
     if(!strcmp(buffer, cmp_strings[i]))
15
       break;
16
     if(i == NR_STRINGS -1)
17
       i = -1;
18
   }
19
   switch(i){
20
      case 0:
21
        printf("Da stand was ekeliges drin");
22
        break;
23
      case 1:
24
        printf("Da stand \"mit\" drin");
25
        break;
26
      ...
27
   }
28
}
#2000958
Lesenswert?

Geht natürlich auch so:
1
#include <stdlib.h>
2
#include <stdio.h>
3

4
#define NR_STRINGS 5
5
char *cmp_strings[] = {"scheisse","mit","erdbeeren","ihh", "erdbeeren!"};
6

7
int main(){
8
   int cmp_str,i;
9
   char buffer[20];
10
   
11
   string_abfragen(buffer);
12
   
13
   for(i=0; i < NR_STRINGS; i++){
14
     if(!strcmp(buffer, cmp_strings[i]))
15
       break;
16
     if(i == NR_STRINGS -1)
17
       i = -1;
18
   }
19
   switch(i){
20
      case 0:
21
        printf("Da stand was ekeliges drin");
22
        break;
23
      case 1:
24
        printf("Da stand \"mit\" drin");
25
        break;
26
      ...
27
   }
28
}
#2000991
Lesenswert?

Hi,
mit den Posts hat es sich gerade ein wenig überschlagen. Ich hab mich 
jetzt für die Lösung von Timmo entschieden, die ist meiner Meinung nach 
sehr elegant ;)
Hab noch kurz eine schleife drumherum gebaut und ZACK kann man alle 
Eingabeparameter auswerten.

Vielen Dank nochmal, an alle die sich hier so schnell und fleißig 
gemeldet haben.

Hier das Resultat:
1
#define NR_STRINGS 5
2
char *cmp_strings[20] = {"-status","-reset","erdbeeren","ihh", "erdbeeren!"};
3

4

5
int main(int argc, char** argv)
6
{
7
  USBDev a;
8

9
   int cmp_str,i;
10
   for(int j =1;j<argc;j++)
11
   {  
12
     for(i=0; i < NR_STRINGS; i++){
13
     if(!strcmp(argv[j], cmp_strings[i]))
14
       break;
15
     if(i == NR_STRINGS -1)
16
       i = -1;
17
     }
18
       switch(i){
19
        case 0:
20
        printf("-status");
21
        break;
22
        case 1:
23
        printf("-reset");
24
        break;
25
       }
26
   }
27
}
Gast #2001077
Lesenswert?

Ich würde eine Klasse dazu erstellen. Für jeden Parameter instanzierst 
du diese Klasse und übergibst ihr die Kommandozeile und den Parameter 
den du haben willst. Nun baust du noch eine Funktion ein die prüft ob 
der Parameter gesetzt wurde, dieser gibt halt true oder false zurück, je 
nachdem ob der Parameter in der übergebenen Liste ist oder nicht.

z.b. hab ich eine Klasse generiert die "clpar" heisst.
Als Konstruktor nimmt sie argc, argv und den Parameter (in echt noch 
mehr).
Dann gibts noch ne Funktion namens isSet() (auch hier natürlich noch 
andere).

Also z.B.:
1
clpar parameterABC(argc, argv, "--ABC");
2
clpar parameterDEF(argc, argv, "-def");
3

4
if (parameterABC.isSet()) // hier tue was

Das war jetzt natürlich nur so grob die Vorgehensweise.
Damit hat man ne schöne Kapselung vom Rest des Projektes und kann die 
Klasse immer schön wiederverwenden.
Ich hab z.B. noch so Sachen wie Argumente für Parameter und deren 
Prüfung mittels Regex eingebaut.
Gast #2001082
Lesenswert?

Ich würde mich nach getopt umschauen. Oder die Parameter sortieren und 
mit bsearch() arbeiten.

Alternativ kann man in der Suchtabelle prima Callbacks hinterlegen oder 
Zeiger auf Flaggen und so weiter.
Gast #2001180
Lesenswert?

Tom A. schrieb:
> Ich hab mich
> jetzt für die Lösung von Timmo entschieden, die ist meiner Meinung nach
> sehr elegant ;)

Dann mach es so, ich finde es nicht sehr schön, da man ein 
aussagekräftigen string Vergleich durch eine Zahl ersetzt wird.
Ein paar else if Anweisungen finde ich persönlich schöner, die muss man 
dann noch nicht mal mehr kommentieren, da der Inhalt schon der Kommentar 
ist.

und wie schon gesagt bist du nicht der erste der das Problem hatte -> 
getopt
#2001215
Lesenswert?

Was in C++ auch geht, ist eine
  std::map< std::string, void(*)() >   meinemap;
oder so ähnlich, also eine Map, die Strings auf Funktionen mappt.
Dann geht die Auswahl mit einem schnöden meinemap[meinstring]()
oder ggf. analog mit Parametern oder Funktionsobjekten statt
Funktionen, falls man richtig schick programmieren will.
#2001339
Lesenswert?

Tom A. schrieb:

> Würdet ihr das etwa mit IF-ELSE lösen?

Kommt drauf an.
Wenn das alles ist, was ausgewertet werden muss: Ja, warum nicht?
15 sind doch nicht viel.

Das ist einfach, schnell geschrieben, leicht zu durchschauen, leicht zu 
erweitern (im Falle eines Falles).

Der Lösung krampfhaft einen switch-case über den Umweg eines Indizes 
einzuführen, kann ich zb überhaupt nichts abgewinnen. Da ist die 
eigentlich wichtige Information, nämlich welches Codestück zu welchem 
Paramater gehört über einen nicht unerkleckliches Stück Code 
verschmiert. Um zu wissen, wann genau der case mit der Nummer 13 
ausgeführt wird, muss ich Wörter in einem Array abzählen. Da schau ich 
lieber auf das if am Anfang des Abschnitts, denn dort steht im Klartext, 
wie die Option lautet. Denn: kürzer ist diese 'Index in Array suchen und 
darauf ausbauen switchen' Lösung in Wirklichkeit auch nicht. Sie 
verschleiert nur ein wenig mehr, was da eigentlich passiert.

Aber seis drum.
Irgendwann wirst auch du merken, dass die vermeintliche Tipparbeit das 
kleinste aller Probleme ist. Code schreibt man nur einmal (ok, manchmal 
wird er noch korrigiert), aber man liest ihn viele male. Da schreib ich 
mir den Code lieber so, dass ich beim Lesen nicht vielen Querverweisen 
folgen und ständig rauf/runter scrollen muss um die Details zu sehen.
#2001616
Lesenswert?

Ok, das mit der switch case, das sehe ich nun auch ein ist Käse ;) da 
man später wirklich nicht mehr durch ...

Ich werde mir jetzt mal das mappen von Funktionen anschauen und mal 
schauen ob das eine gute Lösung für mich ist.

Die if else Lösung finde ich nach wie vor noch nicht soooo tolle ;)

Danke für die Ideen.

Grüße Tom
#2001628
Lesenswert?

Ok, also ich werde es jetzt mal mit einer map realisieren, wenn mich 
dann nochmal etwas stören sollte, werde ich es über den haufen werfen ;)

Die Lösung sieht jetzt so aus:
1
#include <iostream>
2
#include <string>
3
#include <map>
4
using namespace std;
5

6

7
void status() { cout << "status" << endl; }
8
void reset() { cout << "reset" << endl; }
9

10
int main(int argc, char** argv)
11
{
12

13

14
  typedef void (*ptr_fct)();
15
  typedef   map<string, ptr_fct> MapCall;
16
  MapCall fct_map;
17
  fct_map.insert(MapCall::value_type("-status",status));
18
  fct_map.insert(MapCall::value_type("-reset",reset));
19
  MapCall::const_iterator call;
20

21
  
22
  for(int i =1; i<argc;i++)
23
  {
24
    call = fct_map.find(argv[i]);
25
    if (call != fct_map.end())
26
    {
27
      (*call).second();
28
    }
29
    else
30
      cout << "Unknown call requested" << endl;
31
  }
32
}

Vielen dank für die Inspiration ;)

Grüße Tom
#2001686
Lesenswert?

Klaus Wachtler schrieb:
> Was in C++ auch geht, ist eine
>   std::map< std::string, void(*)() >   meinemap;
> oder so ähnlich, also eine Map, die Strings auf Funktionen mappt.
> Dann geht die Auswahl mit einem schnöden meinemap[meinstring]()

Nein, denn das hätte böse Folgen, wenn jemand einen Paramter übergibt, 
den das Programm nicht kennt. Tom hat das mit der Benutzung von find() 
schon richtig gemacht.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren