AnsiString und Operatoren
-
Ich verstehe nicht, wie und unter welchen Bedingungen auf AnsiStrings die Operatoren z.B. [],+= anwenden darf/kann.
Beispielproblem: Im Eintragsfeld ReinerTextEdt steht der Text "SOS", klick auf die Schaltfläche ÜbersetzeBtn trägt im Feld MorsecodeEdt den entsprechenden Morsecode ein. Ich würde das gern wie folgt lösen:void __fastcall TForm1::UebersetzeBtnClick(TObject *Sender) { for(int i=0;ReinerTextEdt->Text[i];i++){ if (ReinerTextEdt->Text[i]=='O') { MorsecodeEdt->Text+="---"; } else if (ReinerTextEdt->Text[i]=='S'){ MorsecodeEdt->Text+="..."; } } }
Dies funktioniert nicht! Schon in der for-Zeile wird ein Laufzeitfehler "Zugriffsverletzung" ausgelöst. Ich vermute den Operator [] als Verursacher.
Folgendes funktioniert, halte ich aber für ausgesprochen unelegant.
void __fastcall TForm1::UebersetzeBtnClick(TObject *Sender) { string sText = ReinerTextEdt->Text.c_str(); string sMCode = ""; for(int i=0;sText[i];i++){ if (sText[i]=='O') { sMCode+="---"; } else if (sText[i]=='S'){ sMCode+="..."; } } MorsecodeEdt->Text=sMCode.c_str(); }
Insbesondere musste ich auch den String sMCode einführen, da der "append-Operator" += auf dem AnsiString MorscodeEdt->Text auch nicht zu funktionieren scheint.
Gibt es jemand der mir das erklären kann und vielleicht eine elegantere Lösung zeigen könnte? Vielen Dank im voraus!
Manfred Hoffmann
-
manna schrieb:
Ich vermute den Operator [] als Verursacher.
Da vermutest du richtig. Bei AnsiString beginnt die Zählung bei 1 und nicht bei 0 wie sonst bei C++ üblich.
Deine Frage gehört aber eher in das BCB-Forum.
-
Dieser Thread wurde von Moderator/in HumeSikkins aus dem Forum C++ in das Forum VCL (C++ Builder) verschoben.
Im Zweifelsfall bitte auch folgende Hinweise beachten:
C/C++ Forum :: FAQ - Sonstiges :: Wohin mit meiner Frage?Dieses Posting wurde automatisch erzeugt.
-
Vielen Dank Braunstein für die sehr schnelle und präzise Antwort. Ich bin ganz neu in diesem Forum, deshalb habe ich offensichtlich die falsch Forumecke gewählt: sorry.
Ich habe das nun korrigiert(siehe unten), aber eine Sache verstehe ich immer noch nicht. Warum funktioniert z.B. MorsecodeEdt->Text+="---"; nicht?
void __fastcall TForm1::UebersetzeBtnClick(TObject *Sender) { for(int i=1;i<=ReinerTextEdt->Text.Length();i++){ if (ReinerTextEdt->Text[i]=='O') { MorsecodeEdt->Text+="---"; } else if (ReinerTextEdt->Text[i]=='S'){ MorsecodeEdt->Text+="..."; } } }
Grüße - besonders Braunstein
Manna
-
Weil Dir wahrscheinlich eine Kopie des Stringes durch den Property gegeben wird.
MorsecodeEdt->Text = MorsecodeEdt->Text + "...";
-
Nicht wahrscheinlich, sondern genau deswegen.
-
Ich denke, es wäre vernünftig, aus den oben genannten Gründen, die Strings in den TEdits vorher zwischenzuspeichern, dann auf diesen Strings zu arbeiten und dann bei Bedarf wieder zurückzuschreiben.
void __fastcall TForm1::UebersetzeBtnClick(TObject *Sender) { AnsiString reinerText(ReinerTextEdt->Text), morsecode(MorsecodeEdt->Text); for(int i=1;i<=reinerText.Length();i++){ if (ReinerText[i]=='O') { morsecode+="---"; } else if (reinerText[i]=='S'){ morsecode+="..."; } } MorsecodeEdt->Text = morsecode; }
-
Yipii - jetzt funktioniert es,
man vergisst doch immer wieder gern beim + Zeichen, dass String-Verkettung eben nicht kommutativ ist, im Gegensatz zur Addition von Zahlen.Danke euch allen!
Manna
PS: Hier noch der (elegantere) lauffähige Code
void __fastcall TForm1::UebersetzeBtnClick(TObject *Sender) { for(int i=1;i<=ReinerTextEdt->Text.Length();i++){ if (ReinerTextEdt->Text[i]=='O') { MorsecodeEdt->Text = "---" + MorsecodeEdt->Text; } else if (ReinerTextEdt->Text[i]=='S'){ MorsecodeEdt->Text = "..." + MorsecodeEdt->Text; } } }
-
Hallo,
ich würde aber das nächste übersetzte Zeichen aus ReinerText dann an MorseText anhängen, anstatt es davor zu setzen. Du gehst ja mit der for-Schleife ReinerText von links nach rechts durch, also solltest du das letzte übersetzte Zeichen auch an MorseText ganz rechts anhängen:
void __fastcall TForm1::UebersetzeBtnClick(TObject *Sender) { for(int i= 1; i <= ReinerTextEdt->Text.Length(); i++){ if(ReinerTextEdt->Text[i]=='O') { // ALT MorsecodeEdt->Text= "---" + MorsecodeEdt->Text; MorsecodeEdt->Text= MorsecodeEdt->Text + "---"; // Besser } else if(ReinerTextEdt->Text[i]=='S') { // ALT MorsecodeEdt->Text= "..." + MorsecodeEdt->Text; MorsecodeEdt->Text= MorsecodeEdt->Text + "..."; // Besser } } }
Bei Palindromen (Zeichenketten die rückwärts gelesen werden können) wie "SOS" oder "Reliefpfeiler" mag das egal sein, aber wenn du ein Programm schreiben willst, das dir beliebige Zeichenketten ins Morsealphabet übersetzt würde das auffallen.
MfG
-
Hai Kolumbus,
du hast recht! Vielen Dank. Der Vollständigkeit halber die finale Version und ein Verständnisfrage:void __fastcall TForm1::UebersetzeBtnClick(TObject *Sender) { for(int i=1;i<=ReinerTextEdt->Text.Length();i++){ if (ReinerTextEdt->Text[i]=='O') { MorsecodeEdt->Text = MorsecodeEdt->Text + "---"; } else if (ReinerTextEdt->Text[i]=='S'){ MorsecodeEdt->Text = MorsecodeEdt->Text + "..."; } } }
Ich muss nämlich zugeben, dass ich den Beitrag von witte und Joe_M. doch noch nicht ganz verstanden habe. Ich habs ja umgeschrieben, weil MorsecodeEdt->Text+="---"; usw. nicht funktioniert. Was jetzt da steht (MorsecodeEdt->Text = MorsecodeEdt->Text + "---";) ist doch nach meinem Verständnis das Gleiche, aber offensichtlich doch nicht! Wo ist denn da mein Denkfehler?
Gruß an alle und einen besonderen an den Käpt'n der Santa Maria
Manna
-
Ok, zum Thema TEdit::Text. Dies ist eine Eigenschaft (Property). Auch wenn sie wie eine ganz normale Variable aussieht, verbirgt sich dahinter eine Getter- und eine Setterfunktion. Wenn Du also die Eigenschaft Text ausliest, wird im Hintergrund eine Funktion aufgerufen, die einen temporären AnsiString erzeugt und Dir diesen zurückgibt.
Ist das so verständlicher?
-
Danke Joe_M.,
das ist mir schon klar, obwohl mir der unterschiedliche Verhalten += und explizitem + nicht klar ist. Um das Beispiel weiter zu reduzieren:Edit->Text = Edit->Text + String-Literal; | |----+---| | | | +- Lesezugriff wird umgesetzt durch Funktionsaufruf getter- | Funktion z.B. getText() --> tempString | +- Zuweisungsoperator = Schreibzugriff, wird umgesetzt durch setter- Funktion z.B. setText(tempString + String-Literal) --> void
Was mir nicht in den Kopf will, dass diese Anweisung funktioniert, aber die Formulierung
Edit->Text += String-Literal;
nicht. += ist doch nur die abkürzende Schreibweise für die explizite Form mit + (siehe oben)
Troztdem Danke, dass du dir soviel Mühe gibst, aber ich check das einfach nicht!
Gruß Manna
-
Wieso ist += abkürzend in diesem überladenen Szenario? Der Setter überschreibt/ersetzt den originalen Text der Textbox. Bei += ist das Ziel der temporäre String, bei = das Original.
-
Ja und genau da kommen die Getter- und Setter-Methoden ins Spiel.
Edit1->Text += "BlaBlubb";
Hier wird zuerst die Getter Methode aufgerufen und ein temporäres Objekt erzeugt, dem dann das Literal angehängt wird. Die Setter Methode wird nicht aufgerufen, kann auch nicht, da Edit1->Text durch ein temporäres Objekt ersetzt wurde. Alle nachfolgenden Aktionen werden nur auf das temporäre Objekt ausgeführt.
Ich weiß nicht mal, ob es technisch möglich wäre, an dieser Stelle den Setter auch noch zu refenzieren, Borland hat es jedenfalls nicht implementiert.Edit1->Text = Edit1->Text + "BlaBlubb";
Hier wird jetzt links vom Gleichheitszeichen der Setter aufgerufen und rechts der Getter. Deshalb funktioniet das.
-
Ich glaube jetzt habe ichs auch kapiert. An manche "Automaten" muss man eben klopfen, bis der Groschen fällt. Vielen Dank an Joe_M. und witte für die tiefer gehende Einsicht, das war wirklich hilfreich!
Beste Grüße
Manna
-
Hallo,
der Vollständigkeit halber noch ein Auszug aus der Hilfe zu AnsiString - operator +=:
BCB-Hilfe schrieb:
Das AnsiString-Objekt wird mit rhs verkettet. Das Ergebnis wird dem AnsiString-Objekt zugewiesen.
AnsiString& __fastcall operator +=(const AnsiString& rhs);
Beschreibung
Der Operator wird für Eigenschaften mit Abruf- und Zuweisungsfunktionen nicht unterstützt.
Objekteigenschaften die den Typ AnsiString haben (wie TEdit->Text) können eben grundsätzlich mit += nicht modifiziert werden.
manna schrieb:
Gruß an alle und einen besonderen an den Käpt'n der Santa Maria
Jo Danke, auch wenn wir die Santa Maria kurz nach Weihnachten 1492 zerlegt haben, um mit ein paar einfachen Hütten La Navidad auf Hispaniola zu gründen... Die Santa Maria war eh' im Eimer, weil der Steuermann gepennt hat und wir auf eine Sandbank aufgelaufen sind... Auf meinen späteren Reisen hatte ich dann andere Schiffe.
MfG
-
Auch dir Kolumbus noch einmal herzlichen Dank und ein kräftiges "Schiff ahoi, ...auf ,auf zu neuen Ufern!"
Gruß Manna