none
Parsen, Algorithmus RRS feed

  • Frage

  • Hallo,

    wie könnte ich folgendes gut testen?

    String = char(2) + "20100816-003320001" + char(3) + char(2) + "20100816-003320002" + char(3) + char(2) + "20100816-003320003" + char(3) +char(2) + "20100816-003320004" + char(3) +char(2) + "20100816-003320005" + char(3)

    a) Wie bekomme ich das jetzt in einen Buffer rein? strcpy ?

    b) ich muss die ID's herausfiltern, wie? Evtl. Reg.Ex?

    c) es kann sein dass die Struktur fehlerhaft ist.

    String = char(2) + "20100816-003320001" + char(3) + char(2) + "20100816-003320002" + char(3) + char(2) + "20100816-003320003" + char(3) +char(2) + "20100816-003320

    Als es fehlt das letzte char(3), sollte dann zu keinem Fehler führen, TRACE Ausgabe halt. Hinweis.

    Ich verwende VS2008, C++,MFC

    string value = GetIDFromPos( int pos )

    string value = GetIDLastValid(  ) // Also falls eine fehlerhafte drin ist.

    Grüße Andreas

     

     

     

    Montag, 16. August 2010 07:19

Antworten

  • Lieber Andreas,

    hier mal ein minimalbeispiel (die meisten Headerdateien brauchste nicht):

    Du must nur die \002 am anfang halt parsen und dann entfernen.

    Minimalbeispiel:

    #include "Windows.h"
    #include <cstdio>
    #include "cstringt.h"
    #include "atlstr.h"
    #include <cstring>
    #include <iostream>
    
    void main(void)
    {
    	char teststring[]="\00220100816-003320001\003\00220100816-003320002\003\002";
    	CString cteststring=teststring;
    	CString restoken;
    	int currpos=0;
    	restoken=cteststring.Tokenize("\002\003",currpos);
    	while(restoken!= "")
    	{
    		std::cout << restoken<<std::endl;
    		restoken=cteststring.Tokenize("\002\003",currpos);
    	}
    
    
    }
    
    
    Das zeigtt kurz und knapp wie es läuft.

    Donnerstag, 19. August 2010 10:17

