vector alphabetisch sortieren nach Groß/Kleinschreibung
-
Hallo,
ich habe einen vector ( vector<Klasse> ) aus Klassenobjekten und diesen will ich jetzt nach einem string Klassenattribut der Objekte alphabetisch sortieren. Das hab ich mit dem Bubblesort Algorithmus bis jetzt auch umsetzen koennen, nur sortiert er dort die Woerter mit Großbuchstaben und Kleinbuchstaben jeweils getrennt alphabetisch.
Beispiel:
unsortiert:
Alles
camel
Baseball
apfelnach bubblesort:
Alles
Baseball
apfel
camelrichtige sollte es sein:
Alles
apfel
Baseball
camelIch habs jetzt versucht anhand der Ascii Codes If Bedingungen aufzustellen, aber irgendwie komm ich damit auch auf keinen grünen Zweig...
Gibt es da eine einfachere Methode als von den einzelnen Buchstaben Fallunterscheidungen zu machen, ob der Ascii Code groeßer als 96 ist, sprich ein Kleinbuchstabe und dann 32 davon abzuziehen, um ihn mit dem Großbuchstaben vergleichen zu koennen?Eine weitere Frage, ist ratsam in einer durch call by reference Funktion den uebergebenen Parameter wieder durch eine andere call by reference Funktion aufzurufen. Bei dem Parameter handelt es sich um den gleichen Vector wie oben.
Danke!
Grüße Steppen
-
Hi,
das Thema ist eigentlich was komplexer, aber fürs erste sollte es doch eigentlich nur reichen, wenn dein bubbleSort so aussieht:
//bubbleSort: /* blub blub, * * * * * blubble */ if(toupper(zeichen) < toupper(zeichen2)) /* blub blub, * * * * * blubble */Dh, alles immer groß oder klein machen und so vergleichen.
Steppen schrieb:
Ich habs jetzt versucht anhand der Ascii Codes If Bedingungen aufzustellen, aber irgendwie komm ich damit auch auf keinen grünen Zweig...
Gibt es da eine einfachere Methode als von den einzelnen Buchstaben Fallunterscheidungen zu machen, ob der Ascii Code groeßer als 96 ist, sprich ein Kleinbuchstabe und dann 32 davon abzuziehen, um ihn mit dem Großbuchstaben vergleichen zu koennen?Da wäre die einfachere Variante, ist im Prinzip das, was du beschrieben hast. Vllt zeigst du uns dein Problem-Code.
-
Steppen schrieb:
Das hab ich mit dem Bubblesort Algorithmus bis jetzt auch umsetzen koennen
Huch!
Schau dir doch malstd::sortauf www.cplusplus.com an.
Du kannst zum Beispiel
std::tolower()aus<locale>einsetzen, um zuerst alles in Kleinbuchstaben umzuwandeln und dann diese direkt zu vergleichen.Zu der Call-By-Reference-Funktion: Warum soll das nicht ratsam sein?
-
Danke füer die schnnellen Antworten!
Also hab es jetzt mit beiden Vorschlaegen versucht, aber komme auch nicht gewünschten Ergebnis bzw. bei sort() klappt es bei mir erst gar nicht.
for(unsigned int i = 0; i < max_string ; i++) {for(unsigned int j =0 ; j < Filmvektor.size()-1 ; j++) { string Name_1 = Filmvektor[j].get_Name() ; string Name_2 = Filmvektor[j+1].get_Name() ; if(toupper(Name_2[i])>toupper(Name_1[i])) { tmp = Filmvektor[j+1] ; Filmvektor[j+1] = Filmvektor[j] ; Filmvektor[j] = tmp ; }}}Das sortiert mir das ganze gar nicht wie es sein soll.
Dann hab ich es mit sort an einem seperaten Klasse ausprobiert:#include <iostream>
#include <algorithm>
#include <vector>using namespace std;
class Klasse {
private:
string Name ;
public:
Klasse(){Name="Default" ;}
Klasse(string s) : Name(s) {}
string get_Name(){return Name ;}
bool operator() (string i,string j) { return (i<j);}
friend ostream& operator<<(ostream& os, Klasse& k){ os << "Name: " << k.Name << endl ; }
};bool myfunction(Klasse& i, Klasse& j)
{
return i.get_Name()<j.get_Name() ;
}int main()
{
Klasse test1("aB");
Klasse test2("zC");
Klasse test3("DI");
Klasse test4("aA");
Klasse test5("iD");
Klasse test6("Ab");vector<Klasse> Test ;
Test.push_back( test1);
Test.push_back( test2);
Test.push_back( test3);
Test.push_back( test4);
Test.push_back( test5) ;
Test.push_back( test6) ;for(unsigned int i =0; i<Test.size() ; i++)
cout << Test[i] << endl ;sort(Test.begin(),Test.end(),myfunction);
//cout << (int)test[2] << endl ;
return 0 ;
}Kompiliert das aber erst wenn ich aus myfunction eine call by value Funktion mache.
-
versuch es mal mit C++ Tags anstatt quote oder code-tags...
so geht es richtig:
#include <locale> #include <string> struct toupper_comparer { bool /*less*/ operator() (const std::string &lhs, const std::string &rhs) const { for(std::string::size_type i(0), e1(lhs.length()), e2(rhs.length()); i != e1; ++i) { if(i != e2) { if( toupper(lhs[i]) == toupper(rhs[i]) ) continue; } return toupper(lhs[i]) < toupper(rhs[i]); } } }; #include <algorithm> #include <iostream> #include <vector> int main() { std::vector<std::string> arr; arr.push_back("f"); arr.push_back("bsd"); arr.push_back("C++"); arr.push_back("ASD"); arr.push_back("G"); arr.push_back("C"); std::sort( arr.begin(), arr.end(), toupper_comparer() ); std::copy( arr.begin(), arr.end(), std::ostream_iterator<std::string> (std::cout, "\r\n") ); //ggf was tun, damit die konsole offen bleibt... }bevor jmd fragt:
if(i != e2)
ist nötig, da std::string ja auch '\0' beinhalten kann...
also würd es bei so was hier:`
a s d \0 f
a s d
`
nen speicherzugriffsfehler geben...bb
-
Danke. Klasse hier kommen die Antwort sehr zügig.
Hab selbst grad noch was rumprobiert und es klappt jetzt mit folgender Version:#include <iostream> #include <algorithm> #include <vector> #include <locale> #include <cctype> using namespace std; class Klasse { private: string Name ; public: Klasse(){Name="Default" ;} Klasse(string s) : Name(s) {} string get_Name(){return Name ;} bool operator() (string i,string j) { return (i<j);} friend ostream& operator<<(ostream& os, Klasse& k){ os << "Name: " << k.Name << endl ; } }; void toUpper(basic_string<char>& s) { for(basic_string<char>::iterator p = s.begin(); p != s.end();++p) *p = toupper(*p) ; } bool myfunction(Klasse i, Klasse j) { string Name_1 = i.get_Name() ; string Name_2 = j.get_Name() ; string vergleich ; string tmp ; toUpper(Name_2) ; toUpper(Name_1) ; return Name_1<Name_2 ; } int main() { Klasse test1("aB"); Klasse test2("zC"); Klasse test3("DI"); Klasse test4("aA"); Klasse test5("iD"); Klasse test6("Ab"); vector<Klasse> Test ; Test.push_back( test1); Test.push_back( test2); Test.push_back( test3); Test.push_back( test4); Test.push_back( test5) ; Test.push_back( test6) ; for(unsigned int i =0; i<Test.size() ; i++) cout << Test[i] << endl ; sort(Test.begin(),Test.end(),myfunction); cout << "----------------------------------"<<endl; for(unsigned int i =0; i<Test.size() ; i++) cout << Test[i] << endl ; //cout << (int)test[2] << endl ; return 0 ; }Ich werd mir Deinen Vorlschag aber jetzt auch noch genauer ansehen.

