char nervt mich langsam echt (chars kopieren und so)
-
hallo,
ich verzweifel bald mit den chars
ich möchte eine methode schreiben, die ein Objekt meiner Stirngklasse zurückgibt, und darin ein SubString enthalten ist...hier mein versuch, einen substirng aus einem char zu holen, vergebens:
MyString MyString::SubString(int pos,int n) { char* temp = new char[n+1]; int posi=0; int counter = 0; for(int i=pos;i<n;i++) { temp[posi]=m_text[i]; posi++; counter++; } MyString t(temp); delete[] temp; return t; }ausser das er mit ner zugriffsverletzung abbricht, ist der substring auch nicht der, der er sein soll...es sind dauernt noch lustige zeichen mit drin!
kann mir bitte einer mal genau erklären wie ich sowas mit chars chararrays und so mache?
ich WILL kein string verwenden....
-
Die Schleifenbedingung scheint nicht zu stimmen, statt i < n würde ich eher posi < n erwarten, n ist ja die Länge des Substrings und nicht die Endposition.
Und machst du im Konstruktor eine tiefe Kopie oder übernimmst du einfach den übergebenen Zeiger?
-
also mein copy ctor sieht so aus:
MyString::MyString(const MyString& Obj) { int copysize = strlen(Obj.m_text)+1; this->m_buffersize = Obj.m_buffersize; m_text = new char[m_buffersize]; strncpy(m_text,Obj.m_text,copysize); StringLeng = strlen(m_text); }schleife hab ich angepasst
-
Und noch ein Punkt: Wenn du mit strlen() und Co. arbeitest, sind die '\0' am String-Ende enorm wichtig - andernfalls wird der String mit den Daten fortgesetzt, die hinter deinem char-Array gerade im Speicher stehen.
-
MyString t(temp) ruft aber den Construktor der ([const] char
erwartet auf, von daher nutzt uns der Copy Constructor nix 
Ich würde meinen am Ende der Schleife fehlt ein temp[posi]='\0' (ein Zeichen für das Nullbyte reservierst Du ja oben sogar).
-
LordJaxom schrieb:
MyString t(temp) ruft aber den Construktor der ([const] char
erwartet auf, von daher nutzt uns der Copy Constructor nix 
Ich würde meinen am Ende der Schleife fehlt ein temp[posi]='\0' (ein Zeichen für das Nullbyte reservierst Du ja oben sogar).
sorry
den hab ich natürlich auch:
MyString::MyString(const char* text,unsigned int buffersize=20) { int copysize = strlen(text)+1; if(strlen(text)>=buffersize) buffersize+=BUFFER; m_buffersize = buffersize; m_text = new char[buffersize]; strncpy(m_text,text,copysize); StringLeng = strlen(m_text); }
-
Weiß nicht ob es dir hilft, aber ich kann dir mal meine Realisierung geben. Allerdings habe ich die Zielklasse als Parameter, da ich unkontrollierte Objekterzeugungen nicht so mag - kannst du ja abändern.
void CString::GetString (CString& xTarget, uint32 uStartPos, uint32 uCharCount) const { FX_ASSERT(&xTarget != this); if (!uCharCount || uStartPos >= this->GetLength()) { xTarget.Reset(); return; } if (uStartPos + uCharCount > this->GetLength()) uCharCount = this->GetLength() - uStartPos; xTarget.SetLength (uCharCount); memcpy (xTarget.cString, &this->cString[uStartPos], uCharCount); }
-
asdasd schrieb:
sorry
den hab ich natürlich auch:
...Wie erwartet - der nutzt auch strlen() für die Längenbestimmung und läuft deshalb vermutlich über's Ziel hinaus.
Mal ausführlich: strlen() zählt einfach nur die Zeichen, bis es auf ein '\0' stößt. Deine temp-Zeichenkette hat selber kein abschließendes '\0', deshalb zählst du über das Ende des von dir reservierten Bereiches hinaus, bis du zufällig auf eine 0 im Speicher stößt - und diese ganzen Mülldaten werden später noch "offiziell" gemacht, indem du sie in deinen String reinkopierst.
(wenn du Glück hast, schaffst du es bis zum Systembereich und dann kollabiert das Programm mit einem SegFault :D)Wie du das Problem lösen kannst, hat LordJaxom schon angedeutet:
MyString MyString::SubString(int pos,int n) { char* temp = new char[n+1]; int posi=0; int counter = 0; for(int i=pos;i<n;i++) { temp[posi]=m_text[i]; posi++; counter++; } //ganz wichtig: temp[posi]='\0'; MyString t(temp); delete[] temp; return t; }(und eventuell könntest du noch ein "if(m_text[i]=='\0') break;" an den Anfang der Schleife setzen - für den Fall, daß jemand einen zu langen SubString anfordert)
-
besser wäre, dem Konstructor MyString::MyString(const char*,int) eine sinnvolle implemntierung zu geben. mit der jetzigen version ist der zweite parameter im grunde sinnlos - der zweck sollte ja wohl sein, dass es gerade nicht auf das vorhandensein eines terminators ankommt (im übrigen könnte ein string ja auch eingebette \0 zeichen haben). das bedeutet auch den verzicht auf einen defaultparameter, denselben effekt erreichen wir durch überladung:
MyString::MyString(const char* s) : m_buffersize(strlen(s)+1), m_text(new char[m_buffersize]) { memcpy(m_text,s,m_buffersize); } MyString::MyString(const char* s, int n) : m_buffersize(n+1), m_text(new char[m_buffersize]) { memcpy(m_text,s,n); m_text[n]='\0'; }dann wird auch SubString sehr einfach und wir vermeiden unnötiges kopieren:
MyString MyString::SubString(int pos,int n) const { return MyString(m_text+pos,n); }