Mini Parser verbessern
-
Hi Leute,
mit c++ kenne ich mich noch nicht so gut aus. Da ich es aber für einen Server praktischer finde, will ich so einen auch in C++ schreiben. Das Grundprinzip funkioniert schon, jetzt will ich noch einen Parser schreiben, dass der Server die Befehle auch benutzen kann. Dazu sollen die gesendeten Zeichenketten in 3 Bestandteile zerlegt werden:
- Absender
- Befehl
- Parameter des Befehls
Das habe cih auch gemacht, aber mich würde interessieren, wie ich meinen bisherigen parser code verbessern kann, bzw welche Programmierwerkzeuge/Techniken dafür besser geeignet wären.Hier mein Code
//Den Befehl parsen und Serverrelevante Befehle erfassen char cBufName[10]="\0", cBufCommand[10]="\0", cBufExpression[100]="\0"; int msgPos = 0; int msgPos2; //Parsing //Name parsen msgPos2=0; while(1) { if (msgPos > 300) break; if (buf2[msgPos]==':') { msgPos++; break; } else { cBufName[msgPos2++] = buf2[msgPos++]; } } //Name parsen msgPos2=0; while(1) { if (msgPos > 300) break; if (buf2[msgPos]==':') { msgPos++; break; } else { cBufCommand[msgPos2++] = buf2[msgPos++]; } } //Name parsen msgPos2=0; while(1) { if (msgPos > 300) break; if (buf2[msgPos]==';') { msgPos++; break; } else { cBufExpression[msgPos2++] = buf2[msgPos++]; } } sprintf(buf,"%s schrieb %s mit Parameter %s ",cBufName, cBufCommand, cBufExpression); cout << " original: " << buf2 << endl; cout << " parsed" << buf << endl;
Vielen Dank schonmal für die Hilfe
-
was passiert
- wenn buf2[msgPos] eine \0 null enthält ?
- wenn ein ":" fehlt
wenn ich deine Code richtig sehe geht er über den stringterminator hinaus und kopiert die zufälligen werte in deine Arbeitsbuffer-dann dein Abbruch bei 300, wäre es nicht sinnvoller die Länge von buf2 vorher zu bestimmen un den Abbruich auf diesen Wert zu setzen.
Was passiert wenn
- der erste Doppelpunkt beim 10. Zeichen oder höher erscheint cBufName[10]="\0"
- ditto bei cBufCommand[10]="\0"
- ditto cBufExpression[100]="\0"
- Deine Maximallänge ist 117 Nutzzeichen wieso gehst du bis 300.msgPos2=0; while( msgPos2 < 10) { if (buf2[msgPos]==':') { msgPos++; break; } else { cBufName[msgPos2++] = buf2[msgPos++]; } } if (buf2[msgPos]!=':') { // error handling }
Da du 3 mal dasselbe machst das und daseinzige was sich unterscheidet der Zielstring ist, wäre eine Unterroutine nicht sinnvoller
Ein Beispiel
/***********************************************************************.FA* .FUNCTION [ gets the first part of a string loosing the delimiter ] -------------------------------------------------------------------------- .GROUP [ String ] -------------------------------------------------------------------------- .DESCRIPTION This routine copies all chars from the beginning of the string in to lowout until ist finds the delimiter. the delimiter gets skipped an the rest of the string is moved to in. That means that the first part of the string ist in lowout, the rest of the string is in except the delimiter -------------------------------------------------------------------------- .PARAMETER CHANGED char * in rest of string OUTPUT char * lowout first part of the string, must be long enough to hold the whole contents -------------------------------------------------------------------------- .RETURNVALUE none -------------------------------------------------------------------------- .HISTORY Date Author Comment 14.06.94 PAD/DDT Definition **********************************************************************.HE**/ void substr(char * in, char * lowout,char search) { char *highout; highout=in; while ( ( search != * in ) && ( * in ) ) *lowout++ = *in++; *lowout=0; if (0 != *in)in++; while ( * in ) *highout++= *in++; *highout=0; return; }
Deine ZerlegeRoutine sähe dann so aus
substr(buf2,cBufName,','); substr(buf2,cBufCommand,','); strcpy(cBufExpression,buf2)
Wenn du keine akutes Platproblem hast würde ich nicht jedem Arbeitsbuffer eine spezielle Größe zuweisen, sondern
alle Arbeistsbuffer mit derselben Länge ausstatten#define NORMSTRINGLEN 128 char Buffer[NORMSTRINGLEN +1];// das +1 ist für den Delimiter