-
Steppen schrieb:
Ich werd mir Deinen Vorlschag aber jetzt auch noch genauer ansehen.

das hoffe ich - deine lösung ist schon in so fern schlecht, weil die Klasse "Klasse" einen operator() anbietet - hat imho nichts dort zu suchen...
dann gehts weiter mit Dingen wie
basic_string<char>&
bäh ->const string&op<< braucht kein friend zu sein und kann außerhalb der klasse implementiert werden und den getter nutzen, dessen Namen ich übrigens komisch finde ^^
Besonders komisch ist diese Funktion:
bool myfunction(Klasse i, Klasse j)//cout << (int)test[2] << endl ;was sollte das hier werden? ^^return 0 ;ist in der main-fkt unnötigweiter möchte ich deine jetzige Lösung erst mal nicht zerpflücken
ich hoffe, du versuchst es noch einmal und trennst das sortier-kriterium von der klasse und zeigst dann deine (dann hoffentlich durchdachtere) Lösung noch mal, aber hier ists mir zu viel zu kommentieren und zu ändern ^^bb
-
Hm, hab mir die Funktion zum testen gebastelt und n paar Sachen drin gelassen von vorherigen Versuchen.
Also sieht jetzt ausgemistet und Deine Hinweise befolgt so aus:#include <iostream> #include <algorithm> #include <vector> #include <cctype> using namespace std; class Klasse { private: string Name ; public: Klasse(){Name="Default" ;} Klasse(string s) : Name(s) {} string get_Name(){return Name ;} friend ostream& operator<<(ostream& os, Klasse& k){ os << "Name: " << k.Name << endl ; } }; void toUpper(string& s) { for(string::iterator p = s.begin(); p != s.end();++p) *p = toupper(*p) ; } bool myfunction(Klasse i, Klasse j) { string Name_1 = i.get_Name() ; string Name_2 = j.get_Name() ; toUpper(Name_2) ; toUpper(Name_1) ; return Name_1<Name_2 ; } int main() { Klasse test1("aB"); Klasse test2("zC"); Klasse test3("DI"); Klasse test4("aA D"); Klasse test5("iD ccD"); Klasse test6("Ab"); vector<Klasse> Test ; Test.push_back( test1); Test.push_back( test2); Test.push_back( test3); Test.push_back( test4); Test.push_back( test5) ; Test.push_back( test6) ; for(unsigned int i =0; i<Test.size() ; i++) cout << Test[i] << endl ; sort(Test.begin(),Test.end(),myfunction); cout << "----------------------------------"<<endl; for(unsigned int i =0; i<Test.size() ; i++) cout << Test[i] << endl ; }Nur wenn ich operator<< außerhalb der Klasse definiere und mit der Membermethode auf den Namen zugreife stürzt das Programm bei mir ab.
Den Aufruf der bool toUpper Funktion wüßte jetzt nicht, wie die Parameter aendern sollte.
Ich versuch mich morgen weiter dran. Schönen Abend noch.
-
ok, sieht besser aus
ich hoffe, die Klasse heißt in Wirklichkeit besser?! ^^
Klasse(){Name="Default" ;} Klasse(string s) : Name(s) {}->
Klasse(const string &s = "Default") : Name(s) {}in diesem Zusammhang könntest du dir noch das Schlüsselwort
explicitauch mal angucken...friend ostream& operator<<(ostream& os, Klasse& k){ os << "Name: " << k.Name << endl ; }wird zu
ostream& operator<< (ostream& os, const Klasse &these) { os << "Name: " << these.get_Name() << endl; return os; }außerhalb der klasse
void toUpper(string& s) { for(string::iterator p = s.begin(); p != s.end();++p) *p = toupper(*p) ; }solltest du so machen:
void toUpper(string& s) { for(string::iterator p = s.begin(), e = s.end(); p != e; ++p) *p = toupper(*p); }for(unsigned int i =0; i<Test.size() ; i++)wird zu
for(vector<Klasse>::size_type i = 0, e = Test.size(); i != e; ++i)bb
PS:
for(unsigned int i =0; i<Test.size() ; i++) cout << Test[i] << endl ;_könntest_ du mit
std::copy( arr.begin(), arr.end(), std::ostream_iterator</*auszugebenden Elementtyp hier einsetzen*/> (std::cout, "\r\n") );ersetzen