C/C++ Aus XML-String Kommazahlen extrahieren?



  • Ja Dravere, diese Sachen hab ich auch schon woanders gelesen, aber ich möchte gerne Zahlen aus einem Text heraus konvertieren, welcher nicht nur aus Zahlen besteht, sondern auch aus Buchstaben etc. .



  • matze77! Dieses sscan-Ding ist... lass es mich milde ausdrücken: schlecht. 😉 Weil du dich ja damit auf genau diese eine bestimmte XML-Abfolge festlegst. Was ist wenn ein Zahlenwert fehlt? Was ist, wenn ein Value sich dazwischen schiebt? Dann geht mit deinem Konzept garnichts mehr. Und der Sinn von XML ist eigentlich das man flexibel Werte hinterlegt und entsprechend flexibel darauf reagieren können muß. Wenn du einen XML-Parser nimmst, macht er genau das: er liest flexibel ein und du kannst sagen, auf was für Inhalte du gerne reagieren willst.

    Du mußt natürlich den XML-Parser kennenlernen und dich darin einarbeiten, aber danach kannst du jedes XML-Dokument (nicht nur dieses ROBO-Beispiel) mit Leichtigkeit verarbeiten.

    Und damit das ganze schneller geht (das Einarbeiten), ist TinyXML nicht schlecht.



  • Artchi schrieb:

    matze77! Dieses sscan-Ding ist... lass es mich milde ausdrücken: schlecht. 😉 Weil du dich ja damit auf genau diese eine bestimmte XML-Abfolge festlegst. Was ist wenn ein Zahlenwert fehlt? Was ist, wenn ein Value sich dazwischen schiebt? Dann geht mit deinem Konzept garnichts mehr.

    Vielleicht reicht es ja für seinen Zweck. Immerhin besser, als gleich einen ganzen XML-Parser mitzuliefern.

    (Das Problem ist eher, dass %d eben für dezimale Ganzzahlen gedacht ist und nicht für Fließkommazahlen. Aber das ist ja nur ein Beispiel)

    Aber vielleicht wären RegEx ein bisschen praktischer, als ein Aufruf von sscanf.



  • Hey danke Artchi!

    Aber der XML-Rahmen ist absolut fest. Da ändert sich nichts. Der Robo schickt immer den gleichen XML-Rahmen. Nur die Zahlen ändern sich. Was meinst Du nun?



  • Also sscan würde ich pers. garnicht benutzen, weil ich das garnicht kenne. Scheint C zu sein, oder?

    TinyXML ist echt mini. Ist glaub ich auch nur Templates, muß man nicht mal bauen.

    Für Regex braucht man aber auch eine zus. Library, selbst wenn es nur TR1 ist. Oder haste TR1 oder Boost? Irgendwas muß man doch noch haben, kann mir nicht vorstellen, nur mit der Stdlib klar zu kommen. Oder ist das ne Embedded-Anwendung wo man auf jedes Byte achten muß?

    Wenns wirklich immer das gleiche Schema ist, dann kann man doch die Standard-Streams benutzen, oder? Funktionsweise ist ähnlich wie der obige Code, nur das man dann halt ne while-Schleife noch einbaut, und unwichtige Blöcke überspringt und mit der string-Klasse kann man ja unwichtige Infos wie =" und " entfernen, bevor die Zahl endgültig konvertiert wird.

    Möchte aber behaupten, das man bei dem Aufwand evtl. mit nem Parser schneller zum Ergebnis kommt. Aber kann man ja ausprobieren, dann weiß man es selber.

    Spirit wäre auch ne Möglichkeit. Aber auch eine zus. Library. Ich weiß nicht, ich bin halt eher der Typ, der sich lieber eine Library schnappt, wenns dafür was gibt. 😃



  • Joah, ich werd mir mal Boost besorgen und mit den RegExp rumexperimentieren! Danke Artchi!

    Aber die Sache mit sscanf interessiert mich dennoch, weil es sehr schlank und schnell ist, denke ich!



  • Wenn das Format immer fix ist, dann dürfte sscanf reichen. (Was aber nicht heißt, dass du dich nicht mal mit RegEx auseinandersetzen solltest :))

    @Artchi
    Regex sind im TR1 und der ist ja bei neuen Compilern dabei. Aber Boost würde ich auch nicht unbedingt als "extra Library" ansehen 😉



  • matze77 schrieb:

    Aber der XML-Rahmen ist absolut fest. Da ändert sich nichts.

    na denn...

    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>
    
    char *strings (char c)
    {
      static int state;
      static char buff[256];
      static char idx;
    
      switch (state)
      {
        case 0:
        if (c == '\"')
          state = 1;
        break;
    
        case 1:
        if (c == '\"')
        {
          buff[idx] = 0;
          state = 0;
          idx = 0;
          return buff;
        }
        buff[idx++] = c;
        break;
      }  
    
      return 0;
    }
    
    int main(void) 
    {
      char *xml =
        "<Rob TYPE=\"KUKA\">"
        "<RIst X=\"12.6\" Y=\"234.456\" Z=\"645.79\" A=\"2.4\" B=\"456.814\" C=\"65.33\" />"
        "<FTC Fx=\"1.234\" Fy=\"54.75\" Fz=\"345.76\" Mx=\"2346.6\" My=\"\" Mz=\"3546\" />"
        "<Override>90</Override>"
        "<IPOC>123645634563</IPOC>"
        "</Rob>";
    
      while (*xml)
      {
        char *p = strings (*xml++);
        if (p && (isdigit(*p) || *p==0))
        {
          printf ("%f\n", atof(p));
        }
      }     
    }
    

    🙂



  • das da oben: static char idx; ^^
    sollte ein 'int' sein, kein 'char'
    🙂



  • Boah! Danke Erst mal! Das muss ich mir erst mal in aller Ruhe anschauen.

    Aber ... Ich habs eben mal mit Dev-C++ kompiliert und er spuckt mir nur '12.6' aus, naja ok. Nur - der XML-Rahmen enthält ja, wenn empfangen wird, "echte" 🙂 Anfürhungszeichen ("). Im Code wurden diese durch (backslash") ersetzt und dann funktioniert es ja auch einigermaßen.

    Frage: Wird der Backslash automatisch generiert, wenn die Daten vom Netzwerk in den Buffer, Variable geschrieben werden? Ich glaub ja nich, mmmmhh .... Wenn nicht, dann werd ich wohl nich um die RegEx drumrumkommen, oder?



  • die backslashes braucht man nur, wenn man "'s in stringkonstanten im code hat. im speicher sind sie nicht mehr vorhanden.

    char *cp = "12\\34\"56\"";  // <-- im speicher steht dann [b]12\34"56"[/b] die beiden äusseren "'s sind die begrenzungen des string-literals
    

    der code^^ reagiert übrigens auf "'s und nicht auf \'s. funktioniert er unverändert bei dir?
    🙂



  • Nein, ich hab noch char in int umgeschrieben, so wie feuerteufel-Fan es schrieb. Aber dann spuckt er mir auch nur 12.6 aus. Ich finde den Code von ihm ein weinig zu überdimensioniert. Da hab ich selbst mal was probiert ...

    /* sscanf example */
    #include <stdio.h>
    
    int main ()
    {
      char sentence []="<FTC Fx=\"1.234\" Fy=\"54.75\"";
      float x, y;
    
      sscanf (sentence,"<FTC Fx=\"%f\" Fy=\"%f\"",&x, &y);
      printf ("%f, %f\n",x,y);
      getchar();
    
      return 0;
    }
    

    Ausgabe: 1.234000, 54.750000

    Und das ist auch genau was ich erstmal möchte nur das mir die Anführungszeichen in der Quelle (sentence) noch Sorgen machen.

    Also Du meinst, dass was im Spiecher liegt (sentence) sind ganz normale ("). Ich muss nur noch wissen, was genau in sentence drinne steht und dann kann ich mit

    sscanf(sentence, "XML-Rahmen mit Kommazahlen in Anführungszeichen", &x, &y);
    

    die Kommazahlen auslesen, oder? Ich muss nur die Anführungszeichen im XML-Code bei sscanf als (backlash") eingeben und dann liest sscanf die Kommazahlen korrekt aus dem NetzwerkEmpfangspuffer aus, oder?



  • matze77 schrieb:

    Nein, ich hab noch char in int umgeschrieben, so wie feuerteufel-Fan es schrieb. Aber dann spuckt er mir auch nur 12.6 aus.

    du musst nur den 'static char idx;' in 'static int idx;' ändern, dann sollte es gehen. bei mir ist die ausgabe:

    12.600000
    234.456000
    645.790000
    2.400000
    456.814000
    65.330000
    1.234000
    54.750000
    345.760000
    2346.600000
    0.000000
    3546.000000
    

    und von wegen überdimensioniert: eine vollwertiger XML-parser wäre überdimensioniert.
    🙂



  • matze77 schrieb:

    oder? Ich muss nur die Anführungszeichen im XML-Code bei sscanf als (backlash") eingeben und dann liest sscanf die Kommazahlen korrekt aus dem NetzwerkEmpfangspuffer aus, oder?

    stell fragen zu 'sscanf' am besten im ansi-c forum
    🙂



  • Tja, und mit TinyXML wäre es bestimmt nicht schneller gegangen. 😃



  • Habt Dank, Leute!

    Also, der Code von Feuerteufel funktioniert doch einwandfrei! Ich Dämlack hab getchar(); mit in die Schleife genommen, damit das ConsolenFenster offen bleibt, hehe. Deswegen nur ein Wert.

    Nochmal Danke an Feuerteufel!



  • matze77 schrieb:

    Nochmal Danke an Feuerteufel!

    gern geschehen. vergiss aber nicht, dass der code einfach nur strings aus anführungszeichen extrahiert. sollte wider erwarten dein XML doch dynamisch sein, dann nimm bitte einen echten XML parser, z.b expat oder das, was artchi vorgeschlagen hat.
    - und - fehlerteufel bitte.
    🙂


  • Administrator

    matze77 schrieb:

    Verzeihung! Ich meine dann C++. Und wie siehts damit aus?

    Jetzt hast du aber C 😃

    Grüssli



  • Hehe! 😃 Hauptsache irgendwatt!



  • Dravere schrieb:

    Jetzt hast du aber C

    ist doch nicht schlimm. ich wette, der code geht unverändert durch 'nen c++ compiler.
    🙂


Anmelden zum Antworten