Out of range Fehler Java

yxy

Lieutenant
Registriert
Juli 2014
Beiträge
556
Hallo,

Ziel des unteren Programmes soll es sein zu vergleichen ob der eingegebene String vorwärts und rückwärts gelesen zum gleichen Ergebnis führt.
Der Compiler gibt mir momentan aber immer einen Fehler aus.

Code:
package Übung6_Palindrom;

import java.util.Scanner;

public class PalindomTest {

    public static void main(String[] args) {
        Scanner userInput = new Scanner(System.in);
        boolean itIsPalindrom = false;

        System.out.println("Geben Sie das Wort ein das Sie ueberpruefen wollen:");
        String input = userInput.nextLine();

        itIsPalindrom = isPalindrom(input);

        if (itIsPalindrom == true) {
            System.out.printf("Das eingegebene Wort %s ist ein Palindrom.\n", userInput);
        } else {
            System.out.printf("Das eingegebene Wort %s ist kein Palindrom.\n", userInput);
            System.out.println("Das eingegebene Wort" + userInput + "ist kein Palindrom");
        }

    }

    static boolean isPalindrom(String word) {
        boolean testResult = true;
        
        if(word.length() > 0)
		{
			if (word.charAt(word.charAt(0)) != word.charAt(word.length()-1)){
                            testResult = false;
                        }
                        
			isPalindrom(word.substring(1, word.length()-1));    
                       
                }

        return testResult;
    }
}
 
Du hast ein Problem mit Wörtern, die nur aus einem einzelnen Buchstaben bestehen. Solch ein Wort ist auch ein Palindrom.
Also was musst du für diesen Fall im Code ändern? ;)
 
Achso, dann liegt hier der Fehler:

Code:
isPalindrom(word.substring(1, word.length()-1));

Denn wenn die Länge 1 ist, gibt es keine Stelle 1 im String, sondern nur die Stelle 0.
Ergänzung ()

Hätte jetzt auf die Schnelle gesagt:

Code:
  if(word.length() > 1)

Aber dann kommt der Fehler immernoch.
 
Ja, genau. Wobei die Zeile 30 auch schon problematisch ist.
 
Ich würde das Problem anderst lösen.

Zuerst Prüfen ob die Vorraussetzungen erfüllt sind.
Dann das Wort konvertieren zu kleingeschrieben und dann das Wort umdrehen.
Dann den Vergleich ist das kleingeschriebene Wort gleich dem umgedrehten Wort.

Beispiel in C#

Code:
        public static bool IsPalindrom(string word)
        {
            if (string.IsNullOrEmpty(word) || word.Length < 4)
                return false;

            var lowercaseWord = word.ToLower();
            var reverseWord = new string(lowercaseWord.Reverse().ToArray());

            return lowercaseWord.Equals(reverseWord);
        }
 
Ich würde mit einer for-Schleife über das Wort iterieren (for-Schleifen Bedingung: i<(word.length-1/2-1)

Oder mit zwei Hilfsvariablen h1= word[0] h2= word.length-1
und dann mit ner while Schleife vergleichen und die Variablen inkrementieren und dekrementieren.
 
Zuletzt bearbeitet:
@: Patrik: Warum ist Zeile 30 problematisch?

@ isip: Danke, so ist es natürlich elleganter. Würde aber trotzdem gerne wissen warum mein Programm nicht funktioniert ;)
 
Müsste es nicht if(word.length() >= 1) sein? Mit >1 bildest du ja immernoch keine Wörter die nur aus einem einzigen Zeichen bestehen ab.

Bitte ignorieren, Tante Edith gab mir eine Backpfeife und sagte mir, dass ich einen Denkfehler habe.
 
Zuletzt bearbeitet:
Kharne schrieb:
Müsste es nicht if(word.length() >= 1) sein? Mit >1 bildest du ja immernoch keine Wörter die nur aus einem einzigen Zeichen bestehen ab.


Doch, dann wir die if Bedingung einfach übersprungen und ein true zurückgegeben.
 
