"Rohdatentyp"



  • Alternativ so:

    #include <iostream>
    #include <vector>
    
    const char * const txt = "Hallo Welt!";
    
    static size_t len(const char * c)
    {
      size_t len;
      for (len = 0; *c++; ++len)
        ;
      return len;
    }
    
    int main()
    {
      std::vector<char> buf(txt, txt + len(txt) + 1);
      std::cout << &buf[0] << '\n';
    }
    


  • Das ist einfach weil strlen() zu low wär 😉



  • Wenn dir strlen() zu low ist, dann wären das noch zwei Möglichkeiten :

    #include <iostream>
    #include <vector>
    
    std::vector<char> cstr2vec(const char * cstr)
    {
      std::vector<char> vec;
      for (; *cstr; ++cstr)
        vec.push_back(*cstr);
      vec.push_back('\0');
      return vec;
    }
    
    int main()
    {
      {
        const char anf [] = "Hallo Welt!";
        const char end [] = "";
    
        std::vector<char> buf(anf, end);
        std::cout << &buf[0] << '\n';
      }
      {
        std::vector<char> buf(cstr2vec("Hallo Welt!"));
        std::cout << &buf[0] << '\n';
      }
    }
    

    Wenn du dich nur an strlen als C-Funktion störst, dann geht auch:

    std::string("Hallo").length()
    

    Das mach aber auch nichts anderes.



  • Für String-Literale spricht natürlich auch in C++ nichts dagegen, const char* zu nehmen. Aber die const -Qualifizierung sollte man nicht vergessen.

    cooky451, vielleicht ein paar Verbesserungsvorschläge für deine Klasse:

    • std::vector besitzt keine Memberfunktion data() .
    • Mach deine Methoden const -korrekt. Sowohl die Memberfunktion selbst als auch ihre Parameter sind teilweise unnötig eingeschränkt durch Zeiger/Referenzen auf veränderbare Objekte.
    • Im Kopierkonstruktor den Zuweisungsoperator aufzurufen ist eher unüblich. Mach es lieber umgekehrt mit dem Copy-and-Swap-Idiom.
    • Der Umweg von char* über std::string ist unnötig ineffizient. Auch hier könntest du mit dem umgekehrten Weg besser fahren (unter Benutzung von std::string::c_str() ).


  • Hm.
    Kann Boost.Assign vielleicht vector<char> = (string-literal) ?


  • Mod

    #include <iostream>
    #include <vector>
    
    const char txt[] = "Hallo Welt!";
    
    template<std::size_t N>
    std::vector<char> str2vec(const char (&str)[N])
    {
        return std::vector<char>( str, str + N );
    }
    
    int main()
    {
      std::vector<char> buf( str2vec( txt ) );
      std::cout << &buf[0] << '\n';
    }
    

  • Mod

    hav a break schrieb:

    const char anf [] = "Hallo Welt!";
        const char end [] = "";
    
        std::vector<char> buf(anf, end);
    

    Das ist ziemlich undefiniert.



  • Aufpasser schrieb:

    SeppJ schrieb:

    Aufpasser schrieb:

    ach du heilige scheiße... nimm doch in gottes namen einfach char* 😃

    Und dann baut er ein Speicherleck nach dem anderen, kommt mit der Übergabe an Funktionen nicht zurecht und und und...

    Das alles um sich die obigen drei Zeilen Code zu sparen?

    Ist aber schon interessant, dass du jedem unterstellst, mit C++-Arrays nicht ordentlich umgehen zu können und ihm stattdessen nahelegst ein Template zu programmieren....

    Er unterstellt nur, dass jeder Fehler macht, und wer viele Fehler macht, macht die auch mal bei C++-Arrays - und das führt dann häufig zu Speicherlecks, weil das eben einer der Schwachpunkte von C++-Arrays gegenüber std::vectoren ist.



  • hustbaer schrieb:

    Hm.
    Kann Boost.Assign vielleicht vector<char> = (string-literal) ?

    #include <vector>
    #include <iostream>
    #include <iterator>
    #include <algorithm>
    #include <boost/assign/list_of.hpp>
    
    int main() 
    {
        using namespace std;
        vector<char> v = boost::assign::list_of<char>().range("Hallo Welt!");
        copy(v.begin(), v.end(), ostream_iterator<char>(cout));
        return 0;
    }
    


  • Also um Speicherlecks mache ich mir weniger Sorgen, bei meinen Mini-Projekten (< 5k Zeilen) fällt sowas doch recht schnell auf. Allerdings versuche ich mich gerade vollständig in C++ zu denken und möchte somit möglichst den "C-Weg" vermeiden - und hoffe einfach dass das nicht zu übertrieben wirkt 😃

    @Nexus
    Die Klasse war eigentlich eher scherzhaft gemeint aber scheinbar ist das wohl gar nicht so schlecht?!?^^

    Naja ein paar Fragen hätte ich da noch zu deinen Verbesserungsvorschlägen:
    1. "Const-Correctness" habe ich mir hier ( http://www.possibility.com/Cpp/const.html ) mal durchgelesen allerdings meckert der VS compiler (warning C4114: Der gleiche Typqualifizierer wurde mehrmals verwendet) bei " const std::string const& text ". Was denn nun? Ist das wirklich falsch?

    2. Copy-and-Swap-Idiom verstehe ich nicht so richtig, eine Erklärung und ein kurzes Beispiel wären eventuell hilfreich.. (Finde da irgendwie immer nur Beschreibungen im Zusammenhang mit exceptions.. und diese verstehe ich peinlicherweise auch nicht wirklich..)

    @hav a break
    Ich verstehe überhaupt nicht was dein Code mir sagen soll.. also.. irgendwie hat das alles ziemlich wenig mit dem gefragten zu tun.. oder übersehe ich hier etwas ganz grobes? Was soll das zB. für eine Funktion sein?:

    hav a break schrieb:

    Alternativ so:

    static size_t len(const char * c)
    {
      size_t len;
      for (len = 0; *c++; ++len)
        ;
      return len;
    }
    

    Und warum nutzt Du da nicht einfach strlen() ?



  • cooky451 schrieb:

    Und warum nutzt Du da nicht einfach strlen() ?

    Weil es länger gedauert hätte die richtigen Header zu ergooglen. 😃
    Wird wahrscheinlich cstring sein. Aber man wird auch nicht dümmer, wenn man mal sieht, wie so etwas gemacht wird.



  • hav a break schrieb:

    cooky451 schrieb:

    Und warum nutzt Du da nicht einfach strlen() ?

    Weil es länger gedauert hätte die richtigen Header zu ergooglen. 😃
    Wird wahrscheinlich cstring sein. Aber man wird auch nicht dümmer, wenn man mal sieht, wie so etwas gemacht wird.

    LOL, den header googlen? Naja gut.. vielleicht nutzt man die Funktion in C++ ja seltener oO



  • cooky451 schrieb:

    1. "Const-Correctness" habe ich mir hier ( http://www.possibility.com/Cpp/const.html ) mal durchgelesen allerdings meckert der VS compiler (warning C4114: Der gleiche Typqualifizierer wurde mehrmals verwendet) bei " const std::string const& text ". Was denn nun? Ist das wirklich falsch?

    const std::string const & text;
    (1)               (2)
    
    1&2 sind identisch:
    
    const std::string & text; // \ Bedeutet das gleiche.
    std::string const & text; // /
    

    cooky451 schrieb:

    2. Copy-and-Swap-Idiom verstehe ich nicht so richtig, eine Erklärung und ein kurzes Beispiel wären eventuell hilfreich...

    Die Seite More C++ Idioms zeigt einige durchaus übliche Programmiertechniken in C++, so auch dieses.



  • Ach wie doof hatte das Seiten Beispiel

    const int* const pZ;        // const pointer to const int
    

    Auch auch Referenzen bezogen was natürlich Quatsch ist - ok das wär schonmal geklärt 😃



  • Die Seite zu dem swap() kenne ich schon, allerdings verstehe ich einfach nicht wie mir das jetzt helfen soll.. vielleicht macht sich ja jemand die Mühe und schreibt ein Beispiel..

    Na gut, ich poste einfach noch mal die Klasse - so lernt man wohl am schnellsten 😃

    class MyBuf
    {
    private:
      std::vector<char> m_vector;
    public:
      MyBuf();
      MyBuf(const std::string& text);
      MyBuf(const char* const text);
      void operator = (const std::string& text);
      void operator = (const char* const text);
      char *data();
      void resize(const std::size_t size);
      std::size_t size();
    };
    
    MyBuf::MyBuf()
    {
    }
    
    MyBuf::MyBuf(const char* const text)
    {
      *this = text;
    }
    
    MyBuf::MyBuf(const std::string& text)
    {
      *this = text;
    }
    
    void MyBuf::operator = (const char* const text)
    {
      m_vector.resize(strlen(text) + 1);
      strcpy(&m_vector[0], text);
    }
    
    void MyBuf::operator = (const std::string& text)
    {
      *this = text.c_str();
    }
    
    char *MyBuf::data()
    {
      return &m_vector[0];
    }
    
    void MyBuf::resize(const std::size_t size)
    {
      m_vector.resize(size);
    }
    
    std::size_t MyBuf::size()
    {
      return m_vector.size();
    }
    

    (Und das vector eigentlich gar keinen Member data() hat ist ja mal eine fiese Microsoft Falle ..)



  • Etwas performanter:

    MyBuf::MyBuf() { } 
    
    MyBuf::MyBuf(char const* text) 
    { 
      *this = text;
    } 
    
    MyBuf::MyBuf(std::string const& text) 
    { 
      *this = text; 
    } 
    
    void MyBuf::operator=(char const* text) 
    { 
      m_vector.assign(text, test + strlen(text));
      m_vector.push_back(0); 
    } 
    
    void MyBuf::operator=(std::string const& text) 
    { 
      m_vector.assign(text.begin(), text.end());
      m_vector.push_back(0);
    } 
    
    char* MyBuf::data() 
    { 
      return &m_vector[0]; 
    } 
    
    void MyBuf::resize(const std::size_t size) 
    { 
      m_vector.resize(size); 
    } 
    
    std::size_t MyBuf::size() const 
    { 
      return m_vector.size(); 
    }
    


  • cooky451 schrieb:

    hav a break schrieb:

    cooky451 schrieb:

    Und warum nutzt Du da nicht einfach strlen() ?

    Weil es länger gedauert hätte die richtigen Header zu ergooglen. 😃
    Wird wahrscheinlich cstring sein. Aber man wird auch nicht dümmer, wenn man mal sieht, wie so etwas gemacht wird.

    LOL, den header googlen? Naja gut.. vielleicht nutzt man die Funktion in C++ ja seltener oO

    Ich verwende strlen so gut wie nie. (Und ich weiss auch nicht in welcher Header man strlen findet.)



  • MyBuf::MyBuf(const char* text)
    {
      m_vector.resize(strlen(text));
      strcpy(data(), text);
      //bzw. geht das natuerlich auch viel schoener
    }
    
    MyBuf::MyBuf(const std::string& text)
    : m_vector(text.begin(), text.end())
    {
       m_vector,push_back(0);
       //zb so waere es schoener
    }
    
    MyBuf& MyBuf::operator = (const char* text)
    //2. const ist unnoetig
    {
      MyBuf temp(text);
      swap(temp);
      //copy&swap
      return *this;
      //immer *this returnen
      //damit man weiter arbeiten kann
      //zB a=b=c; oder aehnliches
    }
    
    void swap(MyBuf& other) {
      m_vector.swap(other.m_vector);
    }
    


  • @Shade of Mine: Erstmal alles in einen Vector kopieren nur um swap nutzen zu können?
    Imo sehr fragwürdig.



  • Ethon schrieb:

    @Shade of Mine: Erstmal alles in einen Vector kopieren nur um swap nutzen zu können?
    Imo sehr fragwürdig.

    Du kopierst ja nicht den vector, sondern erstellst ihn.


Anmelden zum Antworten