[gelöst] conversation vector<string> zu QStringList

Alles rund um die Programmierung mit Qt
Antworten
QtBerserker
Beiträge: 71
Registriert: 15. Mai 2006 09:07

[gelöst] conversation vector<string> zu QStringList

Beitrag von QtBerserker »

Hi,

gibt es einen (einfachen) Weg zur Konversation von vector<string> zu QStringList und umgekehrt? Meine bisherigen Versuche endeten einfach zu kompliziert.

Grüße
Olaf
Zuletzt geändert von QtBerserker am 14. November 2006 19:15, insgesamt 1-mal geändert.
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Mir ist da auch keine Funktion bekannt - musst wohl oder übel über alle Items iterieren und mit QString::fromStdString() konvertieren...
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
QtBerserker
Beiträge: 71
Registriert: 15. Mai 2006 09:07

Beitrag von QtBerserker »

Christian81 hat geschrieben:Mir ist da auch keine Funktion bekannt - musst wohl oder übel über alle Items iterieren und mit QString::fromStdString() konvertieren...
Ok, in Analogie zur STL:

Code: Alles auswählen

namespace Qt {
    typedef std::vector<std::string>::iterator input_iterator;
    typedef QList<QString>::iterator output_iterator;

    output_iterator copy(input_iterator from_first, input_iterator from_last,  output_iterator to_first)
    {
        while (from_first != from_last) {
            to_first->fromStdString(*from_first);
            ++from_first;
            ++to_first;
        }
        return to_first;
    }
}
Olaf
lepsai
Beiträge: 573
Registriert: 14. September 2004 21:33
Wohnort: Berlin
Kontaktdaten:

Beitrag von lepsai »

return braucht man nicht, also:

Code: Alles auswählen

namespace Qt { 
    typedef std::vector<std::string>::iterator input_iterator; 
    typedef QList<QString>::iterator output_iterator; 

    void copy(input_iterator from_first, input_iterator from_last,  output_iterator to_first, output_iterator to_last) 
    { 
        while (from_first != from_last  && to_first != to_last) { 
            to_first->fromStdString(*from_first); 
            ++from_first; 
            ++to_first; 
        } 
    } 
} 

std::vector<std::string> v1;
QStringList v2;

copy(v1.begin(), v1.end(), v2.begin(), v2.end());

Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

Ich verstehe nicht was v2.begin(), v2.end() soll - da muss doch somit davor erst die QStringList gross genug gemacht werden...
Was ist gegen

Code: Alles auswählen

v2 += QString::fromStdStringQString::fromStdString(*from_first);
einzuwenden?
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
lepsai
Beiträge: 573
Registriert: 14. September 2004 21:33
Wohnort: Berlin
Kontaktdaten:

Beitrag von lepsai »

Christian81 hat geschrieben:Ich verstehe nicht was v2.begin(), v2.end() soll - da muss doch somit davor erst die QStringList gross genug gemacht werden...
Was ist gegen

Code: Alles auswählen

v2 += QString::fromStdStringQString::fromStdString(*from_first);
einzuwenden?
Die Vektoren mussen sowieso gleich groß sein, sonst funktioniert die while-schleife in dieser Implementierung nicht. ..
Christian81
Beiträge: 7319
Registriert: 26. August 2004 14:11
Wohnort: Bremen
Kontaktdaten:

Beitrag von Christian81 »

lepsai hat geschrieben: Die Vektoren mussen sowieso gleich groß sein, sonst funktioniert die while-schleife in dieser Implementierung nicht. ..
Das meine ich ja - total überflüssig die QStringList in der Grösse festlegen zu müssen...
MfG Christian

'Funktioniert nicht' ist keine Fehlerbeschreibung
lepsai
Beiträge: 573
Registriert: 14. September 2004 21:33
Wohnort: Berlin
Kontaktdaten:

Beitrag von lepsai »

nun ja, die engültige konvertierung würde in dem hier beschriebenen Fall dann so aussehen:

Code: Alles auswählen

template <typename InIt>
QStrlingList convertFromStdStringContainer(InIt begIt, InIt endIt){
   QStringList output;
   output.resize(endIt-begIt);
    
   copy(begIt, endIt, output.begin(), output.end()); 
   return output;
}
die copy() funktion müsste man dann auch anpassen, so dass sie nicht nur mit std::vector::iterator arbeiten kann, sondern den iteratortyp als template argument bekommt...

