Kleine Schwierigkeit mit Arrays: Palindrom ja oder nein?



  • seldon schrieb:

    Wenn mich grad nicht alles täuscht, sollte

    std::equal(word.begin(), word.begin() + word.size() / 2, word.rbegin())
    

    ausreichen; sonst prüft man im Erfolgsfall quasi doppelt.

    Ist natürlich richtig, an sowas hab ich gar nicht gedacht, als ich mich bemüht habe, möglichst C++-ischen Code zu schreiben 🙂



  • Ich habe mich noch mal mit der Aufgabe beschäfitigt.
    Mir ist die Idee gekommen, dass man hier auch Pointer zur Hilfe nehmen kann.

    -Zunächst wird ein String eingelesen.
    -Dieser wird im Array (arr) gespeichert.

    -Mit Hilfe eines Pointers vergleiche ich dann, ob:
    -> das 1. und letzte Element des Wortes gleich sind
    -> das 2. und vorletzte Element gleich sind

    -Sind die Bedingungen erfüllt, liegt ein Palindrom vor. Andernfalls nicht.

    #include <iostream>
    #include <conio.h>
    #include <string>
    
    using namespace std;
    
    void main() 
    {
    
    	char arr[30];
    	int i, n;
    	char *p = arr;
    
    	cout << "Deine Eingabe: ";
    	cin.getline(arr, 30);
    
    	if (arr[0] == *(p+strlen(arr)-1) && arr[1] == *(p+strlen(arr)-2) ) {
    		cout << "\n" << arr << " ist ein Palindrom!" << endl;	
    	}
    
    	else {
    		cout << "\n" << arr << " ist KEIN Palindrom." << endl;	
    	}
    
    	getch();
    }
    

    Für mich ist die Aufgabe gelöst.
    Ich danke allen, die hier Tipps und Vorschläge gepostet haben! 🙂

    PS: Ich weiß, dass mein Code umständlicher ist. Ziel war es aber anhand des Wissens, dass mir das Buch bisher lieferte eine Lösung zu finden.

    MfG
    Cruxi



  • Deine Prüfung ist aber falsch, denn du musst alle Buchstaben vergleichen, bis du bei der Hälfte bist, wie seldon erwähnt hat. Dazu benötigst du eine Schleife.
    void main() ist ebenfalls falsch, es muss int main() heißen. Und getch() ist auch nicht gerade toll, nimm lieber std::cin.get(); 😉



  • Du hast Recht.

    Danke für den Hinweis. Ich werde versuchen eine Lösung zu finden.
    Ohne Reverse-Iteratoren scheint's ziemlich kompliziert zu sein.


  • Mod

    Cruxi schrieb:

    Du hast Recht.

    Danke für den Hinweis. Ich werde versuchen eine Lösung zu finden.
    Ohne Reverse-Iteratoren scheint's ziemlich kompliziert zu sein.

    Lass dich dafür mal von meinem Code inspirieren. Das gibt dir praktisch alles vor, was du wissen musst, da der Algorithmus auf Strings wie auf Arrays funktioniert.

    Außerdem würde ich ganz dringend das strlen vor die Schleife ziehen, denn strlen ist, im Gegensatz zu string::size(), eine sehr teure Funktion und die Länge ändert sich hier nicht.



  • Für mich ist die Aufgabe gelöst.
    

    Für mich nicht.

    Ich empfehle bei allen einfachen algorithmischen Problemen, daß man es mit den Fingern plant. Außer, man ist schon so weit, daß man es im Kopf kann.

    Hier heißt das, daß man sich 20 Bit besorgt und trinkt. Es entstehen 20 Kronkorken. Die beschriftet man auf der weichen Innenseite mittels eines Kugelschreibers mit Buchstaben. Eine Auswahl davon legt man in einer Reihe vor sich als zu prüfenden String.

    Wie prüft man diesen String? Wie prüft man ihn als Mensch? Wie prüft man ihn als Mensch, wenn man sich vorstellt, daß man es mit einem so großen String zu tun hat, daß man ihn nicht direkt überschauen kann. Kurzum, wenn man so blöd ist, wie ein Computer?

    Man legt den linken Zeigefinder vor den ersten Buchstaben und den rechten Zeigefinger vor den letzten Buchstaben.
    Schleife solange die Zeigefeiner nicht zusammen sind,
    - schaut man, ob die beiden gezeigten Buchstaben gleich sind.
    - Wenn nein, war es kein Palindrom.
    - Wenn ja, rückt man die Finger um eine Position zusammen und macht mit der Schleife weiter.
    Wenn die Schleife aughört, weil die Zeigefinger sich berühren, war es ein Palindrom.

    Das führt zu zum Beispiel folgendem Code (das meiste geklaut von SeppJ):

    bool ist_palindrom(const string &wort)
    {
     int links=0;
     int rechts=wort.size()-1;
     while(links<rechts)
     {
      if(wort[links]!=wort[rechts])
       return false;
      ++links;
      --rechts;
     }
     return true;
    }
    

    Oft entstehen damit saugeile Algorithmen. Welche, die offensichtlich endschnell und sehr einfach sind. Bei einfacheren Problemen nehme ich manchmal die Zifferntasten von ^ bis 9 und stelle sie mir als Array vor, lege die Finger drunter, und operiere im Geiste rum.

    Und dann klappt es bald und ich freue ich mich wie ein Schneekönig.



  • 314159265358979 schrieb:

    Ist natürlich richtig, an sowas hab ich gar nicht gedacht, als ich mich bemüht habe, möglichst C++-ischen Code zu schreiben 🙂

    Wie ein Reh vor dem Scheinwerfer. 🕶
    Man muß stets die Implemetierungssprache im Auge behalten, damit es super wird. Aber superer als super muß es nicht werden.



  • Um mal den Trick von volkard zu klauen:

    #include <iostream>
    #include <algorithm>
    #include <iterator>
    #include <cstring>
    
    int main()
    {
            const int n = 42;
            char str[n];
    
            typedef std::reverse_iterator<const char*> cr_iter;
    
            while(std::cin.getline(str, n))
            {
                    const int length = std::strlen(str);
                    std::cout << str << " ist " << std::equal(str, str + length, cr_iter(str + length)) + "kein Palindrom.\n";
            }
    }
    

    http://www.ideone.com/hQW5y
    🤡



  • 314159265358979 schrieb:

    Um mal den Trick von volkard zu klauen:

    std::cout << str << " ist " << std::equal(str, str + length, cr_iter(str + length)) + "kein Palindrom.\n";
    

    Was war daran besser als das schon gesehene

    std::cout << word << " ist " << std::equal(word.begin(), word.end(), word.rbegin()) + "kein Palindrom.\n";
    

    ?
    Mir fällt nur eine weitere Definition cr_iter auf, daß ich, um den Code zu verstehen, an mehr Ecken zugleich lesen muß. Und daß die Zeilen zufällig genau gleich viele Zeichen haben.



  • Er wollte es doch mit einem Array haben. Ich dachte mir, mit der Definition kann er es besser lesen. Ich hätte das typedef ansonsten auch weggelassen.



  • 314159265358979 schrieb:

    Er wollte es doch mit einem Array haben. Ich dachte mir, mit der Definition kann er es besser lesen. Ich hätte das typedef ansonsten auch weggelassen.

    Achso. Jaklar. Jetzt ist es ein Array. Das hatte ich glatt übersehen.



  • Ich möchte was von Deinem Stoff haben. Meine Adresse haste ja. Weitere Geschäfte per Mail.



  • Wie bitte? 😃



  • volkard schrieb:

    ?: doch nicht.

    std::cout << word << " ist " << std::equal(word.begin(), word.end(), word.rbegin()) + "kein Palindrom.\n";
    

    http://ideone.com/5n5T3

    Ich hätt lieber den Stoff von dem hier..
    Meine Fresse hat das gedauert bis ich es gepeilt hab.



  • ⚠ @ 314159265358979

    Und getch() ist auch nicht gerade toll, nimm lieber std::cin.get(); 😉

    Ich verwende getch(); am Ende, damit die Konsole nicht automatisch schließt, wie du dir bestimmt gedacht hast.
    cin.get(); ist eine etwas problematische Wahl.
    cin.get(); liest nämlich sofort die im Puffer verbleibenden Eingaben ein.

    Habe ich also zuvor eine Eingabe getätigt und diese mit Enter bestätigt, so wird ein Zeilenvorschub(Enter-Taste) im Puffer zurückbleiben. Verwende ich nun am Ende cin.get(), so wird der Zeilenvorschub aus dem Puffer automatisch eingelesen und die Konsole schließt sich.
    Ein doppeltes cin.get() würde das Problem natürlich lösen. Ebenfalls ein cin.ignore(); würde ausreichen, welches das letzte Zeichen im Puffer löscht.

    Das ist der Grund, warum ich getch(); wähle. Dieses greift nämlich nicht auf den Puffer zu. Wollte bloß nochmal Stellung dazu nehmen.

    Ansonsten danke ich für die Vorschläge, die hier gegeben wurden. Hab's nun auf viele Varianten versucht. Auch wenn es länger gedauert hat. Es klappt. 😃

    Das Thema kann (meinetwegen) beendet werden.


Anmelden zum Antworten