std::string durchlaufen



  • Den Key definieren als struct Key{ char a,b,c;} und dann den Pointer in den String darauf casten sollte gehen.

    Bye, TGGC (Keine Macht den Dummen)



  • TGGC schrieb:

    Den Key definieren als struct Key{ char a,b,c;} und dann den Pointer in den String darauf casten sollte gehen.

    Wow, wenn man noch nen 'operator <' überlädt, klappt das sogar. Aber diese Lösung ist dann doch ein wenig krank. 😉 Viel rumgecaste ...



  • Konrad Rudolph schrieb:

    TGGC schrieb:

    ...

    Wow, wenn man noch nen 'operator <' überlädt, klappt das sogar. Aber diese Lösung ist dann doch ein wenig krank. 😉 Viel rumgecaste ...

    das ist genau 1 cast...



  • otze schrieb:

    Konrad Rudolph schrieb:

    TGGC schrieb:

    ...

    Wow, wenn man noch nen 'operator <' überlädt, klappt das sogar. Aber diese Lösung ist dann doch ein wenig krank. 😉 Viel rumgecaste ...

    das ist genau 1 cast...

    Ja, in der Schleife schon ... aber die Hashtable muss ja mit Strings à drei Buchstaben initialisiert werden. Okok, man kann sich einen impliziten Konstruktor mit einem String als Parameter für diese key-Struktur schreiben. Was mich daran eigentlich am meisten stört, ist eher der Gebrauch von 'c_str()'. Ich überlege im Moment eigentlich, ob es sinnvoll wäre, so ein "CharTriple" mit einem Cast vom String-Iterator zu verwenden.



  • Was mich daran eigentlich am meisten stört, ist eher der Gebrauch von 'c_str()'.

    was stört dich daran? bei meiner implementation ist das einfach die rückgabe des internen char pointers des strings...



  • otze schrieb:

    Was mich daran eigentlich am meisten stört, ist eher der Gebrauch von 'c_str()'.

    was stört dich daran? bei meiner implementation ist das einfach die rückgabe des internen char pointers des strings...

    Nun, in 'std::string' ist es ein nullterminiertes char-Array, was auf dem Heap vor sich hin vegetiert und auf Erlösung seitens des std::string wartet. Gut für Interop mit C-Bibliotheken. Wahrscheinlich sage ich hier gerade etwas unheimlich falsches ... aber nullterminierte Strings sind einfach nicht mein Ding. Außerdem finde ich, dass 'c_str()' als Aufruf unheimlich hässlich aussieht. Ich will ja mit der String-Instanz interagieren und mich nicht mit Implementierungsdetails herumschlagen. In meinem Augen ist 'c_str' aber eine Offenlegung von Implementierungsdetails für Rückwärtskompatibilität.



  • Außerdem finde ich, dass 'c_str()' als Aufruf unheimlich hässlich aussieht.

    soll es auch. Hierbei bewahrt es uns nur davon, für einen unter umständen recht langen string size()/3 "new" aufzurufen....

    dann schaun wir uns das mal an:

    struct Codon{
        char a,b,c;
    };
    //ich bete zu gott, dass ich endlich mal den richtigen cast verwende
    const Codon*  codons=static_cast<const Codon*>(sequence.c_str());
    for(int i=0;i<sequence.size()/3;++i){
        if (rnaCodons.find(codons[i]) == rnaCodons.end())
                throw InvalidSequenceError();
            this->aminoAcids.push_back(rnaCodons[codons[i]]);
    }
    

    dann ist rnaCodons keine map<string, string> sondern eine map<Codon, string>

    ich persönlich würds zwar auch nicht so machen, aber es ist ne alternative



  • otze schrieb:

    Außerdem finde ich, dass 'c_str()' als Aufruf unheimlich hässlich aussieht.

    soll es auch. Hierbei bewahrt es uns nur davon, für einen unter umständen recht langen string size()/3 "new" aufzurufen....

    Hmm, irgendwie hast Du recht, da kann doch schon einiges an Performance rauszuholen sein.

    //ich bete zu gott, dass ich endlich mal den richtigen cast verwende

    Nope. 'static_cast' geht hier ja gerade nicht, man braucht ein 'reinterpret_cast' ... mit Vorsicht zu genießen.

    Allerdings kommen bei mir da jetzt sowieso sehr komische Resultate heraus, egal, wie ich es nun mache.

    Ich habe die Klasse 'Codon' ein wenig ausgebaut, damit sie mit der 'map' verwendbar ist aber irgendwo ist da der Wurm drin:

    struct Codon {
    private: char a, b, c;
    public:
        Codon(const char* rhs)
        {
            this->a = rhs[0];
            this->b = rhs[1];
            this->c = rhs[2];
        }
    
        bool operator <(const Codon& rhs) const
        {
            return this->a < rhs.a or this->b < rhs.b or this->c < rhs.c;
        }
    
        operator bool() const
        {
            return this->a != 0;
        }
    };
    
    Angewendet wird das wie folgt:
    
    map<Codon, string> rnaCodons;
    rnaCodons["Tyr"] = "Tyrosine";
    rnaCodons["Lys"] = "Lysine";
    rnaCodons["His"] = "Histidine";
    rnaCodons["Gln"] = "Glutamate";
    rnaCodons["Glu"] = "Glutamine";
    
    string foo("LysHisGluGlnTyrTyr");
    
    for (const Codon* i = reinterpret_cast<const Codon*>(foo.c_str()); *i; ++i)
        std::cout << rnaCodons[*i] << std::endl;
    

    Ausgegeben wird:

    Histidine
    
    Tyrosine
    Tyrosine
    

    (Die erste Zeile ist leer, Histidin steht in der zweiten Zeile)

    Die letzten beiden Zeilen des Codes kann man auch durch Deine Variante ersetzen, selbes Resultat:

    const Codon* codons = reinterpret_cast<const Codon*>(foo.c_str());
    for (int i = 0; i < foo.size() / 3; ++i)
        std::cout << rnaCodons[codons[i]] << std::endl;
    


  • es liegt an deinem op< der ist falsch.

    ich muss leider schnell weg, kann mir deshalb nix ausdenken, hiermit hats aber funktioniert:

    bool operator <(const Codon& rhs) const
        {
           std::string str1;
    	   str1+=a;
    	   str1+=b;
    	   str1+=c;
    
    	   std::string str2;
    	   str2+=rhs.a;
    	   str2+=rhs.b;
    	   str2+=rhs.c;
    
    	   return str1<str2;
        }
    


  • Danke, daran lag's natürlich. Eine Lösung ohne String sieht so aus:

    bool operator <(const Codon& rhs) const
    {
        return this->a < rhs.a or
               this->a == rhs.a and
               (this->b < rhs.b or
               this->b == rhs.b and
               this->c < rhs.c);
    }
    


  • kleiner tipp: es gibt den op<= 😉



  • otze schrieb:

    kleiner tipp: es gibt den op<= 😉

    Ja aber da sind die Prioritäten anders. 'and' hat ja eine höhere Priorität als 'or', daher würde '<=' in diesem Kontext etwas anderes heißen.

    Mit anderen Worten:

    (a <= b and c < d) != (a < b or a == b and c < d)
    

Anmelden zum Antworten