String-Klasse als Vorbild gesucht
-
Möchte eine eigene Stringklasse (char) entwickeln. Wo findet man ein bezüglich OOP und C++ vorbildliches Beispiel?
-
std::string?
*duck*
-
Die ist zu kompliziert. Außerdem kommt man da nicht an den Sourcecode ran.
-
Doch, gibt ja durchaus auch freie Implementierungen, allerdings war das nicht ganz ernstgemeint; std::string (bzw. dessen Interface) wird ja immer wieder gerne als einer der größten Designfehler der Standardlibrary bezeichnet.
Fang einfach mal mit einer sauberen Stringklasse an bei der alle 0815-Operatoren verwendbar sind, das ist nicht allzu schwer, reicht aber für den Anfang mal aus.
-
gibt ja durchaus auch freie Implementierungen
kann mir bitte jemand einen Link auf eine freie volleinsehbare String-Klasse geben? finde nix mit google. In C++-Tutorials macht auch keiner so was.
-
Naja, zumindest bei meiner gcc reicht ein Blick nach /usr/lib/gcc-lib/i686-pc-linux-gnu/3.3.3/include/g++-v3/string.
-
Hi!
Ich habe hier eine aus einem Buch, die ich dir schicken könnte, wenn du mir deine Mailaddy gibst.
Code-Hacker
-
STLPort ist ne ziemlich gute STL-Implementierung. Ansonsten hat wxWidgets ne Klasse wxString dabei, und glibmm liefert Glib::string - ich denke, das sollte für den Anfang reichen.
-
Ansonsten hat wxWidgets ne Klasse wxString dabei, und glibmm liefert Glib::string - ich denke, das sollte für den Anfang reichen.
ähm, er suchte ein vorbildliches Beispiel.
-
Hier habe ich einen Ansatz für eine String-Klasse gepostet, der ist aber leider auch nicht besonders gut, zumindest copy-con, op= kannst du anschauen:
http://www.c-plusplus.net/forum/viewtopic.php?t=83500In der Literatur oder im Internet fällt mir jetzt auch kein vorbildliches Beispiel ein. Muss nochmal in meine Bücher schauen.
Bei Till Jeske, C++, Addison-Wesley findet sich eine rudimentäre Stringklasse, die aber nicht vollständig ist.
-
Wär es bei ner Stringklasse nicht praktischer, wenn operator[] eine Referenz auf einen char zurückgeben würde?
-
// [] char MyString::operator[]( int i ) const { if( i >= 0 && i < getLaenge() ) { return pData_[i]; } else { return '\0'; } }
Meinst du dies hier? Eine Referenz auf einen char? hmmm.
Ich denke, nein.
-
Hi!
Ich habe mal eben die Stringklasse hochgeladen:
Header: s. Erhard Henkes
Cpp: s. Erhard HenkesCode-Hacker
-
Damit man leichter diskutieren kann, hier der Code (von Code-Hacker):
#include <conio.h> #include <iostream> #include <vector> #include <cassert> using namespace std; class EString { private: static const unsigned long FWDBUFFER=15; static const unsigned long INPBUFFER=200; char* string; unsigned long len; unsigned long bufsize; void replace(const char*); void replace(const vector<char>& v); void insert(unsigned long, unsigned long, const char*); public: EString(); EString(const char*); EString(const char); EString(const EString&); ~EString(); EString& operator=(const EString&); EString& operator=(const char*); EString& operator=(const char); friend ostream &operator<<(ostream&, const EString&); friend istream &operator>>(istream&, EString&); EString& operator+=(const EString&); EString& operator+=(const char*); EString& operator+=(const char); friend const EString operator+(const EString&, const EString&); const EString operator+(const char*) const; const EString operator+(const char) const; friend const EString operator+(const char*, const EString&); friend const EString operator+(const char, const EString&); char &operator[](unsigned long); const char &operator[](unsigned long) const; EString operator()(unsigned long, unsigned long) const; bool operator<(const EString&) const; bool operator<=(const EString&) const; bool operator==(const EString&) const; bool operator!=(const EString&) const; bool operator>=(const EString&) const; bool operator>(const EString&) const; }; /* ** Private Methoden (technische Methoden) */ void EString::replace(const char *s) { if(string) delete[](string); len=strlen(s); bufsize=FWDBUFFER+len+1; string=new(char[bufsize]); assert(string!=0); strcpy(string,s); } void EString::replace(const vector<char>& v) { if(string) delete[](string); len=v.size(); bufsize=FWDBUFFER+len+1; string=new(char[bufsize]); assert(string!=0); unsigned int x=0; for (;x<v.size();x++) string[x]=v[x]; string[x]=0; } void EString::insert(unsigned long pos, unsigned long slen, const char *s) { if(!string) { len=slen; bufsize=FWDBUFFER+len+1; string=new(char[bufsize]); assert(string!=0); strcpy(string,s); return; } else { if((len+slen+1)<=bufsize) { for(unsigned long x=len+1;x>=pos+1;x--) string[x+slen-1]=string[x-1]; for(unsigned long x=0;x<slen;x++) string[x+pos]=s[x]; len+=slen; } else { bufsize=FWDBUFFER+len+slen+1; char *sptr=new(char[bufsize]); assert(sptr!=0); unsigned long y=0,x; for(x=0;x<pos;x++) sptr[y++]=string[x]; for(x=0;x<slen;x++) sptr[y++]=s[x]; for(x=pos;x<=len;x++) sptr[y++]=string[x]; len+=slen; delete[](string); string=sptr; } } } /* ** Konstruktoren und Destruktoren */ EString::EString(void) { len=0; bufsize=0; string=0; } EString::EString(const char *s) { string=0; replace(s); } EString::EString(const char c) { string=0; char s[2]; s[0]=c; s[1]=0; replace(s); } EString::EString(const EString &s) { string=0; replace(s.string); } EString::~EString() { if(string) delete[](string); } /* ** Zuweisung */ EString &EString::operator=(const EString &s) { if(this==&s) return(*this); replace(s.string); return(*this); } EString &EString::operator=(const char *s) { replace(s); return(*this); } EString &EString::operator=(const char c) { char s[2]; s[0]=c; s[1]=0; replace(s); return(*this); } /* ** Ein-/Ausgabe-Operatoren */ ostream &operator<<(ostream &ostr, const EString &s) { if(s.len) ostr << s.string; return(ostr); } istream &operator>>(istream &istr, EString &s) { char c; vector<char> inp; while(!isspace(c=static_cast<char>(istr.get()))) inp.push_back(c); s.replace(inp); return(istr); } /* ** Additions-Operatoren */ EString &EString::operator+=(const EString &s) { insert(len,strlen(s.string),s.string); return(*this); } EString &EString::operator+=(const char *s) { insert(len,strlen(s),s); return(*this); } EString &EString::operator+=(const char c) { insert(len,1,&c); return(*this); } const EString operator+(const EString &s1, const EString &s2) { EString tmp=s1.string; tmp.insert(tmp.len,strlen(s2.string),s2.string); return(tmp); } const EString EString::operator+(const char *s) const { EString tmp=string; tmp.insert(len,strlen(s),s); return(tmp); } const EString EString::operator+(const char c) const { EString tmp=string; tmp.insert(len,1,&c); return(tmp); } const EString operator+(const char *s, const EString &str) { EString tmp=s; tmp.insert(tmp.len,strlen(str.string),str.string); return(tmp); } const EString operator+(const char c, const EString &str) { EString tmp=c; tmp.insert(tmp.len,strlen(str.string),str.string); return(tmp); } /* ** Indizierungsoperator */ char &EString::operator[](unsigned long p) { assert(p<len); return(string[p]); } const char &EString::operator[](unsigned long p) const { assert(p<len); return(string[p]); } /* ** Funktionsaufrufoperator */ EString EString::operator()(unsigned long p, unsigned long l) const { assert((p<len)&&((p+l)<=len)); EString tmp=""; tmp.insert(0,l,string+p); return(tmp); } /* ** Vergleichsoperatoren */ bool EString::operator<(const EString &s) const {return(strcmp(string,s.string)<0);} bool EString::operator<=(const EString &s) const {return(strcmp(string,s.string)<=0);} bool EString::operator==(const EString &s) const {return(strcmp(string,s.string)==0);} bool EString::operator!=(const EString &s) const {return(strcmp(string,s.string)!=0);} bool EString::operator>=(const EString &s) const {return(strcmp(string,s.string)>=0);} bool EString::operator>(const EString &s) const {return(strcmp(string,s.string)>0);} int main() { EString s1 = "Hallo "; EString s2 = "schoene "; EString s3 = "Welt"; cout << s1+s2+s3 << endl; getch(); }
-
Erhard Henkes schrieb:
// [] char MyString::operator[]( int i ) const { if( i >= 0 && i < getLaenge() ) { return pData_[i]; } else { return '\0'; } }
Meinst du dies hier? Eine Referenz auf einen char? hmmm.
Ich denke, nein.Warum das? Dann kann ich ja das folgende gewohnte gar nicht machen:
MyString s = "hallo"; void translate() { s[1] = 'e'; }
-
Hi!
War mir nicht sicher ob ich den posten darf, da der sehr lang ist, aber wenn er hier ist, dann nehm ich ihn wieder runter.
Code-Hacker
-
Wozu braucht man diesen FWDBUFFER ? z.B. in der Funktion replace()
-
Hi!
Da der String wachsen kann/soll wird dem String gleich mehr Speicher zur Verfügung gestellt um nicht bei jeder Vergrößerung einen neuen Speicherbereich anfordern zu müssen. Somit enthält die Konstante FWDBUFFER die Anzahl Zeichen die bei jeder neuen Reservierung von Speicher zusätzlich belegt werden sollen.
Könnte man also auch weglassen, war ne Idee des Autors...
Code-Hacker
-
@KPC: du hast recht, EString verwendet ebenfalls char& als Rückgabetyp bei []
-
[Müll]
Ich vermisse Konstruktoren für Typen wie long, double, std::string, std::wstring, usw.
Aus Performancegründen kann man ja dann auch noch mal die Operatoren entsprechend überladen. Ja, das wäre allerdings viel Arbeit.Der Ritter des size_t Typs wird dir sicher auch noch einiges erzählen.
Außerdem fehlen einige komfortable Funktionen. Ich denke da an trim(), endsWith(String), startsWith(String), substring(), ...