pl: Zeichenketten, Arrays mit Zeichen in c dynamisch füllen

Sozusagen ein push. Problem: Die Anzahl der Zeichen die da kommen ist zum Zeitpukt der Deklaration des Datentyps nicht bekannt.

Lösung: Einen Pointer deklarieren, später für die Zeichenkette Stück für Stück neuen Speicher anfordern und die anzufügenden Zeichen da reinkopieren.

Nun, ich komme da einfach nicht weiter, kann mir da mal jemand auf die Sprünge helfen?

MfG

  1. Den entscheidenden Schritt sehe ich so.

    • Bisherigen Pointer merken.
    • Neuen größeren Speicherbereich anfordern.
    • Daten vom alten in den neuen Speicher kopieren.
    • alten Speicher freigeben.

    Beim durchdenken stellt man beim kopieren fest dass man den bisherigen Pointer noch braucht, nachdem man den neuen Speicherbereich angelegt hat.

    Damit du weißt wie viele Zeichen schon belegt sind und wo du weiter anfügen kannst, musst du natürlich die Länge des Strings merken. Und die verfügbare Maximalgröße.

    Manche Sprachen die Strings kennen reservieren sich beim vergrößern gleich mehr Speicher als aktuell nötig. Damit kannst du dir ständiges umkopieren sparen.
    Was sagt deine Suchmaschine zu "c string implementation"? Ich sehe die Chance etwas fertiges zu finden das du entweder direkt einsetzen kannst, oder du kannst dir relevante Teile abschauen.

  2. Hallo,

    kann es sein, das du realloc suchst?

    Gruß
    Jürgen

    1. problematische Seite

      Hi Jürgen,

      kann es sein, das du realloc suchst?

      Des isses!!! Danke Dir!

      Und natürlich auch Danke an die Anderen hier!

      Worums geht is klar ne 😉

      Konkret gehts um den Parser, Enctype vorerst application/x-www-form-urlencoded und da die Parameter prozentkodiert sind, gibts Verschnitt. Dh. wenn für %E2%82%AC (Eurozeichen) Speicher allociert wird, werden für die Verarbeitung letztendlich nur 3 Bytes benötigt.

      Mein Perl Framework in c, echt der Hammer, läuft auf meiner alten Kiste 10x schneller als in Perl.

      Schönen Sonntag!

      1. problematische Seite

        Moin pl,

        für den Anwendungsfall,

        Konkret gehts um den Parser, Enctype vorerst application/x-www-form-urlencoded und da die Parameter prozentkodiert sind, gibts Verschnitt. Dh. wenn für %E2%82%AC (Eurozeichen) Speicher allociert wird, werden für die Verarbeitung letztendlich nur 3 Bytes benötigt.

        könntest du theoretisch ganz konservativ auch einfach genau so viel Speicher belegen, wie der Prozent-kodierte String hat, da dessen Länge ja größer bzw. gleich der Länge des Zielstrings ist. Wie viele NULL-Bytes am Ende eines Strings stehen, wenn der Zielstring kürzer ist, macht dem späteren free nichts aus.

        Viele Grüße
        Robert

        1. problematische Seite

          hii @Robert B.

          für den Anwendungsfall,

          Konkret gehts um den Parser, Enctype vorerst application/x-www-form-urlencoded und da die Parameter prozentkodiert sind, gibts Verschnitt. Dh. wenn für %E2%82%AC (Eurozeichen) Speicher allociert wird, werden für die Verarbeitung letztendlich nur 3 Bytes benötigt.

          könntest du theoretisch ganz konservativ auch einfach genau so viel Speicher belegen, wie der Prozent-kodierte String hat, da dessen Länge ja größer bzw. gleich der Länge des Zielstrings ist.

          Genau das macht mein Parser. Genauer gesagt, wird zum Reservieren die Länge des ganzen Paar name=value genommen. Was auch nicht weiter tragisch ist, weil name i.d.R. kurz gehalten wird. Da kommt es auf ein paar Bytes mehr oder weniger auch nicht an. Von daher kann für name eine feste Länge vorgegeben werden, z.B. [32] und für value eben alles zusammen.

          Wie viele NULL-Bytes am Ende eines Strings stehen, wenn der Zielstring kürzer ist, macht dem späteren free nichts aus.

          Ja, das free muß ich noch einbauen. Zumindest kann der Speicher für den prozentkodierten String nach dem decode wieder freigegeben werden.

          MfG

      2. problematische Seite

        Hallo pl,

        Vorsicht. realloc kann den Speicherbereich an eine andere Stelle verlegen. Gespeicherte Pointer darauf werden dadurch ungültig.

        Es wäre sinnvoll, relozierbare Strings durch ein Handle zu repräsentieren, hinter dem eine struct mit Länge und Zeiger auf den eigentlichen String steckt. Dein Code operiert nur mit dem Handle, und Manipulationen sind nur von dafür gemachten Funktionen zulässig. Kannst du in C nicht gut forcieren, aber beim Programmieren drauf achten.

        Rolf

        --
        sumpsi - posui - clusi
        1. problematische Seite

          hi @Rolf B

          ich werd mal damit spielen. c ist bekanntlich sehr pragmatisch was den Umgang mit Speicher betrifft. Die erste gute Übung beim Umsetzen meines FW von Perl nach c war das Einlesen der Binary auf eine verkettete Liste. Gute Übung deswegen weil ich dabei wieder lerne wie c tickt und warum es überhaupt numerische Datentypen gibt: Wegen der exakten Anzahl der Bytes!

          Und so liegt in c eine Binary genauso im Hauptspeicher wie sie in einer Datei eingefroren ist, nur daß da eben noch die Symboltabelle dazu ins Spiel kommt was den random Access ermöglicht.

          Aus diesem Grund eignet sich c ausgzeichnet zum Verarbeiten von Binärsequenzen. Beim Entwickeln meines CGI Parsers musste ich mal wieder feststellen wie grottig+schrottig der Enctype application/x-www-form-urlencoded ist und für die Anderen wie JSON, XML, multipart/form-data trifft dasselbe zu.

          Formulardaten als proprietären Enctype binary/name+value zu verarbeiten ist da viel effizienter, der wird ganz einfach sequentiell aus stdin gelesen und einen solchen Enctype mit modernen JS zu erzeugen ist auch seit Jahren möglich. Fileuploads inbegriffen, serverseitig steht der Dateiinhalt in value und zwar ohne vorher den Server zu vergewaltigen oder mit temporären Dateien vollzumüllen.

          Plan für heute, danach das Array 😉 (realloc oder memcpy)

          MfG

          1. problematische Seite

            Hallo pl,

            grottig+schrottig der Enctype application/x-www-form-urlencoded

            Du musst bedenken, wann und wofür das gemacht wurde. ASCII Zeichen 0x20 bis 0x7f sind so ziemlich die einzige Codierung, die auf jeder Maschine verstanden wird und die sich halbwegs sicher in andere Codierungen übersetzen lässt. Diese Dinge stammen aus den 70ern, teilweise vermutlich sogar aus den 60ern.

            Rolf

            --
            sumpsi - posui - clusi
            1. problematische Seite

              hi @Rolf B

              grottig+schrottig der Enctype application/x-www-form-urlencoded

              Du musst bedenken, wann und wofür das gemacht wurde. ASCII Zeichen 0x20 bis 0x7f sind so ziemlich die einzige Codierung, die auf jeder Maschine verstanden wird und die sich halbwegs sicher in andere Codierungen übersetzen lässt. Diese Dinge stammen aus den 70ern, teilweise vermutlich sogar aus den 60ern.

              Das kann ich nicht nachvollziehen. Die Prozentkodierung für obenstehenden Enctype hat nämlich mit der Zeichenkodierung gar nichts zu tun weil nicht die Zeichen sondern die Bytes prozentkodiert werden. Beispiel Eurozeichen %E2%82%AC in UTF-8

              Decode stellt daraus die Bytes wieder her und denen ist es egal was sie darstellen. Genauso wie einem jeden Parser die Zeichenkodierung völlig Wurst ist, weil Parser bytesemantisch arbeiten. Und eine Bytesequenz aus STDIN lesen geht seit Kerninghan+Richie c entwickelt haben.

              Mein neuer Enctype funktioniert auf Byteebene und das einwandfrei und weit weniger umständlich als ein Parser für obenstehenden Enctype. Einzig die Bowser sind es die mal wieder der Zeit völlig hinterherhinken.

              MfG

        2. problematische Seite

          hi @Rolf B

          danke für Deine Hinweise. Hier mal ein typischer Fehler:

           // betrifft: Templatedatei
           filecontent = (char*)malloc(filesize);
          

          Das Übliche: Terminierung vergessen. Das Tückische: Der Fehler wird nicht gleich bemerkt! Hat mich 3 Tage gekostet, der Fehler trat sporadisch auf, das P ist einfach abgeschmiert, rein zufällig bei bestimmten GET oder POST Parametern.

          Als ich das Formular um AJAX erweitert habe, wunderte ich mich, daß bei denselben Parametern kein Absturz erfolgte. Das hat mich dann dahin geführt wo es passiert, Lösung: mit malloc(filesize +1) den Platz für die Nullterminierung anfordern und den String terminieren.

          Läuft wie geschmiert jetzt 😉

          Was ich am FW in c anders mache als im Perl-FW: Ausgaben gehen gleich raus auf stdout. In Perl hingehen hab ich das alles erst gepuffert.. nun Beides hat seine Vor und Nachteile. Die Arbeitsweise der Templatemachine ctemplate läßt jedoch gar keine andere Arbeitsweise zu, letztendlich führt es grundsätzlich zu einem Transfer-Encoding: chunked.

          Der Vorteil in c: Ich kann mit fwrite() arbeiten und Binärdaten ausgeben. Interessant für AJAX, einen JSON direkt auf stdout auszugeben geht natürlisch auch.

          Schluß für Heute 😉

  3. Moin pl,

    mit C++ lässt sich aus deinem Problem …

    Die Anzahl der Zeichen die da kommen ist zum Zeitpukt der Deklaration des Datentyps nicht bekannt.

    … eines der Standardbibliothek machen:

    #include <sstream>
    
    std::ostringstream puffer;
    
    while (/* immer wieder neue Daten */) {
        puffer << daten;
    }
    
    // Abschließend:
    std::string pufferInhalt(puffer.str());
    

    Viele Grüße
    Robert

    1. Hallo,

      mit C++ lässt sich aus deinem Problem …

      Du darfst doch auf eine c-Frage nicht mit cpp antworten!

      Das wäre ja so ungefähr, als ob jemand auf ne perl-Frage mit PHP antwortete…

      Scnr

      Gruß
      Kalk

      1. Moin,

        ein standardkonformer C++-Compiler kann auch C fehlerfrei und ordnungsgemäß kompilieren.

        Viele Grüße
        Robert

    2. hi @Robert B.

      c++ kommt auch noch dran. Das eigentlich Interessante ist, beim Bau meines FW in veschiedenen PLs sehe ich immer wieder mal Fehler die ich in den anderen PLs gemacht habe.

      Schönen Sonntag!

      1. Moin pl,

        c++ kommt auch noch dran. Das eigentlich Interessante ist, beim Bau meines FW in veschiedenen PLs sehe ich immer wieder mal Fehler die ich in den anderen PLs gemacht habe.

        na dann weiterhin viel Spaß daran und wenn Fragen sind, immer gerne her damit!

        Auch dir einen schönen Sonntag
        Robert

        1. wow danke Dir @Robert B.

          Im Grunde genommen ist mein FW ja objektorientiert: Routingtable und Konfiguration sind als Objekte in einer Binary eingefroren. EAV ist das Muster der Struktur, Entity ist z.B. /index.html, class wäre ein Attribut und Public::Class::Name der Value dazu. In c spielt zwar das Attribut class keine Rolle, aber es gibt ja weitere Eigenschaften wie title und descr. Und ggf. ein Dateiname fürs Template.

          Natürlich können diese Eigenschaften auch !OOP verarbeitet werden, denn für den wahlfreien Zugriff (Random Access) liegt ja alles griffbereit im Hauptspeicher.

          So hat die main in c nur ganze 20 Zeilen, das ist das eigentliche FW, also der Kern. In Perl ist das nicht viel anders, nur daß mit OOP der ganze Code besser organisiert werden kann.

          Mal sehen, was sich in c++ da machen lässt. Ismir auf jeden Fall 1000x lieber als Java, aber in Java ist mein FW sicher auch machbar, davon bin ich überzeugt.

          Jetzt vollende ich erstmal den Parser, das Array für mehrere gleichnamige Parameter ist noch offen. Ansonsten funktioniert der Parser einwandfrei für den Default Enctype in POST und GET 😉

          omit ich mich ganz bestimmt nicht mehr befassen werde ist der Enctype multipart/form-data, für den habe ich längst einen bessere Ersatz und die clientseitigen JS Libraries dazu. Dieser neue Enctype heißt multipart/slice-data hier beschrieben. Und der ist auch in c total einfach zu parsen.

          MfG