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
    

Anmelden zum Antworten