String wiedergeben
-

-
Beantworte mal meine Frage. std::string hat viele Vorteile und keine Nachteile. Erinnert mich an bisschen an die GoingNative Frage an Sutter, da hat auch jemand erzählt, wie seine Arbeitskollegen die Standardbibliothek als irgendetwas externes sehen und sie nicht benutzen wollen. (Gab viel Gelächter danach.) Also los, bau dir eine eigene Stringklasse, aber finde dich damit ab das Gespött der std::string-Kenner zu sein. (Und das sind viele.)
-
RussianTux schrieb:
1. Meine Funktionen sind ebenfalls getestet und brauchen nur ein Klassen-Overlay

Mal ganz davon abgesehen, dass ich nicht sehe, wieso man noch Memberfunktionen braucht, wenn es das Ganze schon als freie Funktionen gibt, kannst du bitte mal zwei, drei Algorithmen posten?
-
Michael E. schrieb:
RussianTux schrieb:
1. Meine Funktionen sind ebenfalls getestet und brauchen nur ein Klassen-Overlay

Mal ganz davon abgesehen, dass ich nicht sehe, wieso man noch Memberfunktionen braucht, wenn es das Ganze schon als freie Funktionen gibt, kannst du bitte mal zwei, drei Algorithmen posten?
Ohne Klassen-Overlay:
const char* string1 = "text1", string2 = "TEXT2"; //eine der einfachsten algorithmen... string1 = s_convert_toUpper(string1); string2 = s_convert_toLower(string2); cout << string1 << "\n"; cout << string2 << "\n";Mit Klassen-Overlay
String string1 = "text1", string2 = "text2"; string1.convert_toUpper(); string2.convert_toLower(); cout << string1 << "\n"; cout << string2 << "\n";Beides funktioniert, aber das 2te ist etwas geordneter
-
Geschmackssache. Aber kannst du bitte noch zwei nicht triviale Algorithmen posten? Danke.
-
Das ist ja noch schlimmer als bei std::string, und da sind die Memberfunktionen schon nicht mehr das Wahre.
@TE Google mal nach "prefer non-member non-friend functions". Da gibt es zwar noch Spielräume (meiner Meinung nach), aber solche Dinge sollten definitiv freie Funktionen sein.
-
Der Vorteil kehrt sich um, sobald du den String selbst nicht verändern willst und das Resultat daher in einem anderen Ziel speichern musst.
Wie sieht denn dein convert_toUpper aus? Meins funktioniert ungefähr so:
void convert_toUpper(std::string& str){ std::transform(str.begin(),str.end(),str.begin(),std::toupper); }//edit oder für wide character unterstützung:
template<class CharT, class Alloc> void convert_toUpper(std::basic_string<CharT,Alloc>& str){ typedef std::basic_string<CharT,Alloc> String; String::iterator end = str.end(); std::locale loc; for(String::iterator pos = str.begin(); pos != end; ++pos){ *pos=std::toupper(*pos,loc); } }
-
Michael E. schrieb:
Geschmackssache. Aber kannst du bitte noch zwei nicht triviale Algorithmen posten? Danke.
Ausnahme mäßig ja, zwei vergleichsweise kleinen Algorithmen s_convert_toUpper & s_get_lenght:
const char* s_convert_toUpper(const char* string) { if(string[0] == '\0') return ""; const char* buffer_out; unsigned int buffer_size = S_BUFFER_STARTSIZE; char* buffer = new char[buffer_size]; unsigned int pos_str; for(pos_str = 0; string[pos_str] != '\0'; pos_str++) { if(pos_str > buffer_size) { buffer_size *= 2; char* buffer_sec = buffer; buffer = new char[buffer_size]; unsigned int pos_b = 0, pos_bs = 0; for(pos_b = 0, pos_bs = 0; buffer_sec[pos_bs] != '\0'; pos_b++, pos_bs++) { buffer[pos_b] = buffer_sec[pos_bs]; } buffer[pos_b] = '\0'; } //if character is a small one if(string[pos_str] <= 122 && string[pos_str] >= 97) buffer[pos_str] = (string[pos_str] - 32); else buffer[pos_str] = string[pos_str]; } buffer[pos_str] = '\0'; buffer_out = buffer; return buffer_out; }unsigned int s_get_lenght(const char* string) { unsigned int count; for(count = 0; string[count] != '\0'; count++); return count; }Nahezu alle Algorithmen funktionieren durch Iteration, man geht Stück für Stück durch die Zeile...
Mehr werde ich leider nicht veröffentlichen dürfen...
-
WTF machst du da?
void to_lower(std::string& s) { std::transform(s.begin(), s.end(), s.begin(), std::tolower); }
-
Das habe ich mir schon fast gedacht. Soviel zum Thema "getestet".
const char* s_convert_toUpper(const char* string) { if(string[0] == '\0') return "";Hier gibst du einen Pointer auf "" zurück, im Normalfall aber mit new angelegten Speicher. Soll der Aufrufer nun den Rückgabewert deleten oder nicht?
const char* buffer_out; unsigned int buffer_size = S_BUFFER_STARTSIZE; char* buffer = new char[buffer_size]; unsigned int pos_str; for(pos_str = 0; string[pos_str] != '\0'; pos_str++) { if(pos_str > buffer_size)Falsche Bedingung. Bereits für pos_str == buffer_size musst du das Array vergrößern.
{ buffer_size *= 2; char* buffer_sec = buffer; buffer = new char[buffer_size]; unsigned int pos_b = 0, pos_bs = 0; for(pos_b = 0, pos_bs = 0; buffer_sec[pos_bs] != '\0'; pos_b++, pos_bs++) { buffer[pos_b] = buffer_sec[pos_bs]; }Da du buffer_sec nicht nullterminiert hast, funktioniert dieses Kopieren (warum benutzt du eigentlich nicht eine Kopiermethode aus der Standardbibliothek wie memcpy?) nicht. Außerdem deletest du das alte Array nicht, sodass du ein Speicherleck hast.
Immer noch sicher, dass du nicht std::string benutzen möchtest, wo die Funktion ein Einzeiler ist?
-
RussianTux schrieb:
Nahezu alle Algorithmen funktionieren durch Iteration, man geht Stück für Stück durch die Zeile...
Und was genau ist an dem Scheiß jetzt besser als richtiges C++?
RussianTux schrieb:
Mehr werde ich leider nicht veröffentlichen dürfen...
Finde ich auch.
Michael E. schrieb:
Das habe ich mir schon fast gedacht. Soviel zum Thema "getestet".
const char* s_convert_toUpper(const char* string) { if(string[0] == '\0') return "";Hier gibst du einen Pointer auf "" zurück, im Normalfall aber mit new angelegten Speicher. Soll der Aufrufer nun den Rückgabewert deleten oder nicht?
Die naheliegende Lösung: Nie irgendwas freigeben

Ist sogar total effizient, man spart ja die ganzenfree-Aufrufe.
Alle modernen Sprachen haben einen GC, also sollte das kein Problem sein.
-
Man könnte jetzt noch hinzufügen, dass der Code implizit auch noch annimmt, dass das System einen ASCII-konformen Zeichensatz verwendet der auf gar keinen Fall internationalisierte Zeichen wie ä,ö, und ü enthält. Ich kenne aus dem Stehgreif Systeme, bei denen der Code nicht zufriedenstellend funktioniert - zum Beispiel an dem wo ich gerade sitze. Aber ich kenne kein System, wo es nicht zumindest die c-Version von toupper gibt.
-
TyRoXx schrieb:
Und was genau ist an dem Scheiß jetzt besser als richtiges C++?
Zum Glück ist volkard momentan irgendwie abwesend, der wäre glatt vom Balkon gesprungen hätte er den Code lesen müssen.
-
Nur um das nochmal klarzustellen: Meine Bitte nach Code war nicht, um sich über dich lustig zu machen. Mir war ziemlich klar, dass dein Code ungefähr so aussehen würde und dass du dir der Probleme nicht bewusst bist. Manchmal muss man aber glaube ich die Leute etwas auflaufen lassen, damit sie sich von besseren Lösungen überzeugen lassen

-
Man muss aber dazu sagen, dass es natürlich auch mit c-strings viel schöner ginge:
const char* toUpper(const char* str){ std::size_t size = std::strlen(str); const char* result = new char[size]; std::transform(str,str+size,result,std::toupper); return result; }Der Aufrufer muss sich natürlich immer noch mit dem delete rum plagen, das würde einem erst der string abnehmen:
std::string toUpper(std::string const& str){ std::string result(str.size()); std::transform(str.begin(),str.end(),result.begin(),std::toupper); return result; }Aber wie du siehst wird der Code dadurch schon viel übersichtlicher und eine Menge der ätzenden Fehlerquellen werden einem abgenommen.
-
Achja, wenn ein Dreißigzeiler zu dein kleinen Algorithmen gehört und du für 16 Algorithmen 1500 Zeilen veranschlagst, wie groß ist dann erst dein größter Algorithmus? Kann man da überhaupt noch durchblicken? Drei deiner Algorithmen haben wir ja bereits ersetzt. Fehlen noch 13
Wie heißen sie?
-
Michael E. schrieb:
Achja, wenn ein Dreißigzeiler zu dein kleinen Algorithmen gehört und du für 16 Algorithmen 1500 Zeilen veranschlagst, wie groß ist dann erst dein größter Algorithmus? Kann man da überhaupt noch durchblicken? Drei deiner Algorithmen haben wir ja bereits ersetzt. Fehlen noch 13
Wie heißen sie?Leute Leute, muss ich mich hier komplett entblößen

unsigned int s_get_lenght(const char* string); const char* s_get_fraction(const char* string, const char* delimiter, unsigned int position); const char* s_get_fraction_atFront(const char* string, const char* delimiter); const char* s_get_fraction_atEnd(const char* string, const char* delimiter); const char* s_convert_toUpper(const char* string); const char* s_convert_toLower(const char* string); const char* s_filter_numeral(const char* string, bool ovw /*= true*/, const char* ovw_s /*= "*"*/); const char* s_filter_specsym(const char* string, bool ovw /*= true*/, const char* ovw_s /*= "*"*/); const char* s_filter_string(const char* string, const char* fstring, bool ovw /*= true*/, const char* ovw_s /*= "*"*/); const char* s_append(const char* string, const char* addition, unsigned int position, bool ovw /*= false*/, const char* ovw_s /*= "*"*/); const char* s_append_atFront(const char* string, const char* addition, bool ovw /*= false*/); const char* s_append_atEnd(const char* string, const char* addition); const char* s_cut_out(const char* string, unsigned int from, unsigned int to /*= 0*/); const char* s_cut_off(const char* string, unsigned int from, unsigned int to /*= 0*/); unsigned int s_split(const char* string, const char* delimiter); bool s_compare(const char* string_1, const char* string_2);
-
Ich versteh' grad nicht, wieso das hier
std::transform(s.begin(), s.end(), s.begin(), std::toupper);diesen Fehler hier verursacht
Fehler: keine passende Funktion für Aufruf von »transform(std::basic_string<char>::iterator, std::basic_string<char>::iterator, std::basic_string<char>::iterator, <unaufgelöster überladener Funktionstyp>)«|, und das hier
std::transform(s.begin(), s.end(), s.begin(), toupper);funktioniert. Warum ist das so?
-
<ctype.h> statt <cctype> eingebunden?
-
Flüchtigkeitsfehler. Es kollidieren toupper(int) und toupper(charT, locale) im namespace std miteinander und der Compiler braucht Hilfe bei der Entscheidung. da du noch die alte c-version mit eingebunden hast, kommt die Kollision im globalen namensraum nicht zustande.
immernoch ungetestet
int (*applyUpper)(int) = std::toupper; std::transform(s.begin(), s.end(), s.begin(), applyUpper);