Du läufst unendlich durch den String, weil bei einem ungleichen Ergebnis nur das testResultat auf false gesetzt wird, aber isPalindrom weiter aufgerufen wird.

Geändert: Was mir noch aufgefallen ist, du nimmst das Ergebnis nicht entgegen bei dem Aufruf.

Code:
    static boolean isPalindrom(String word) {
        boolean testResult = true;
        
        if(word.length() > 0)
		{
			if (word.charAt(word.charAt(0)) != word.charAt(word.length()-1)){
                            return false;
                        } // oder else einbauen
                        
			testResult = isPalindrom(word.substring(1, word.length()-1));    
                       
                }
 
        return testResult;
    }
 
Zuletzt bearbeitet:
word.charAt(word.charAt(0)) in Zeile 30 führt das zu, dass du das Zeichen vom Index des Dezimalwertes des ersten Characters abfragst.

Gibst du also als Input "Maoam" ein, gibt es eine OutOfBoundsException, weil du versuchst den Character von Index 77 (Dezimalwert von "M") abzufragen. Der Index existiert natürlich nicht.
 
Also von deinem Ursprungscode ausgehend:

Code:
static boolean isPalindrom(String word) {
        boolean testResult = true;

        // ergo word.length 2 und größer damit substring / charAt keinen Ärger machen
        if(word.length() > 1)
        {
            // word.charAt(word.charAt(0) ergibt keinen Sinn, deshalb word.charAt(0)
            if (word.charAt(0) != word.charAt(word.length()-1)){
                testResult = false;
            } else {
                // Rückgabewert von isPalindrom sollte ausgewertet werden, sonst hat der Aufruf keinen Sinn
                testResult = isPalindrom(word.substring(1, word.length()-1));
            }

        }

        return testResult;
}

Es wäre sicherlich nicht falsch wenn du dich mit ein paar weiteren Rekursions-Beispielen auseinandersetzt.

Code:
static boolean isPalindrom(String word) {

        if (word.length() < 2) return true;

        if (word.charAt(0) == word.charAt(word.length() - 1)) {
            return isPalindrom(word.substring(1, word.length() - 1));
        } else {
            return false;
        }
}
 
@Hooo:
Ok, das macht mehr Sinn. Tue mir noch etwas schwer mit der Rekursion.

Der 2. If Block macht also folgendes:

Wenn die 2 verglichenen Randbuchstaben gleich sind, ruft er die Methode "isPalindrom" nochmals auf (dieses mal mit dem Wort das den ersten und letzten Buchstaben abgeschnitten hat). Wenn die 2 Randbuchstaben wieder gleich sind ruft er "isPalindrom" nochmal auf (mit wieder verkürztem Wort).
Das geht so lange, bis einer der folgenden Fälle eintritt:

1: Die Randbuchstaben sind ungleich
Dann gibt die zuletzt aufgerufene Methode den Wert "false" zurück. Diese wird dann durch den Befehl
"return isPalindrom(word.substring(1, word.length() - 1));"
von der zweitletzten Methode als Rükgabewert an die drittletzte Mthode weitergegeben.
Diese wiederrum gibt den Wert an die vorherige weiter,... bis schließlich die von der main Methode aufgerufene Methode den Rückgabewert "false" an die main Funktion übergibt.

2: Das Wort ist ein Palindrom
Die letze Methode gibt der vorherigen Methode den Wert "true" zurück. Diese wiederum der ihr vorherigen,... bis "true" bei der main landet.
 
Genau,

main: isPalindrom("abcba")

Der sogenannte Call-Stack wird aufgebaut bis isPalindrom die Rekursion beendet und einen konkreten Wert zurückgibt.

isPalindrom("abcba")
isPalindrom("bcb")
isPalindrom("c") -> return true

Dann müssen die vorherigen Funktionsaufrufe rückabgewickelt werden (beginnend beim letzten Aufruf: hier c):

a) isPalindrom("abcba") return true to main
b) isPalindrom("bcb") return true to a
c) isPalindrom("c") return true to b
 
Zurück
Oben