Frage zu substr



  • Hallo, schönes WE,
    ich nutze diese Library [1] und frage mich ob meine Funktion substr1() richtig ist:

    #include <stdio.h>
    #include <stdlib.h>
    
    #include <iostream>
    #include <iomanip>
    #include <fstream>
    
    #include <string>
    #include <sstream>
    
    #include "json.hpp"
    
    // for convenience
    using json = nlohmann::json;
    
    using namespace std;
    
    json j_pop_systems;
    
    string substr1(json & j, int len)
    {
    	char ca[len + 1];
    	ca[len] = '\0';
    	stringstream ss;
    	ss << j;
    	for(int i = 0; i < len; i++)
    		ss >> ca[i];
    	return string(ca);
    }
    
    int main(int argc, char **argv)
    {
    	// read a JSON file
    	ifstream i("/home/ubuntu-1/Downloads/systems_populated.json");
    	i >> j_pop_systems;
    
    	cout << setw(4) << substr1(j_pop_systems, 500) << endl;
    
    	return 0;
    }
    

    len bedeutet, wie viele Zeichen einer Json-Datei ausgegeben werden sollen.

    Ich wär dankbar, wenn mir das jemand um die Ohren hauen könnte. ♥-Dank.



  • So ein Quatsch.



  • @Mechanics sagte in Frage zu substr:

    So ein Quatsch.

    Begründung!! 😁



  • Warum schreibst du eine substr Funktion?
    Kompiliert das?



  • Hallo,
    ja es kompiliert. Um es zu compilieren, brauchst du nur die Datei json.hpp im Build-Path!



  • @Mechanics sagte in Frage zu substr:

    Warum schreibst du eine substr Funktion?

    Um nur den Anfang der/einer JSON-Datei (begrenzte Zeichen) über cout auszugeben.



  • @EinNutzer0 sagte in Frage zu substr:

    brauchst du nur die Datei json.hpp im Build-Path!

    Darauf wollte ich nicht hinaus, sondern auf dein array, das du mit einer Variable initialisierst. Das glaub ich jetzt nicht, dass das kompiliert.
    Und nochmal, WARUM schreibst du so eine schlechte Funktion selber (total hässlich und ineffizient, falls das mal funktionieren sollte, statt etwas fertiges zu benutzen?



  • @Mechanics sagte in Frage zu substr:

    total hässlich und ineffizient, falls das mal funktionieren sollte, statt etwas fertiges zu benutzen?

    Oh, das müsstest du jetzt begründen oder untermauern, mit einer besseren Version. Zudem ist mir für diesen Anwendungsfall keine bessere Funktion bekannt. (Was soll wie wann dabei langsam oder schlechter Stil sein?)

    @Mechanics sagte in Frage zu substr:

    Das glaub ich jetzt nicht, dass das kompiliert.

    Doch tut es.

    Ich hoffe das ist nicht nur viel Wind. 😉



  • Kurze Anfängerfrage von mir: warum nimmst du nicht einfach die substr-Methode vom std::string?



  • @EinNutzer0 sagte in Frage zu substr:

    Doch tut es.

    Wie soll das gehen? Das würde nur gehen, wenn das ganze einschließlich len constexpr wäre, ist es aber nicht.

    Warum das langsam ist?
    Da werden sehr viele Kopien angelegt. Es fängt schon damit an, dass du ALLES in einen string stream schreibst, obwohl du nur einen kleinen Teil haben willst. Das kann schon sehr viel Rechenzeit verschwenden, als nötig wäre. Dann kopierst du die Zeichen einzeln in ein Array. Dann kopierst du das Array wieder in einen neuen string. Sehr viele völlig überflüssige Operationen.



  • @Zhavok sagte in Frage zu substr:

    Kurze Anfängerfrage von mir: warum nimmst du nicht einfach die substr-Methode vom std::string?

    Weil j.substr(0,500) (j sei hier vom Typ json) in dem Stream nicht funktionieren würd, und außerhalb nicht der gesamte Stream gelesen würd, also weniger als 500 Zeichen ausgegeben werden würd.

    Ich hab jetzt versucht, mehr darüber zu lesen, ob es unsicher usw. wäre. Siehe zum Beispiel [2] .

    Innerhalb des lokalen Scope wird (irgendwie) Speicher angefordert bzw. reserviert, dieser wird kopiert oder re-referenziert, und danach zurückgegeben. Aber dennoch wäre das (zumindest nach Artikel [2] ) Nicht unsicher.



  • @EinNutzer0 sagte in Frage zu substr:

    Doch tut es.

    Ich hoffe das ist nicht nur viel Wind. 😉

    Das:

    @EinNutzer0 sagte in Frage zu substr:

    string substr1(json & j, int len)
    {
        char ca[len + 1];
        // ...
    

    ist kein gültiges Standart-C++. In C++ gibt es keine VLAs. Der gcc und vielleicht auch clang wenn man ihn richtig streichelt schlucken soetwas als Spracherweiterung. Schön ist es nicht. Ist es ein String? Nimm std::string. Sind es sonstwelche Daten? Nimm einen std::vector<char>.

    std::string substr1(json const &j, int len)
    {
        return j.dump(0).substr(0, len);
    }
    


  • Genau so wie @Swordfish das gezeigt hat, hab ichs gemeint. Auf dump() kannst du ganz einfach substr() anwenden. Da brauchst du das Rad nicht neu zu erfinden.



  • Aber zuerst den kompletten JSON-String zu erzeugen, um dann anschließend nur die ersten x Zeichen auszugeben, sind performance- und speichertechnisch eher suboptimal.

    Ich habe nur kurz über den Source geschaut, aber ich würde dann eher auf den Iterator zugreifen und solange Zeichen ausgeben, bis die Gesamtlänge erreicht ist.



  • @Th69 Ich habe nicht so genau geschaut, aber ich glaube nicht daß die Iteratoren von diesem json-Ding zeichenweise arbeiten.

    ps: Ach, Du meinst das sicher anders.



  • Ja, meinte es anders, aber ist wohl nicht so einfach so (bei dem bestehenden Code der JSON-Lib).
    Evtl. einen eigenen Output-Adapter (basierend auf output_adapter_protocol) definieren, welcher bei Überschreitung der Gesamtlänge z.B. eine Exception wirft und diese dann abfangen.

    string_t dump_until(int max_length,
                        const int indent = -1,
                        const char indent_char = ' ',
                        const bool ensure_ascii = false,
                        const error_handler_t error_handler = error_handler_t::strict) const
    {
        string_t result;
       
        try
        {
          serializer s(my_output_adapter<char, string_t>(result, max_length), indent_char, error_handler);
    
          if (indent >= 0)
          {
              s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
          }
          else
          {
              s.dump(*this, false, ensure_ascii, 0);
          }
        }
        catch (maxlength_exception &ex)
        {
        }
    
        return result;
    }
    

    (evtl. kann man auch den error_handler dafür gebrauchen?)



  • @Swordfish sagte in Frage zu substr:

    ist kein gültiges Standart-C++. In C++ gibt es keine VLAs.

    Danke, daran hatte ich gar nicht mehr gedacht. Ich dachte eher, er hätte nicht den Code gepostet, mit dem er wirklich testet.



  • @EinNutzer0 sagte in Frage zu substr:

    stringstream

    Ich denke mal vorsichtig, dass stringstream dabei überflüssig ist, und der Rest so stimmt. 😊

    const &j - was bedeutet eigentlich const und &? Nur der Pointer ist unveränderlich, nicht das Objekt an sich, oder? Sonst stünde stattdessen const json const &j, oder? ... Zuweilen scheint Cpp sogar logisch zu sein. 😃



  • @EinNutzer0 sagte in Frage zu substr:

    const &j - was bedeutet eigentlich const und &?

    j ist eine Referenz auf ein konstantes Dingsti.


Log in to reply