String in verschiedene Begriffe aufspalten



  • Hallo!

    Ich habe ein Programm geschrieben das als Server arbeitet und von Robotern eine kurze Mitteilung bekommt wenn sie einen Defekt haben. Die Nachricht wird als string geschickt und empfangen und hat folgenden Aufbau:

    "Robotername,Uhrzeit,Ort"

    Nun weiß ich ja nicht wie lang die einzelnen Begriffe sind, nur das sie durch ein Komma getrennt werden. Jetzt hab ich mir überlegt das ich den string in einem Char[] speicher und dann versuche nach dem ',' zu suchen, dass habe ich bis jetzt:

    const int ARRAY_GROESSE = 15;
    
    void Dispatch_String(char begriff[], char roboter[], char zeit[], char ort[])
    {
     for(int i=0; i<=ARRAY_GROESSE; i++)
      {
      if(begriff[i] == ',')
        {
          for(int j=0; j<=i; j++)
            {
              roboter[j]=begriff[j];
            }
            roboter[i]='\0';
        }
      }
    }
    
    int main(int argc, char *argv[])
    {
    
      char roboter[ARRAY_GROESSE];
      char zeit[ARRAY_GROESSE];
      char ort[ARRAY_GROESSE];
    
      char begriff[] = "RA-OL17,14:35:15,Halle 3";
    
      Dispatch_String(begriff, roboter, zeit, ort);
      cout<<roboter;
     return(0);
    }
    

    Nur wie komme ich an die anderen Begriff? Den Ansatz hab ich ja schonmal 😃 Oder würdet ihr es ganz anders lösen?



  • nimm doch std::string, da gibts ne split methode. oder du machst ne "state machine" z.B. so:

    int pos = 0;
    int i = 0;
    char buf[124];
    int t = 0;
    while (i != ARRAY_GROESSE)
    {
        if (begriff[i] == ',')
            pos = 1;
    
        if (pos == 0)
        {
            buf[t] = begriff[i];
            ++t;
        }
        else if (pos == 1)
        {
            buf[t+1] = '\0';
            pos = 0;
            t = 0;
        }
         ++i;
    }
    


  • Hast du mehr Informationen zum string splitting? suche gerade in der msdn finde aber nichts passendes





  • Ich glaube dieses stringsplit kann viel viel mehr als ich eigentlich will.
    Da reinzufuchsen dauert mir ehrlich gesagt zu lange, gibt es niemanden der schon einmal das gleiche / ein ähnliches Problem hatte?

    Ich hab jetzt schon verschiedene Sachen ausprobiert aber die Ergebnisse gefallen mir nicht, hier meine momentane Lösung:

    #include <iostream>
    #include <string>
    using namespace std;
    
    const int ARRAY_GROESSE = 30;
    
    // Braucht euch da nicht reinzufuchsen, Erklärung folgt unten
    void Dispatch_String(int pos, char auswahl, char begriff[], char roboter[], char zeit[], char ort[])
    {
     switch(auswahl)
      {
        case 'r':
           for(int i=pos; i<=ARRAY_GROESSE; i++)
               {
                if(begriff[i] == ',')
                  {
                   for(int j=0; j<=i; j++)
                        roboter[j]=begriff[j];
    
                   roboter[i]='\0';
                   pos = i+1;
                   break;
                 }
                }
            Dispatch_String(pos, 'z', begriff, roboter, zeit, ort);
            break;
    
        case 'z':
           for(int i=pos; i<=ARRAY_GROESSE*7; i++)
               {
                if(begriff[i] == ',')
                  {
                   for(int j=0; j<=i-pos; j++)
                        zeit[j] = begriff[j+pos];
    
                   zeit[i-pos]='\0';
                   pos = i+1;
                   break;
                 }
                }
             Dispatch_String(pos, 'o', begriff, roboter, zeit, ort);
             break;
    
        case 'o':
           for(int i=pos; i<=ARRAY_GROESSE*7; i++)
               {
                if(begriff[i] == ' ')
                  {
                   for(int j=0; j<=i-pos; j++)
                        ort[j]=begriff[j+pos];
    
                   ort[i-pos]='\0';
                   break;
                 }
                }break;
      }
    }
    
    int main(int argc, char *argv[])
    {
      // Hier werden die einzelnen Begriffe gespeichert
      char roboter[ARRAY_GROESSE];
      char zeit[ARRAY_GROESSE];
      char ort[ARRAY_GROESSE];
    
      // String wird "empfangen" und zur besseren Verarbeitung in ein chararray kopiert
      string begriff = "RH-OLA115,10:07:34,Fertigungshalle";
      char chararray[100];
      strcpy(chararray, begriff.c_str());
    
      // Meine Funktion sucht nun nach den Kommas(?) und trennt die Begriff
      Dispatch_String(0, 'r', chararray, roboter, zeit, ort);
      cout<<roboter<<endl;
      cout<<zeit<<endl;
      cout<<ort<<endl;
    
     return(0);
    }
    

    Dispatch_String wird rekursiv aufgerufen und dabei wird dann der Buchstabe übergeben der angibt welcher Begriff nun gesucht wird (r=roboter,z=zeit,o=ort) und die aktuelle Position im char array. Na ja, die Loesung klappt schon nicht mehr wenn z.b. im letzten Begriff so etwas wie "Halle 7" auftaucht, da ich dort nach einem ' ' zum abbrechen suche. Allgemein sehr unschön, aber wenn ihr es mal eben kompiliert seht ihr was ich suche.

    Und das gibts doch garantiert schon irgendwo 😉 ?



  • Tipp:
    Ich würde die Funktion "strtok" verwenden, und die Strings in einen Vektor pushen.

    (Ich kann dir momentan leider kein Beispiel geben. Beschäftige dich mal mit der Funktion)



  • Weil bei dir eh bekannt ist wieviele Strings zu parsen sind, könntest du auch ein char* Array mit fixer größe nehmen, statt einem Vektor...



  • Also meine bevorzugte Methode wären stringstreams.

    #include <sstream>
    #include <iostream>
    using namespace std;
    
    int main()
    {
            stringstream wort;
            wort << "RA-OL17,14:35:15,Halle 3" << endl;
    
            string blah;
            while(getline (wort, blah, ','))
                    cout << blah << endl;
    }
    

    Da muss man sich nicht großartig "reinfuchsen", es ist schnell, einfach und übersichtlich.



  • Eleganter geht's glaub ich nicht, CarstenJ 👍 😉



  • string Dispatch_String(string &source,char sep,int pos)
    {
    int x=-1;
    while(pos--) x=source.find(sep,x)+1;
    return source.substr(x,source.find(sep,x)-x);
    }
    


  • Hab trotzdem noch eine Frage dazu 😃

    #include <iostream>
    #include <string>
    #include <sstream>
    using namespace std;
    
    int main(int argc, char *argv[])
    {
      string roboter, zeit, ort;
    
      stringstream begriff;
      begriff<<"RH-OLA115,10:07:34,Fertigungshalle";
    
      while(true)
      {
      getline(begriff,roboter, ',');
      break;
      }
      cout<<roboter;
     return(0);
    }
    

    geht ja wirklich schon elegant einfach, nur wie sag ich ihm das er die zeit nach dem ersten komma findet?



  • Eine Möglichkeit wäre, dass du einen Zähler in die While Schleife einbaust und diesen mit einer if-Abrage überprüfst....

    [edit]
    Satzbau 🙂



  • Vielleicht habe ich mich unglücklich ausgedrückt 🙂
    Wie kann ich angeben das er ab dem ersten bis zum zweiten Komma sucht?

    So wie die Funktion in meinem Code (oben gepostet) steht holt sie nur den ersten Begriff.

    Ich weiß nicht wo ich da ansetzen muss damit er nach dem Komma weitersucht und nicht wieder von vorne 🙂



  • Also ich würde das in einer Klasse oder einer Struktur machen:

    #include <iostream>
    #include <string>
    #include <sstream>
    using namespace std;
    
    struct einheit{
            string roboter;
            string zeit;
            string ort;
    };
    
    int main(int argc, char *argv[])
    {
            stringstream begriff;
            string getrennt;
            int position = 0;
    
            begriff<<"RH-OLA115,10:07:34,Fertigungshalle";
            einheit Einheit;
            while(getline (begriff, getrennt, ',')){
                    Einheit.roboter = getrennt;
                            getline(begriff, getrennt, ',');
                    Einheit.zeit = getrennt;
                            getline(begriff, getrennt, ',');
                    Einheit.ort = getrennt;
            }
            cout << "Einheit: " << Einheit.roboter << endl;
            cout << "Zeit: " << Einheit.zeit << endl;
            cout << "Ort: " << Einheit.ort << endl;
    }
    

    Nur als Denkansatz. Ist mit Sicherheit nicht optimal. Z. B. könnte man mehrere Einheiten in einem Vector speichern, oder die Schleife so basteln, dass beliebig viele Element eingetragen werden können etc......



  • Ja vielen Dank erstmal, es funktioniert einwandfrei 🙂
    Nur ich verstehe noch nicht ganz wie das funktioniert:

    while(getline(begriff, getrennt, ','))
        {
           roboter = getrennt;
           getline(begriff, getrennt, ',');
           zeit = getrennt;
           getline(begriff, getrennt, ',');
           ort = getrennt;
         }
    

    Könntest du evt. beschreiben wie das von statten geht? Ich komm nicht dahinter 😕



  • Im Grunde ist das ja selbsterklärend. Aber frei nach dem Motto "Wenn du was erklären kannst, hast dus auch verstanden" versuch ich mal mein Glück. 🙂

    // Schleife läuft solange, bis das Ende von begriff erreicht ist; 
    // Schreibt den Teil bis zum ersten Komma aus dem sstream "begriff" in den String "getrennt"...
            while(getline (begriff, getrennt, ',')){ 
                    Einheit.roboter = getrennt; // Kopiert den Inhalt von "getrennt" in die Membervariable "roboter" des Objekts "Einheit"
    
                    getline(begriff, getrennt, ','); // Liest bis zum nächsten Komma, überschreibt den alten Inhalt von "getrennt"...
                    Einheit.zeit = getrennt; // Kopiert das zweite Wort in die Membervariable "zeit" des Objekts "Einheit"
    
                    getline(begriff, getrennt, ','); // Liest bis zum nächsten Komma, überschreibt den alten Inhalt von "getrennt"...
                    Einheit.ort = getrennt; // Kopiert das dritte Wort in die Membervariable "ort" des Objekts "Einheit"
    
            }
    

    Ich hoffe, das war verständlich. Wie schon gesagt, wenn du mal Lust hast, kannst du das ja etwas dynamischer machen. Diese Version ist speziell auf dein Problem zugeschnitten, d. h. wenn eine Enheit noch ein zusätzliches Member bekommen würde oder sich die Reihenfolge ändert, müsste der ganze Kram angepasst werden. Aber das nur am Rande. 😃

    Hier noch ein Link:
    www.cppreference.com



  • ahh vielen Dank 🙂 mir war nicht ganz klar wieso er nicht immer wieder das erste wort ausliest, aber jetzt weiß ich bescheid 🙂

    danke!



  • Besser weil um einiges schneller ist sowas:

    string Dispatch_String(string &source,char sep,int pos)
    {
    int x=-1;
    while(pos--) x=source.find(sep,x)+1;
    return source.substr(x,source.find(sep,x)-x);
    }
    


  • Schneller ist nicht unbedigt besser. Dein Code ist unübersichtlich, fehleranfällig und kaum intuitiv zu benutzen.



  • Schneller ist nicht unbedigt besser. Dein Code ist unübersichtlich, fehleranfällig und kaum intuitiv zu benutzen.

    1.An welcher Stelle sollen diese 3 Zeilen unübersichtlich sein ?
    2.Läuft absolut fehlerfrei !
    3.Intuitiv.Übung macht den Meister ... 🙄


Anmelden zum Antworten