Alle Antworten

  • Lieber Andreas,

    eine meiner schlimmsten Fragen in der Schulzeit war: "Was will der Autor mir damit sagen????" und da fühle ich mich auch an dich errinnert.

    Wenn du dein Problem ein bisschen Ausführlicher beschreibst kann man dir auch helfen ;-)...

    also zu b) Ja mit Regex  kann man wunderbar "Strukturen" aus einem string herausfiltern.

    Wenn du aber eine Konkenation aus verschiedenen ID´s hast, die z.b. alle mit einem , getrennt sind geht es aber noch deutlich schneller in dem du z.b. mit Hilfe von find und substr arbeitest:

    Minimalbeispiel:

     

    
    
    // string::find
    
    
    
    
    
    
    
    #include <iostream>
    #include <string>
    using namespace std;
    
    int main (void)
    {
    	string parsedvalue[3];
    	string test="1234-567,1234-568,1234-569,";
    	size_t startpos=0,currentpos=0;
    	int i=0;
    	currentpos=test.find(",",startpos);
    	while (currentpos!=string::npos)
    	{
    		parsedvalue[i]=test.substr(startpos,8);
    		startpos=currentpos+1;
    		i++;
    		currentpos=test.find("," ,startpos);
    	}
    return 0;
    }
    

     

    Wenn du die MFC benutzt ist aber vielleicht auch dies http://msdn.microsoft.com/en-US/library/k4ftfkd2%28v=VS.80%29.aspx ganz hilfreich.

    RegEx ist sehr mächtig aber auch sehr langsam....

    • Bearbeitet Brian Dahl Dienstag, 17. August 2010 20:00
    Montag, 16. August 2010 08:46
  • Hallo Brian,

    String = char(2) + "20100816-003320001" + char(3) + char(2) + "20100816-003320002" + char(3) + char(2) + "20100816-003320003" + char(3) +char(2) + "20100816-003320004" + char(3) +char(2) + "20100816-003320005" + char(3)

    Es ist kein Komma möglich!

    Ein 1D-Barcodescanner liest einen Inhalt ein, dieser ist umrahmt mit Ascii 2 und 3 (also STX, ETX)

    Ich möchte das zunächst mal suimulieren,was später im seriellen Buffer drin liegt. Ich hoffe das Problem ist ist rüber gekommen. Dabei kann sein, dass der Scanner mehrere 1 D Codes liest, der letzte soll dann der Richtige sein. Nichts desto trotz, wäre das hilfeich. Danke im Voraus.

    Grüße Andreas

    ·         string value = GetIDFromPos( int pos )

    ·         string value = GetIDLastValid(  ) // Also falls eine fehlerhafte drin ist.

     

    Montag, 16. August 2010 10:20
  • Lieber Andreas,

    es muss ja auch kein Komma sein.

    Schau dir mal die beschreibung von string::find an z.b. http://www.cplusplus.com/reference/string/string/find/ , ansonsten ist das tokenizen genau das was du brauchst http://msdn.microsoft.com/en-US/library/k4ftfkd2%28v=VS.80%29.aspx .

    Ansonsten macht mein minimalbeispiel eigentlich vom grundsatz her das was du willst nämlich das aufspalten eines strings nach einem bestimmten delimeter...

    Dienstag, 17. August 2010 19:56
  • Hallo Brian,

    ja ok, wobei ich halt ein Startzeichen und ein Endezeichen habe.

      ..> String = char(2) + "20100816-003320001" + char(3) + char(2) +...

    Ich möchte das zunächst mal simulieren,was später im seriellen Buffer drin liegt.

    Wärs dann sinnvoller, ich kopiere den CString (MFC) in ein Buffer rein? strcpy?

    Danke.

    Grüße Andreas

    Donnerstag, 19. August 2010 07:23
  • Hallo Andreas!

    Wärs dann sinnvoller, ich kopiere den CString (MFC) in ein Buffer rein?
    strcpy?

    Du kannst einen char Array direkt einen CString zuweisen!


    Martin Richter -- MVP for VC++ [Germany] -- http://blog.m-ri.de
    Donnerstag, 19. August 2010 09:28
    Moderator
  • Lieber Andreas,

    hier mal ein minimalbeispiel (die meisten Headerdateien brauchste nicht):

    Du must nur die \002 am anfang halt parsen und dann entfernen.

    Minimalbeispiel:

    #include "Windows.h"
    #include <cstdio>
    #include "cstringt.h"
    #include "atlstr.h"
    #include <cstring>
    #include <iostream>
    
    void main(void)
    {
    	char teststring[]="\00220100816-003320001\003\00220100816-003320002\003\002";
    	CString cteststring=teststring;
    	CString restoken;
    	int currpos=0;
    	restoken=cteststring.Tokenize("\002\003",currpos);
    	while(restoken!= "")
    	{
    		std::cout << restoken<<std::endl;
    		restoken=cteststring.Tokenize("\002\003",currpos);
    	}
    
    
    }
    
    
    Das zeigtt kurz und knapp wie es läuft.

    Donnerstag, 19. August 2010 10:17
  • Der Algortihmus arbeitet so nicht korrekt.
    Der Abschluß ist immer nur eine \003! Keine \002\003.
    Ich würde einfach immer die nächste \003 suchen und kontrollieren ob der führende String ene \002 hat, wenn ja diese entfernen.

    Wenn nicht haben wir einen Protokollfehler.


    Martin Richter -- MVP for VC++ [Germany] -- http://blog.m-ri.de
    Donnerstag, 19. August 2010 10:31
    Moderator
  • achso ich hatte das übersehen das nur mit 003 endet, ich habe aber ein merkwürdiges verhalten entdeckt.

    Bei mir parst VC 2010 einfach die erste 002 weg. kann mir jemand sagen wieso????

    Donnerstag, 19. August 2010 20:54
  • achso ich hatte das übersehen das nur mit 003 endet, ich habe aber ein merkwürdiges verhalten entdeckt.

    Bei mir parst VC 2010 einfach die erste 002 weg. kann mir jemand sagen wieso????


    Hallo Brian,

    ich verwende noch VS2008.

    Kompiliere doch mal in VS2008, danach in VS2010.

     

    @Martin, Du?

    Grüße Andreas

    Sonntag, 22. August 2010 18:36
  • ich verwende noch VS2008.

    Kompiliere doch mal in VS2008, danach in VS2010.

    Ich habe mich vielleicht nicht klar ausgedrückt.
    Tokenize verwendet eine Liste von Trennzeichen. Ihm ist es egal wie die Trennzeichen ankommen.
    Das Protokoll dieses Gerätes packt aber den String zwischen ein \002 und \003.
    Wenn man also einen Parser entwickelt, dann sollte man auch den Syntax des Protokolls berücksichtigen um Fehler zu vermeiden.
    D.h.: Jeder String beginnt mit einem \002 und endet mit \003. Einzig gültiges Folgezeichen wieder ein \002!

    Sicher ist das mehr Aufwand aber in meinen Augen der einzige richtige Weg.

    @Martin, Du?

    Was meinst Du damit?


    Martin Richter -- MVP for VC++ [Germany] -- http://blog.m-ri.de
    Montag, 23. August 2010 06:40
    Moderator
  • @Martin, Du?

    Was meinst Du damit?



    Hallo Martin,

    >Bei mir parst VC 2010 einfach die erste 002 weg. kann mir jemand sagen wieso????

     die Frage von Brian. Du hast am meisten Erfahrung denke ich. Wie würdest du das dann konkret sauber machen? Wenn du halt willst.

    a) unter VS2008

    b) unter VS2010

    Grüße Andreas

    Montag, 23. August 2010 09:25
  • Bei mir parst VC 2010 einfach die erste 002 weg. kann mir jemand sagen wieso????

      die Frage von Brian. Du hast am meisten Erfahrung denke ich. Wie würdest
    du das dann konkret sauber machen? Wenn du halt willst.

    Ich habe VC-2005 und VC-2010 verglichen und keinen Unterschied festgestellt.
    Beide verhalten sich gemäß Doku!

    [quote]
    The Tokenize function finds the next token in the target string. The set of characters in pszTokens specifies possible delimiters of the token to be found. [b]On each call to Tokenize the function starts at iStart, skips leading delimiters[/b], and returns a CStringT object containing the current token, which is the string of characters up to the next delimiter character.
    [/quote]

    a) unter VS2008
    b) unter VS2010

    Beide verhalten sich bzgl. Tokenize gleich.

    Ansonsten habe ich das geschrieben wie ich es machen würde... Ich würde den Parser so schreiben, dass er sich an das Protokoll hält... ;)

    BTW: Ich erledige ungern die Arbeit anderer, denn es kostet meine Zeit! Zudem glaube ich, dass Du selbst mehr lernst, wenn Du Deine Versuche selbst verbesserst und zur Diskussion stellst.


    Martin Richter -- MVP for VC++ [Germany] -- http://blog.m-ri.de
    Montag, 23. August 2010 10:01
    Moderator