String in verschiedene Begriffe aufspalten
-
-
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 ...
-
Wenn du die STL nicht benutzt geht es auch noch schneller.
string Dispatch_String(string &source,char sep,int pos) { int prv=0,i=-1; while(pos) { i++; if (source[i]==sep) { pos--; if(pos) prv=i+1; } } return source.substr(prv,i-prv); }
Ist das für dich übersichtlicher ?
-
Ist das für dich übersichtlicher ?
Ja.
Wenn du die STL nicht benutzt geht es auch noch schneller.
Vermutest du das, oder hast du das getestet? Ist der Geschwindigkeitsvorteil überhaupt relevant?
1.An welcher Stelle sollen diese 3 Zeilen unübersichtlich sein ?
int x=-1; <- Was das soll, ist mir nicht wirklich klar
2.Läuft absolut fehlerfrei
Mit fehleranfällig mein ich nicht, dass der Code fehlerhaft läuft, sondern dass man nicht erkennen kann, was er tut. Wenn man das debuggen muss, ist es mit Sicherheit komplizierter, als die Lösung mit den Stringstreams.
3.Intuitiv.Übung macht den Meister ...
Man kann sich das Leben auch selber schwer machen...
Solange dein Code funktioniert, der Benutzer weiss, was er tut, Geschwidingkeit von enormer Bedeutung ist und der Geschwindigkeitsvorteil (falls vorhanden) auch enorm ist, kann man das mit Sicherheit benutzen. Dein Code gibt aber auch nur den Teil bis zum ersten Trennzeichen zurück. Was ist mit den Teilen danach?
-
Mit fehleranfällig mein ich nicht, dass der Code fehlerhaft läuft, sondern dass man nicht erkennen kann, was er tut. Wenn man das debuggen muss, ist es mit Sicherheit komplizierter, als die Lösung mit den Stringstreams.
while(pos--) x=source.find(sep,x)+1;
Solange pos nicht 0 ist setze in x die Position des gefundenen (ab Position x suchen) ',' Trennzeichens + 1.
Vermutest du das, oder hast du das getestet? Ist der Geschwindigkeitsvorteil überhaupt relevant?
Getestet.
Wenn du ständig etwas längere strings auslesen musst (ca 2 MB) und veränderungen der empfangenen strings im Bereich von ms liegen ist Geschwindigkeit immer von Vorteil.Dein Code gibt aber auch nur den Teil bis zum ersten Trennzeichen zurück. Was ist mit den Teilen danach?
Wenn du der Funktion in pos den Wert 2,3,4 usw übergibst bekommst du auch die anderen Teilstrings.
Man kann sich das Leben auch selber schwer machen...
Schwer finde ich diesen Code wirklich nicht.Eine Implementation auch nicht.