C-String unbestimmte Länge



  • Hallo!
    ich mache für mein Programm ein kleine Kommandozeile, nun habe ich das Problem, dass ich in den Befehlen Leerzeichen benötige, also verwende ich fgets. fgets fordert eine bestimmte Länge, nur, ich kann das nicht pauschal angeben: Mal ist die Zeichenkette nur z.B. /?\0 und mal /help\0, also ganz verschieden. Wenn ich z.B. für /help\0 die Zahl 6 für 6 Zeichen nehme, dann findet strcmp zwar /help und alle anderen Befehle mit Zeichenlänge 6, aber /? nicht mehr.

    Code:

    int GetCommand() {
        static char command[103];
        printf("$ > ");
        fgets(command, strlen(command), stdin);
    
        if(!strcmp(command, "/?") || !strcmp(command, "/help"))
            PrintHelp();
    
        if(!strcmp(command, "/exit") || !strcmp(command, "/close"))
            return 1;
    
        if(!strcmp(command, "/n") || !strcmp(command, "/new"))
            printf("%s", command);
    
        return 0;
    }
    

    Ist diese ewige if(!strcmp()erei "elegant"? Gibt es schönere Lösungen, die gleichzeitig mein Problem lösen?



  • Achso, das strlen da war nur ein verzweifelter Versuch, nicht beachten! 😃



  • Mauli schrieb:

    Ist diese ewige if(!strcmp()erei "elegant"? Gibt es schönere Lösungen, die gleichzeitig mein Problem lösen?

    ein array mit char*, das du absuchst z.b. und dann den index zurückgibts. weil's immer zwei kommandos sind, die das gleiche bedeuten, kannst du z.b. den index immer durch 2 teilen, etwa so:

    int find_cmd (char *cmd)
    {
      static char *cmds[] = {"hallo1",  // 0
                             "hallo2",  // auch 0
                             "doof1",   // 1
                             "doof2",   // auch 1
                             "blah1",   // 2
                             "blah2"};  // auch 2
      int s;
      for (s=0; s<sizeof(cmds)/sizeof(*cmds); s++)
      {
        if (strcmp(cmd, cmds[s]) == 0)
          return s/2;
      }
      return -1;  // not found
    }
    


  • > weil's immer zwei kommandos sind, die das gleiche bedeuten, kannst du z.b. den index immer durch 2 teilen, etwa so:

    Und was bringt das? Ich muss ja dem Command irgendwie die jeweilige Funktion zuweisen, was hilft dort ein halber Index der Cmds-Liste?



  • Mauli schrieb:

    Und was bringt das? Ich muss ja dem Command irgendwie die jeweilige Funktion zuweisen, was hilft dort ein halber Index der Cmds-Liste?

    das ersetzt dein: if(!strcmp(command, ...) || !strcmp(command, ...))
    wenn's anders ist, also nur ein string pro kommando, dann natürlich nicht.
    🙂



  • ach hier, so gehts noch einfacher:

    #include <stdio.h>
    #include <string.h>
    
    // funktionen für die kommandos
    void doof (void){puts ("doof");}
    void hallo (void){puts ("hallo");}
    void blah (void){puts ("blah");}
    
    // liste der funktionen und keywords
    struct cmds
    {
      char *name;
      void (*func)(void);
    }cmds[] = 
      {
        "hallo1", hallo,
        "hallo2", hallo,
        "doof1", doof,
        "doof2", doof,
        "blah1", blah,
        "blah2", blah,   // einfach andere kommandos anhaengen
      };
    
    // funktion anhand des namens aufrufen
    void call_cmd (char *cmd)
    {
      int s;
      // suchen...
      for (s=0; s<sizeof(cmds)/sizeof(*cmds); s++)
      {
        // gefunden? --> dann aufrufen
        if (strcmp(cmd, cmds[s].name) == 0)
        {
          cmds[s].func();
        }
      }
    }
    
    // test
    void main ()
    {
      call_cmd ("hallo1");
      call_cmd ("gibts_nicht");
      call_cmd ("blah2");
    }
    

    🙂



  • Das ist eine sehr schöne Lösung, ich bin zu viel C++ gewöhnt, kann kein C. 😃

    Meine Funktion schaut so aus:

    int GetCommand() {
    
        struct CmdTable {
          const char *name;
          void (*func)(void);
        } cmds[] = {
            "/?", PrintHelp,
            "/help", PrintHelp
        };
    
        static char command[103];
        printf("$ > ");
        fgets(command, 3, stdin);
    
        int i;
        for(i = 0; i < sizeof(cmds) / sizeof(*cmds); i++) {
            if(strcmp(command, cmds[i].name) == 0) {
                cmds[i].func();
            }
        }
    
        return 0;
    }
    

    Aber noch wichtiger ist mir: wie kann ich dieses C-String-Problem lösen? Ich habe a) Leerzeichen, die ich haben MUSS und b) ist die Stringlänge verschieden, sodass ich in fgets keine Längenangabe machen kann.



  • ich bin zu viel C++ gewöhnt, kann kein C

    mein reden. c++ verdirbt den character. *grins*

    Mauli schrieb:

    Ich habe a) Leerzeichen, die ich haben MUSS

    wieso muss? und wenn, fgets() liest doch leerzeichen mit ein, oder nicht?
    ausserdem kannst du den string doch nach belieben weiterverarbeiten, leerzeichen hinzufügen, abschneiden, usw.

    Mauli schrieb:

    b) ist die Stringlänge verschieden, sodass ich in fgets keine Längenangabe machen

    mach einfach ein array, das gross genug ist, um den längsten befehl zu fassen. dessen länge und adresse übergibste dann an fgets().
    🙂



  • Mauli schrieb:

    int GetCommand() {
        static char command[103];
        printf("$ > ");
        fgets(command, strlen(command), stdin);
        
        if(!strcmp(command, "/?") || !strcmp(command, "/help"))
            PrintHelp();
            
        if(!strcmp(command, "/exit") || !strcmp(command, "/close"))
            return 1;
            
        if(!strcmp(command, "/n") || !strcmp(command, "/new"))
            printf("%s", command);
            
        return 0;
    }
    

    In Zeile 4 benutzt du strlen, aber command wurde noch nicht initialisiert, d.h. da kann alles mögliche oder auch nix drin stehen. Warum benutzt du nicht sizeof()?


Anmelden zum Antworten