C++: Wie kann ich den String mit meinem Ansatz umdrehen?
Ich habe die Aufgabe bekommen, einen String in C++ einzulesen und anschließend in umgekehrter Reihenfolge wieder auszugeben.
Beispiel: "Hallo" --> "ollaH"
Könnte mir jemand sagen, wo mein Fehler in der Logik ist?
Ich weiß, ich könnte die Aufgabe so lösen, wenn ich die for-Schleife einfach umstelle, aber leider hat mich der Ehrgeiz gepackt und möchte Sie in der Form meines Ansatzes lösen.
(Alle Bibliotheken sind eingebunden)
int main (void)
{
string s;
cin >> s;
size_t i;
int h;
cout << s << endl;
for (i=0; i < s.length(); i++) {
s[s.length() - i] = s[s.length() + 5];
s[i] = s[s.length() - i];
s[s.length() + 5] = s[i];
}
cout << s << endl;
return 0;
}
Meine Denkweise: Mit dem Beispiel "Hallo" --> H=0, a=1, l=2, l=3, o=4
Die letzte Ziffer meines Strings speichere ich zwischen auf eine Stelle irgendeine Stelle (hier 5). Danach setze ich die Ziffer an der Stelle i ganz nach hinten - i.
Stelle 0 = 4, Stelle 1 = 3, Stelle 2 = 2, Stelle 3 = 1, Stelle 4 = 0
Danach setze ich die zwischengespeicherte Stelle auf den Platz i.
4 Antworten
Naja, du musst doch nur solange die x-te und (length-x)-te Stelle tauschen, bis du die Hälfte erreicht hast.
Also (ungetestet)
For(i=0; i < s.length()-i; i++){
Temp_char = s[i];
s[i] = s[s.length()-i]; //oder -i-1? Das letzte Byte ist ja meistens das Nullbyte
s[s.length()-i] = Temp_char;
}
Mich würde es aber wundern, wenn für das Umdrehen der Array-Elemente nicht schon eine Funktion existieren würde.
Desweiteren musst du entweder überall length()-1-i machen oder nirgends. Aber nicht gemischt. Ist leider etwas länger her, dass ich c++ genutzt habe. Bei "Hallo", gibt da s.length() 4 aus, oder 5? Ich denke 5, daher musst du überall -1 nehmen, da das Array ja nur von 0 bis 4 geht. Bei i=0 muss also s[0] mit s[4] getauscht werden. 4 wäre 5-1-0, usw..
Du kannst nicht einfach das letzte Byte deines Strings als 'buffer' missbrauchen. In diesem Byte steht eine Null, die festlegt wo der String endet. Leg dir also bitte ein temporäres char an wenn du ein Zeichen zwischenspeichern möchtest, ohne dir deinen originalen String zu zerschießen.
Und abgesehen davon tauschst du in jedem Schleifendurchlauf immer 2 Zeichen miteinander, du musst also nur halb so oft durch die Schleife wie der String lang ist
Jo das mit der Zahl 5 war ne Schnaps idee, ist mir jetzt auch so gekommen...
Ich habe jetzt das Programm so umgeändert:
for (i=0; i > (s.length()-i); i++)
{
h=s[i];
s[i]=s[s.length()-i-1];
s[s.length()-i]=h;
Wo liegt jedoch hier der fehler? h ist natürlich als Char deklariert worden.
Naja, wie bereits gesagt darf die Schleife nur laufen solange i < length/2 ist, du tauschst ja die erste Hälfte mit der zweiten. Und zusätzlich musst du beim zurückschreiben von 'h' in den eckigen Klammern natürlich auch am Ende wieder 1 abziehen, nicht nur 'i'
Lecko Mio, vielen dank... es funktioniert!
Gut zu Wissen das mein Ansatz nicht von Grundauf falsch war. Der Fehler im String rumzupfuschen war einfach nicht nachgedacht...
Oh, und die Bedingung in deiner Schleife macht so überhaupt keinen Sinn, nach deiner Logik darf die Schleife nur betreten werden wenn 'i' größer als die Länge vom Text ist, was schon bei der ersten Überprüfung nicht stimmt, weswegen deine Schleife niemals betreten wird.
Am besten siehst du dir mal im Debug-Modus an, was dein Programm Zeile für Zeile anstellt
Man kann es sich natürlich unnötig schwer machen :-).
Anstatt im String rumzupfuschen (Den Swap würde man in einer temporären Variable machen), nutze doch die Möglichkeiten:
std::reverse(s.begin(),s.end());
Sonst eben auch reverse_copy.
Und im Zweifelsfall kannst Du auch eine Reverse Iterator Instanziierung machen.
Alles geht, nichts muß.
Leider bin ich in meinem jetzigen Stand nicht dazu in der Lage auf sämtliche Tricks in C++ zuzugreifen. Ich Lerne es ja gerade noch :)
Es würde auch so gehen:
for (int i= s.length()-1; i >=0; i--)
Ich muss leider gestehen das ich auf diese Lösung nicht selbst gekommen bin.
Daher will ich es anhand der Logik lösen. Das es da vmtl sämtliche Tipps und Tricks gibt ist mir bewusst. Aber so lerne ich es leider nicht.. :)
Ich würde das ausnutzen einer Funktion in der Standardbibliothek nicht unbedingt als Trick sehen ;)
Wenn DU die Zeichen einzeln ausgeben willst, sicher, aber:
for ( auto: i=s.crbegin(); i!=s.crend(); i++) std::cout << *i;
oder vielleicht eher:
std::for_each ( s.rbegin(), s.rend(), [](const char &c){ std::cout << c; } )
Wie es am besten schmeckt.
Oder wie bereits erwähnt:
std::cout << std::string(s1.crbegin(),s2.crend());
oder ....
Und nein, das sind keine 'Tricks' - insbesondere das letzte Beispiel benutzt einfach nur die Fähigkeiten der Stringklasse selbst.
Was geht denn nicht bei deinem Ansatz?
Was aber sicher Falsch ist, ist dass Du i mal tauschst. Bei einer i langen Zeichenkette musst du nur i/2 oft tauschen.
Ausserdem solltest du nicht da hinten im sting an stelle 5 rumpfuschen. Nimm eine eigene Variable dafür
Es kommt immer nur das selbe raus..
Sprich 12345 --> 12345
dann schreibe ich es so schonmal um:
for (i=0; i <= (s.length()/2); i++)
meine for schleife sind nun wie folgt aus:
for (i=0; i <= (s.length()/2); i++)
{
s[s.length()-i]=h;
s[i]=s[s.length()-i];
h=s[i];
ich hab nun die 1. Zeile geändert in
h=s[s.length()-i];
bisher verstehe ich aber deine einwände :)
Leider sieht die situation nach wie vor gleich aus. Wird nich umgekehrt :s
Das ist mein Quelltext den ich von dir genommen habe, leider ist der fall immernoch derselbe: Bsp: 12345 --> 12345