Telefonbuchprogramm - Strings werden nach dem Sortieren nicht mehr angezeigt.


  • Mod

    CStolls Frage ist auf jeden Fall das erste, dass einem einfällt. Natürlich ist es zulässig, deine Klassen so zu benennen, dafür sind Namensräume ja da. Es ist aber in Hinblick auf die Standardbibliothek unglücklich, die gleichen Namen zu verwenden - mindestens bei Bezeichnern, die sehr häufig genutzt werden.

    Ohne jetzt das Programm analysiert zu haben, fällt mir in set<T> auf, dass du einerseits Informationen doppelt speicherst (m_size ist auch in m_data enthalten), und andererseits m_size nicht initialisierst...

    ob das ein Problem ist ? keine Ahnung - schau selber nach

    Grundsätzlich sind nicht nur public oder protected Daten kritisch zu beurteilen; selbst innerhalb einer Klasse ist es sinnvoll, zu kapseln, und den direkten Zugriff auf Daten auf eine kleine Anzahl von Funktionen (eine Art minimales Interface im Sinne von Sutters) zu beschränken.

    Edit: Mach dich auch mit den Algorithmen der Standardbibliothek vertraut, damit wird einiges deutlich einfacher und ausdrucksstärker. Nachdem du weist, wie du arrays mit einer Schleife kopierst, solltest du wirklich lernen, mit copy umzugehen 😉



  • Mh ja ich nen die halt so weil ich das so mache wie in dem Volkar Tutorial, und mich halt an die Namen von dem gehalten habe.
    Das schaut nur so aus, m_size in der Klasse set hat andere Werte als m_size in der Klasse vector. In der Klasse set zählt m_size immer mit wo es den nächsten Eintarg einfügen muss, also nachdem ersten Eintrag mit der Methode Insert -> m_size++, also anfangs ist m_size=0; dann 1,2....... soviele Einträge es halt gibt.
    Und m_size in vector ist anfangs 10 und wenn das Array dann vergrößert wird, dann ist m_size="= 20....... (vergrößert wird in vector mit der Methode "grow")
    Siehe vector.hpp Zeile 80 --> change_size(&m_data,m_size,fields);
    Dankeschön schon mal im Vroaus.

    PS: Meine Vererbungen sind aber glaub n bissel konfus.


  • Mod

    Eigentlich funktioniert das auch mit ints u.ä. nicht so richtig - allerdings wird das möglicherweise nicht sichtbar, wenn du im Debug-Modus arbeitest. Dein vector weiß nichts davon, wie viele Elemente tatsächlich mit sinnvollen Werten gefüllt sind und beim Sortieren benutzt er einfach alle, auch solche, die eigentlich erst einmal nur reserviert sind. Nun sind aber default-konstruierte Strings leere Strings. Und beim Vergleich sind diese kleiner als jeder andere String, landen also am Anfang.



  • Danke für deinen Rat camper, stimmt natürlich, ich hab mein Programm gleich bissel umgebaut und jetzt geht alles mit dem Sortieren.
    So aber kommen wir gleich zu meinem nächsten Problem 😃
    Folgendes:
    Das hier ist ja meine SORTIER-FUNKTION

    template <class T>
    void sort<T>::sort_array(T *array,int length)
    {
        int tradeoff=0;
        for (int i=0;i<length-1;i++)
        {
            tradeoff=i;
            for (int j=i;j<length;j++)
            {
                if (array[tradeoff]>array[j])
                {
                    tradeoff=j;
                }
            }
            swap(array[i],array[tradeoff]);
        }
    }
    

    Wenn ich nun ein Array mit strings durchsortieren lasse, dann ist es so das er auch zwischen groß und kleinschreibung unterschiedet. DAs heißt also, wenn ich folgendes habe:

    main.cpp

    #include <iostream>
    #include "set.hpp"
    #include <string>
    using namespace std;
    
    int main()
    {
        set<string> data_base;
        data_base.insert("zerch");
        data_base.insert("Werner");
        data_base.insert("olm");
        data_base.insert("oskar");
        data_base.insert("Hanna");
        data_base.insert("franz");
        data_base.insert("gehart");
        data_base.insert("Otto");
        data_base.insert("olga");
        data_base.insert("xaver");
        data_base.insert("gerda");
        data_base.insert("Peter");
        data_base.insert("hans");
        data_base.insert("elliott");
    
        for (int i=0;i<14;i++)
        {
            cout << data_base[i] << endl;
        }
    	return 0;
    }
    

    dann kommt das hier raus:

    Hanna
    Otto
    Peter
    Werner
    elliott
    franz
    gehart
    gerda
    hans
    olga
    olm
    oskar
    xaver
    zerch

    Des is aber ziemlich häslich, weil ich möchte das nicht unter groß und kleinschreibung unterschieden wird, sondern nur unter den Buchstaben im Alphabet.
    Das Problem ist ja das der operator ">" bei strings diese nach den ASCII-Zeichen untersucht, was also heißt bei Großbuchstaben von 65 (für A) bis 90 (für Z), und das gleiche bei Kleinbuchstaben 97 (für a) bis 122 (für z).
    Also müsste ich die Buchstaben in meiner Sortier funktion irgendwie kruz vor dem sortieren alle in kleinbuchstaben umwandeln, also wie das hier:

    #include <ctype.h>
    ....
    .....
    //in sortier Methode
    if (tolower(array[tradeoff])>tolower(array[j]))
    ......
    .....
    ...
    

    So alles schön und gut, aber wie man ja bei meiner sortier Methode (oben gepostet) sieht, handelt es sich um eine template Methode, und ich will ja da Zahlen sortieren bzw. strings.... somit muss ich die so allgemein wie möglich halten.
    Also kann ich das hier:

    if (tolower(array[tradeoff])>tolower(array[j]))
    

    gar nicht machen, weil ja bei "int,..." Probleme kommen würden. Somit muss ich erst irgendwie feststellen ob "T" ein string,int.... ist [Funktionskopf: void sort<T>::sort_array(T *array,int length)]. Und dann halt irgendwie das so abfragen:
    Wenn T ein string ist dann --> if (tolower(array[tradeoff])>tolower(array[j]))
    Wenn T kein string ist dann ganz normal --> if (array[tradeoff]>array[j])

    So aber wie mach ich das nun? Wie kann ich unterscheiden ob T ein "float" ist oder ein "double" oder ein "string"......???
    Dankeschön schon mal im Voraus.



  • Der Groß- und Kleinschreibungs - Vergleich von String ist in C++ eine etwas längere Geschichte 😃 ( Exceptional C++ oder hier: http://fara.cs.uni-potsdam.de/~kaufmann/?page=GenCppFaqs&faq=stricmp#Answ steht auch nen bissl was dazu ).

    Zu deinem Problem: In dem falle würde dir TemplateSpezialisierung helfen:

    template<class T> void func() { }
    //func() für ints spezialsiert
    template<> void func<int> () {}
    

    Das nur auf dein Beispiel abstimmen und sorg dafür das dein Sortier-Code ausgelagert ist und deine template Funktion diese aufrufen.
    Wandel die String in Groß/Klein um und übergib sie deinem sort().



  • Meinst du sowas?

    ....
    template <class T>
    void sort<T>::sort_array(T *array,int length)
    {
        int tradeoff=0;
        for (int i=0;i<length-1;i++)
        {
            tradeoff=i;
            for (int j=i;j<length;j++)
            {
                if (array[tradeoff]>array[j])
                {
                    tradeoff=j;
                }
            }
            swap(array[i],array[tradeoff]);
        }
    }
    
    template <class T>
    void sort<T>::sort_array<std::string>(T *array,int length)
    {
        int tradeoff=0;
        for (int i=0;i<length-1;i++)
        {
            tradeoff=i;
            for (int j=i;j<length;j++)
            {
                if (tolower(array[tradeoff])>tolower(array[j]))
                {
                    tradeoff=j;
                }
            }
            swap(array[i],array[tradeoff]);
        }
    }
    .....
    

    Das funzt aber irgendwie net bei mir.
    Da kommt:

    -------------- Build: Debug in Telefonbuch ---------------
    Compiling: main.cpp
    In file included from size.hpp:4,
    from vector.hpp:4,
    from set.hpp:6,
    from main.cpp:2:
    sort.hpp:51: error: expected init-declarator before '<' token
    sort.hpp:51: error: expected `;' before '<' token
    Process terminated with status 1 (0 minutes, 0 seconds)
    2 errors, 0 warnings

    Mh ich kenn mich leider mit templates no net so gut aus, das mit der template Spezialisierung hab ich au no nie gehört, weil ich sowas spezielles eigentlich noch nie gebraucht habe. 😃
    Na ja aber es gibt ja immer ein erstes mal! 🙂
    Is das sowas wie überladen, das mit der template Spezialisierung? Oder kann ich das vll. irgendwie auch mit "string" überladen? Oder ist das dann template Spezialisierung? Kann sich jemand vorstellen was ich meine?
    Dankeschön schon mal im Voraus.



  • Dein sort für Elementfunktion muss so aussehen:

    template <>
    void sort<T>::sort_array<std::string>(std::string *array,int length)
    {
        int tradeoff=0;
        for (int i=0;i<length-1;i++)
        {
            tradeoff=i;
            for (int j=i;j<length;j++)
            {
                if (tolower(array[tradeoff])>tolower(array[j]))
                {
                    tradeoff=j;
                }
            }
            swap(array[i],array[tradeoff]);
        }
    }
    

    Erinnerung: Versuche doppelten gleichen Code zu meiden.

    Hier ist ein guter Artikel für Templates: http://www.c-plusplus.net/forum/viewtopic-var-t-is-128361.html



  • Irgendwie funzts nicht:

    #ifndef SORT_HPP_INCLUDED
    #define SORT_HPP_INCLUDED
    
    #include <string>
    #include <ctype.h>
    
    template <class T>
    class sort
    {
        public:
        sort();
        ~sort();
        void sort_array(T *array,int length);
        void swap(T &a,T &b);
    
        private:
    
    };
    
    template <class T>
    sort<T>::sort()
    {
    
    }
    
    template <class T>
    sort<T>::~sort()
    {
    
    }
    template <class T>
    void sort<T>::sort_array(T *array,int length)
    {
        int tradeoff=0;
        for (int i=0;i<length-1;i++)
        {
            tradeoff=i;
            for (int j=i;j<length;j++)
            {
                if (array[tradeoff]>array[j])
                {
                    tradeoff=j;
                }
            }
            swap(array[i],array[tradeoff]);
        }
    }
    
    template <>
    void sort<T>::sort_array<std::string>(std::string *array,int length)
    {
        int tradeoff=0;
        for (int i=0;i<length-1;i++)
        {
            tradeoff=i;
            for (int j=i;j<length;j++)
            {
                if (tolower(array[tradeoff])>tolower(array[j]))
                {
                    tradeoff=j;
                }
            }
            swap(array[i],array[tradeoff]);
        }
    }
    
    template <class T>
    void sort<T>::swap(T &a,T &b)
    {
        const T temp=a;
        a=b;
        b=temp;
    }
    
    #endif // SORT_HPP_INCLUDED
    

    Aber so hast dus doch gemeint oder?

    EROOR:

    -------------- Build: Debug in Telefonbuch ---------------
    Compiling: main.cpp
    In file included from size.hpp:4,
    from vector.hpp:4,
    from set.hpp:6,
    from main.cpp:2:
    sort.hpp:52: error: T' was not declared in this scope sort.hpp:52: error: template argument 1 is invalid sort.hpp:52: error: expected init-declarator before '<' token sort.hpp:52: error: expected;' before '<' token
    Process terminated with status 1 (0 minutes, 0 seconds)
    4 errors, 0 warnings

    Dankeschön schon mal im Voraus.



  • Übergib deinem Set doch einfach als weiteren Parameter eine Comperator Klasse, die du per default auf less_then (oder wie hiesz die??) stellst. Wenn du dann eben ohne Grosz-Kleinschreibung vergleichen willst-> lies Volkards tut ein bisschen weiter bis zur NoCaseStringComperator-Klasse.



  • Ach murks, habe irgendwie was vercheckt 🙂
    So ist es logisch und muss es aussehen:

    template <>
    void sort<std::string>::sort_array(std::string *array,int length)
    

Anmelden zum Antworten