[C++] Switch achtige constructie voor strings

Pagina: 1
Acties:
  • 109 views sinds 30-01-2008

  • Aaargh!
  • Registratie: Januari 2000
  • Laatst online: 02-05 09:13

Aaargh!

Bow for me for I am prutser

Topicstarter
Ik ben bezig met een programmaatje en daarin moet je een commando in kunnen geven. Nu wil ik het liefst met een switch achtige constructie werken om te checken welke commando er ingevoerd is. maar een switch werkt niet op strings.

is er een nettere manier om een string met een hoop mogelijkheden te vergelijken behalve een zooi if constructies ?

Those who do not understand Unix are condemned to reinvent it, poorly.


  • Sjaaky
  • Registratie: Oktober 2000
  • Laatst online: 26-05 01:17
Je zou een hashtable kunnen gebruiken.

  • hufkes
  • Registratie: Maart 2000
  • Laatst online: 16:52

hufkes

nee, daar staat niet hufter!

errm, kan switch geen string aan? Ik kan het hier even niet testen, dus ik geloof je maar :)

Wat je wel kunt doen is je case per letter doen, op die manier kun je de commando's keurig nesten.

Dus
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
switch(string[1])
{
 case 'a':
 case 'A':
  switch (string[2])
  {
   case 'd':
   case 'D':
    [commando voor 'Add']
    break;
   case 'l':
   case 'L':
     [command voor 'All']
    break;
   default:
     [invalid command]
  }
 etc
}

Onderstaande signature is al >20jr oud ***hoe dan***
---
Het internet is een veelbelovend medium
....dat maar heel weinig van zijn beloftes nakomt.
Wat weg is... raak je nooit meer kwijt :P


  • Lorn
  • Registratie: Maart 2000
  • Laatst online: 13-01-2025

Lorn

I have a bad feeling...

Ik zou denken dat een hash te prefereren is over een switch per ingevoerde letter. Je moet alleen wel even goed uitdenken hoe om te gaan met eventuele parameters die meegegeven kunnen worden aan de commando's. Je zult ook moeten afvangen of de letters in upper of lower case zijn want anders komt je hash waarde niet overeen.

  • ^Mo^
  • Registratie: Januari 2001
  • Laatst online: 04-11-2025
Op maandag 29 april 2002 00:04 schreef hufkes het volgende:
errm, kan switch geen string aan? Ik kan het hier even niet testen, dus ik geloof je maar :)

Wat je wel kunt doen is je case per letter doen, op die manier kun je de commando's keurig nesten.

Dus
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
switch(string[1])
{
 case 'a':
 case 'A':
  switch (string[2])
  {
   case 'd':
   case 'D':
    [commando voor 'Add']
    break;
   case 'l':
   case 'L':
     [command voor 'All']
    break;
   default:
     [invalid command]
  }
 etc
}
dat komt dus op het zelfde neer als een stringcompare, alleen dan op een minder leesbare manier. Want of je nou zo naar het commando "Add" zoekt, of met stricmp( Input, "Add") .... lijkt me de tweede manier toch iets beter :)

"There are 10 kinds of people in the world, those who understand binary and those who don't" | Werkbak specs


  • hufkes
  • Registratie: Maart 2000
  • Laatst online: 16:52

hufkes

nee, daar staat niet hufter!

* hufkes heeft ook nooit gezegd dat dit slim en efficient was :)
Maar inderdaad, een stringcompare is zeker makkelijker, ik had me alleen even op de switch gegooid...

Onderstaande signature is al >20jr oud ***hoe dan***
---
Het internet is een veelbelovend medium
....dat maar heel weinig van zijn beloftes nakomt.
Wat weg is... raak je nooit meer kwijt :P


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 15:32

.oisyn

Moderator Devschuur®

Demotivational Speaker

je kan natuurlijk ook een arraytje maken met de commando's en pointers naar de functie die moet worden aangeroepen. Dan is het ook redelijk eenvouding om je lijst met commando's uit te breiden

zoiets zeg maar:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
void cmd_bla ()
{
    // ...
}

void cmd_hop ()
{
    // ...
}

void cmd_aars ()
{
    // ...
}



struct command_t
{
    const char * cmd;
    void (*func) ();
};

command_t commands[] =
{
    { "bla", cmd_bla },
    { "hop", cmd_hop },
    { "aars", cmd_aars },
    { NULL, NULL }
};



void execute_command (const char * cmd)
{
    for (int i = 0; commands[i].cmd; i++)
      if (!strcmp (cmd, commands[i].cmd))
        commands[i].func ();
}

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • Aaargh!
  • Registratie: Januari 2000
  • Laatst online: 02-05 09:13

Aaargh!

Bow for me for I am prutser

Topicstarter
Thanks, hiermee kom ik er wel uit :)

Those who do not understand Unix are condemned to reinvent it, poorly.


  • drZymo
  • Registratie: Augustus 2000
  • Laatst online: 12-04 13:01