dann hätte man eine universelle Konvertierung von einem std::string-Kontainer zu QStringList.

Was Du vorschlägst funktioniert natürlich auch...
QtBerserker
Beiträge: 71
Registriert: 15. Mai 2006 09:07

Beitrag von QtBerserker »

gut, die erste Lösung war etwas holprig, wie Euch bereits aufgefallen ist, muss der QListVector erst'mal resized werden.

Hier eine neue Lösung, die auch den assert Test (stdsv.size() == qtsl.size()) bestand:

Code: Alles auswählen

namespace std {

    template<>
    class back_insert_iterator<QStringList> : public iterator<output_iterator_tag, void, void, void, void>
    {
    protected:
        QStringList* container;

    public:
        typedef QStringList          		qcontainer_type;
        typedef std::vector<std::string> 	scontainer_type;

        explicit back_insert_iterator(qcontainer_type& x)
            : container(&x)
        { }

        back_insert_iterator& operator=(scontainer_type::const_reference value) {
            container->push_back(QString().fromStdString(value));
            return *this;
        }

        back_insert_iterator& operator*() { return *this; }
        back_insert_iterator& operator++() { return *this; }
        back_insert_iterator  operator++(int) { return *this; }
    };

    template<>
    inline back_insert_iterator<QStringList>
    back_inserter(QStringList& x) { return back_insert_iterator<QStringList>(x); }

}
using:

Code: Alles auswählen

std::copy(first, last,std::back_inserter(qtstrlst));
Diese Lösung funzt zumindest für den g++ 4.1.2, wobei die zweite Spezialisierung mit dem g++ nicht notwendig ist, evtl. aber bei VC notwendig wird. Prinzipiell kann man somit auch andere Qt Sachen spezialisieren. So, nun macht mich fertig ;-)

Olaf
lepsai
Beiträge: 573
Registriert: 14. September 2004 21:33
Wohnort: Berlin
Kontaktdaten:

Beitrag von lepsai »

Nun ja, das wäre eine STL-konforme Lösung... Die lässt sich aber für alle Kontainertypen verallgemeinern:

Code: Alles auswählen

namespace std {

    template<typename InputContainerType>
    class back_insert_iterator: public iterator<output_iterator_tag, void, void, void, void>
    {
    protected:
        QStringList* container;

    public:
        typedef QStringList          		qcontainer_type;
        typedef InputContainerType	scontainer_type;

        explicit back_insert_iterator(qcontainer_type& x)
            : container(&x)
        { }

        back_insert_iterator& operator=(scontainer_type::const_reference value) {
            container->push_back(QString().fromStdString(value));
            return *this;
        }

        back_insert_iterator& operator*() { return *this; }
        back_insert_iterator& operator++() { return *this; }
        back_insert_iterator  operator++(int) { return *this; }
    };

    template<typename InputContainerType>
    inline back_insert_iterator
    back_inserter(QStringList& x) { return back_insert_iterator<InputContainerType>(x); }

}
using:

Code: Alles auswählen

std::copy(first, last,std::back_inserter(qtstrlst));
QtBerserker
Beiträge: 71
Registriert: 15. Mai 2006 09:07

Beitrag von QtBerserker »

so einfach geht das leider nicht, zum einen klemmt's bei std::back_inserter(qtstrlst), da der Template Parameter dann QStringList wäre, zum anderen gibt es eine Neudefinition von template back_insert_iterator. Imo kommt man um eine Spezialiserung des back_insert_iterators nicht umhin - wenn man diesen Weg wählen möchte.

Olaf
lepsai
Beiträge: 573
Registriert: 14. September 2004 21:33
Wohnort: Berlin
Kontaktdaten:

Beitrag von lepsai »

QtBerserker hat geschrieben:so einfach geht das leider nicht, zum einen klemmt's bei std::back_inserter(qtstrlst), da der Template Parameter dann QStringList wäre, zum anderen gibt es eine Neudefinition von template back_insert_iterator. Imo kommt man um eine Spezialiserung des back_insert_iterators nicht umhin - wenn man diesen Weg wählen möchte.

Olaf
QStringList braucht man nicht als template argument, da es fest ist... Also, wo liegt das Problem?
Antworten