Der was een tweaker hier met een hele handige constructie daarvoor. Ik zoek het ff op.

Found it:
Op donderdag 06 december 2001 16:57 schreef SpHeaRe het volgende:
Taal : C/C++
Doel : Een switch() op strings
Omschrijving: Visual Basic en C# ondersteunen beide switchen op strings. In C moet je hiervoor strcmp gebruiken. Dit leid al snel tot onduidelijke, geneste if /else if's. Volgende macro's doen in principe hetzelfde, maar zorgen er wel voor dat je code een stuk netter wordt.
code:
code:
1
2
3
4
#define sswitch(a) {char* _p = a; if (0)
#define scase(x) } else if ( !stricmp(_p, x) ) {
#define sdefault } else {
#define sendswitch }

Gebruik:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
char *psz = ...;

sswitch( psz )
{
  scase( "geval1" )
    //  code voor geval 1

  scase( "geval2" )
    //  code voor geval 2

  // etc

  sdefault
    //  default code 
}
sendswitch
uit codebase topic :P

"There are three stages in scientific discovery: first, people deny that it is true; then they deny that it is important; finally they credit the wrong person."


  • tomato
  • Registratie: November 1999
  • Niet online
drZymo: Der was een tweaker hier met een hele handige constructie daarvoor. Ik zoek het ff op.
Oeioeioei, ranzige constructie imho :o

Maar misschien ook omdat ik vrijwel nooit C/C++ gebruik, dus nogal snel walg van precompiler directives (zeker op dit soort manieren)...

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 09-04 22:08
Associatieve array :
code:
1
2
3
4
5
6
7
std::map< string, Commando > ops;

ops["Read"] = &Read;
ops["Write"] = &Write;

int i;
ops["Read"] ( std::cin, i );

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • Aaargh!
  • Registratie: Januari 2000
  • Laatst online: 02-05 09:13

Aaargh!

Bow for me for I am prutser

Topicstarter
Op maandag 29 april 2002 09:26 schreef MSalters het volgende:
Associatieve array :
code:
1
2
3
4
5
6
7
std::map< string, Commando > ops;

ops["Read"] = &Read;
ops["Write"] = &Write;

int i;
ops["Read"] ( std::cin, i );
Thanks, precies wat ik zoek!

Those who do not understand Unix are condemned to reinvent it, poorly.


  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Hmm ik kan dit niet simpel/snel uitleggen, maar, ideaal in dit geval is om een "object factory" te gebruiken, die op basis van strings objecten aanmaakt (of zelfs van istreams, heb je meteen gratis batch files). De objecten die je zo aanmaakt kunnen dan command objecten of functors zijn.

Op deze manier krijg je ontzettend veel flexibiliteit. Switch statements zijn eigenlijk altijd slecht en niet onderhoudbaar...nieuw commando toevoegen is erg lastig.

Een en ander staat in 'design patterns' (gamma et al 1995), vnl onder factory en command. Een goede aanvulling is modern 'C++ design' (alexandrescu 2001)

Als je serieus een shell/command parser op wilt zetten is dit "the way to go"

  • Aaargh!
  • Registratie: Januari 2000
  • Laatst online: 02-05 09:13

Aaargh!

Bow for me for I am prutser

Topicstarter
Op maandag 29 april 2002 15:12 schreef Zoijar het volgende:
Hmm ik kan dit niet simpel/snel uitleggen, maar, ideaal in dit geval is om een "object factory" te gebruiken, die op basis van strings objecten aanmaakt (of zelfs van istreams, heb je meteen gratis batch files). De objecten die je zo aanmaakt kunnen dan command objecten of functors zijn.

Op deze manier krijg je ontzettend veel flexibiliteit. Switch statements zijn eigenlijk altijd slecht en niet onderhoudbaar...nieuw commando toevoegen is erg lastig.

Een en ander staat in 'design patterns' (gamma et al 1995), vnl onder factory en command. Een goede aanvulling is modern 'C++ design' (alexandrescu 2001)

Als je serieus een shell/command parser op wilt zetten is dit "the way to go"
Ik weet wat een factory is, en het boek "Design patterns" staat hier in de kast.
Als ik echt een shell zou willen maken dan zou ik daar een parser generator voor gebruiken, maar dit gaat om een klein tooltje dat niet voor eindgebruikers bedoelt is maar alleen als debugging hulpmiddel.

Ik ben met een opdracht voor school bezig en ik moet een unix style filesystem bouwen. een aantal delen hiervan zijn al af en ik ben nu bezig met een debug tooltje waarmee ik allerlei structuren in het FS kan afdrukken en wijzigen zodat ik de werking van m'n fs kan testen en testcases kan aanmaken (unclean fs met wat fouten erin om de fsck tool te checken b.v.)

Those who do not understand Unix are condemned to reinvent it, poorly.


Verwijderd

ok, ik heb ook nog een vraagje over zoiet:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <iostream.h>
#include <string.h>

using namespace std;

int main(int argc, char *argv[])
 {
 string cnx = "Aap, vowa doede dien test, ge zijt zllf nen CNX-er!";
 string black = "Jaja, ge zijt zo nen looser di da op dn blacklist sta!";
 string nee = "Ge hebt geluk, ge sta (nog) nie op dn blacklist!"; 
 char naam[20];
 char quit;
 
 cout << "Welkom op de 'blacklistchecker' van de CNX." << endl;
 cout << endl;
 cout << "Gelieve uw naam in te voeren met _ ipv spaties en zonder hoofdletters." << endl;
 cout << "vb.: nicolaas_van_mira" << endl;
 cout << endl;
 cin >> naam;
 quit = '\0';
 
 while (quit != 'q')
   {
   const int arLen = 4; 
   string cnxMensen[arLen] = {"kris_van_den_bergh","yves_goorden","glenn_van_loon","steven_hectors"}; 
   const int arDen = 7;
   string blackList[arDen] = {"kate_uytterlinde","jan_harrewijn","lander_de_bruyn","fraa_cox","marleen_hermans","kathy_elsen","julie_de_ruyter"};
   const int arBen = 1;
   string erDoor[arBen] = {"kris_door_de_muur"};
 
   if (erin(cnxMensen, arLen, naam)) 
     cout << cnx << endl;
   else if (erin(blackList, arDen, naam))
     cout << black << endl;
   else if (erin(erDoor, arBen, naam))
     cout << "owned!" << endl;
   else
     cout << nee << endl;
   
   cout << endl;
   cout << "Duw q om af te sluiten." << endl;
   cin >> quit;
   }
 return(0);
 }


dit is mijn script, maar ik snap eigenlijk niet goed hoe ik die erin moet declareren :(
dit script dient eigenlijk gewoon om te checken of je op de blacklist van onze clan staat

  • whoami
  • Registratie: December 2000
  • Laatst online: 23:03
Switch statements heb je in C++ afaik niet voor string-types.

En wat snap je niet? Wat wil je erin implementeren en wat lukt er niet?

Trouwens, je opent beter een nieuw topic dan dat je een oud topic omhoogkicked als je niet verder geraakt met de info die je in dat oud topic vindt. (Zie ook hier: Recyclen van topics: ja of nee?)

https://fgheysels.github.io/


Verwijderd

whoami schreef op 23 november 2003 @ 21:56:
En wat snap je niet? Wat wil je erin implementeren en wat lukt er niet?
die erin is de bedoeling dat het een bool wordt die zegt ofdat die string dan waar of vals is en als hij dan waar is moet hij die if doen ...
whoami schreef op 23 november 2003 @ 21:56:
Trouwens, je opent beter een nieuw topic dan dat je een oud topic omhoogkicked als je niet verder geraakt met de info die je in dat oud topic vindt.
ik had een nieuw topic geopend, maar dat hebben ze gesloten omdat dit topic er al ongeveer over ging dus... :/

  • whoami
  • Registratie: December 2000
  • Laatst online: 23:03
Verwijderd schreef op 23 november 2003 @ 21:59:
[...]


die erin is de bedoeling dat het een bool wordt die zegt ofdat die string dan waar of vals is en als hij dan waar is moet hij die if doen ...
:?
Ik snap er niets van wat je nu wilt zeggen. Zorg eens voor duidelijke zinnen en een goeie structuur.
ik had een nieuw topic geopend, maar dat hebben ze gesloten omdat dit topic er al ongeveer over ging dus... :/
Euh, ja, met een reden dus:
[rml]curry684 in "[ C++] tekenreeks als case in een switchi..."[/rml]

https://fgheysels.github.io/


Verwijderd

ok, dus, in mijn script hierboven staat dus:

C++:
1
2
3
4
5
6
const int arLen = 4; 
string cnxMensen[arLen] = {"kris_van_den_bergh","yves_goorden", 
     "glenn_van_loon","steven_hectors"}; 

if (erin(cnxMensen, arLen, naam)) 
     cout << cnx << endl;


en daarin staat dus erin, maar dat moet ik nog declareren, en dat moet zoals:

C++:
1
2
3
4
5
6
7
8
9
bool erin(string haystack[], int stackLen, string needle) 
{ 
     for (int i = 0; i < stackLen; i++) 
     { 
          if (haystack[i] == needle) 
               return true; 
     } 
     return false; 
}


maar ik snap niet goed hoe ik dat dan mag doen en of die erin dan maar 1 keer kan gebruikt worden en dat ik dan nog zo een andere moet maken voor de 2 andere gevallen

  • whoami
  • Registratie: December 2000
  • Laatst online: 23:03
Dit topic was toch dicht?

https://fgheysels.github.io/


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 15:32

.oisyn

Moderator Devschuur®

Demotivational Speaker

bReEzAh: check je mail over 10 minuten

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.

Pagina: 1

Dit topic is gesloten.