String/Char-API

carsten_java

Mitglied
Hallo zusammen!
Ich möchte folgende Aufgabe lösen:

Die Methode istName nimmt eine Zeichenkette als Argument an und gibt einen Wahrheitswert zurück, ob sie ausschließlich Buchstaben oder Bindestriche ('-') enthält. Ein Bindestrich darf aber nicht als erstes oder letztes Zeichen auftreten. Es sind keine White Spaces zugelassen, auch nicht am Anfang oder Ende. Eine leere Zeichenkette ist ein gültiger (eben leerer) Name. Z.B. ergibt ein Aufruf mit dem Argument "Lisa-", "R2-D2" oder "Johann Wolfgang" den Wert false (letzteres sind zwei Namen). Ein Aufruf mit dem Argument "Brad-Arnold" oder "ey" ergibt den Wert true.

Meine Lösung sieht folgendermaßen aus:

[CODE lang="java" title="String/Char-API Aufgabe"]
public class bindestrich{
public static boolean istName(String n){
boolean z = true;
if (n.isEmpty()){
return true;
}
if (n.indexOf(' ') == 0 | n.indexOf('-') == 0 | n.lastIndexOf(' ') == n.length() - 1 | n.lastIndexOf('-') == n.length() - 1){
return false;
}
int i = 0;
while (i<0){
char c = n.charAt(i);
if (!Character.isLetter(c) & c != '-' & c == ' '){
return false;
}
else{
return true;
}
}
return z;
}
}
[/CODE]

Leider wird bei "R2-D2" und "Johan Wolfgnag" der falsche Wahrheitswert ausgegeben. Nach langem Suchen und mehrmaligem Herumprobieren habe ich den Fehler nicht gefinden.

Könnt ihr mir hierbei vielleicht weiterhelfen und erklären wo der Fehler ist und warum das Programm mit dieser Lösung nicht richtig ausgeführt wird?

VG
Carseten
 
Also neben dem Punkt, dass er in die Schleife nie hinein geht, wäre da direkt noch etwas, das ich ansprechen möchte:

Du hast eine Schleife und in der Schleife eine Bedingung. Die Bedingung hat aber immer ein return.
==> Die Schleife wird also sofort verlassen und die Schleife ist so einfach sinnlos. Vom Sinn her ist das while hier bei dem Code nichts anderes als ein if.

Generell ist das Pattern immer das folgende:
Annahme eines Falles.
Schleife über alle Elemente, ob der angenommene Fall richtig ist. Falls nein, dann hat man ein Ergebnis und springt zurück.
Nach der Schleife: Die Annahme ist bestätigt und wir geben die Annahme zurück.

Also konkretes Beispiel wäre z.B. die Prüfung: String enthält nur kleine Buchstaben:
Java:
public static boolean onlySmallLetters(final String text) {
    // Annahme ist: Ja, alle zeichen sind kleine Buchstaben: true
    for (char ch : text.toCharArray()) {
        // Gegenteil wird geprüft
        if (ch < 'a' || ch >'z') return false; // Resultat steht ja mit nur einem gefundenen Fall fest.
    }
    
    // Es wurden alle Zeichen geprüft und alles ist korrekt:
    return true;
}

Und noch ein wichtiger punkt, auf den Du sehr gut achten musst:
Du veränderst i in der Schleife nicht und damit hättest Du eine Endlosschleife. (Aber die anderen beiden Punkte verhindern dies natürlich - so kommst Du ja nie in die Schleife und wenn, dann würdest Du diese sofort wieder verlassen.)
 
Und als Ergänzung zu dem von @kneitzel Gesagten:

Es gibt in Java unterschiedliche Schleifenarten. Du hast hier die while-Schleife, bei der die Bedingung am Anfang überprüft wird.
Java:
while(bedingung) {
    // mach was
}
Wenn die Bedingung nicht erfüllt ist, dann wird auch nichts gemacht.

Es gibt auch noch die do-while-Schleife:
Java:
do {
    // mach was
} while (bedingung)
Hier wird die Bedingung erst am Ende überprüft, es wird also mindestens einmal etwas gemacht.

Zuletzt gibt es noch die for-Schleife, die typischerweise eine Zählschleife ist.
 
Also wird immer, wenn in der Schleife eine Bedingung
Du hast eine Schleife und in der Schleife eine Bedingung. Die Bedingung hat aber immer ein return.
==> Die Schleife wird also sofort verlassen und die Schleife ist so einfach sinnlos. Vom Sinn her ist das while hier bei dem Code nichts anderes als ein if.
Also wird immer, wenn ein Fall in der Schleife zutrifft auf den entsprechenden Wahrheitswert gesetzt, das Programm beendet und dieser Wahrheitswert dann ausgegeben?
Wäre es dann richtig, wenn man anstatt der return-Anweisungen schreiben würde z=true, oder z=false?
 
Wäre es dann richtig, wenn man anstatt der return-Anweisungen schreiben würde z=true, oder z=false?
Nein, das ist auch problematisch, denn dann würden ja alle Ergebnisse immer überschrieben und Du hättest am Ende nur das Ergebnis der letzten Prüfung.

Wenn ich Dir einen Zettel mit ganz vielen Ziffern gebe und du sollst mir sagen: Sind da auch 9er drauf. Dann gehst Du doch so vor:
Du gehst alle Ziffern durch, sobald Du eine 9 gefunden hast, weißt Du: Es gibt auch 9er auf dem Zettel. Also kannst Du abbrechen und sagen: Ja, es sind 9er auf dem Zettel. Wenn Du aber den ganzen Zettel durchgegangen bist und hast keine 9 gefunden: Dann sagst Du: Es gibt keine 9er.

Und so sieht es dann auch in einer Schleife aus:
Du gehst alle Elemente durch. Sobald du ein Zeichen gefunden hast, das kein kleiner Buchstaben ist, dann weisst Du: Es sind nicht nur kleine Buchstaben vorhanden. Und da macht ein Return Sinn, denn damit brichst Du die Suche auch ab.
Wenn Du alles geprüft hast und hast kein Zeichen gefunden, dass kein kleiner Buchstabe ist, dann hast Du auch ein Ergebnis, dass Du zurück geben kannst.

Den Fall mit der Variablen, die immer gesetzt wird, könnte man aber auch durchspielen, den technisch kann es gehen, so man die Schleife abbricht:
Java:
boolean result = true;
for (char zeichen: alleZeichen) {
    if (isSmallCharacter(zeichen)) {
        result = true;
    } else {
        result = false;
        break;
    }
}

return result;

Wenn wir den leeren String prüfen, dann sind da keine Zeichen drin, die keine Kleinbuchstaben sind. daher initialisieren wir result auf true.
In der Schleife result auf true setzen ist jetzt aber unnötig. Result ist doch bereits true. Dadurch wird also nichts verändert.
Sobald da aber ein Zeichen kommt, das kein Kleinbuchstabe ist, dann wird die Schleife abgebrochen.

Mit dem Hintergrundwissen vereinfacht sich der Code dann schnell zu:
Java:
for (char zeichen: alleZeichen) {
    if (!isSmallCharacter(zeichen)) {
        return false;
    }
}

return true;

Hat dies geholfen, es etwas besser zu verstehen?
 
Also wird immer, wenn ein Fall in der Schleife zutrifft auf den entsprechenden Wahrheitswert gesetzt, das Programm beendet und dieser Wahrheitswert dann ausgegeben?
Wäre es dann richtig, wenn man anstatt der return-Anweisungen schreiben würde z=true, oder z=false?
Die Bedingung hat aber immer ein return.
Damit ist nicht die "return" Anweisung gemeint, die i.d.R. einen Wert zurück gibt. Es ist damit gemeint, dass die Schleife abgebrochen wird, wenn die Bedingung nicht mehr zu trifft. Je nachdem ob die Bedingung am Anfang oder am Ende geprüft wird (siehe auch #6) wurde die Schleife mindestens einmal durchlaufen oder auch nicht (damit sind die Anweisungen im Schleifenrumpf, innerhalb der geschweiften Klammern, gemeint).

Es ist allerdings durchaus möglich innerhalb des Schleifenrumpfs eine "return" Anweisung zu haben, die dann nicht nur die Schleife, sondern die ganze Methode verlässt. Siehe das letzte Beispiel in #8: Die Methode wird beendet, wenn die if-Bedingung innerhalb des Schleifenrumpfs erfüllt ist.

EDIT: Evtl. habe ich allerdings deine Frage falsch verstanden. Sei es drum 😉
 
Zuletzt bearbeitet:
Also, wenn ich eine return-Anweisung in eine Schleife schreibe und die Bedingung für dieses return zutrifft, wird die Schleife und auch evtl. das Programm beendet?
 
Wenn die return Anweisung in der main()-Methode ist wird das Programm beendet, ansonsten die Methode in der das return steht.
Also dem ersten Punkt möchte ich widersprechen. Ich habe regelmäßig Applikationen, die weiter laufen, obwohl die main() Methode sich schon beendet hat (Swing / JavaFX aber auch Spring Boot ... Es gibt viele Bereiche, in dem dies so ist).
Eine Java Applikation beendet sich ansonsten erst, wenn alle Threads, die nicht als Background Thread markiert wurden, sich beendet haben.

@carsten_java: Lass Dich von diesem Detail bitte nicht verwirren. Ganz am Anfang wirst Du vermutlich nicht wissen, was ein Thread ist und Du wirst nichts machen, dass einen zusätzlichen Thread starten wird. Daher trifft die Aussage von temi in so einfachen Applikationen zu. Aber dennoch sind es zwei verschiedene Punkte: das return in der main Methode und das Beenden der Java Virtual Machine. Erstes ist eine Voraussetzung für das Zweite. Aber aus dem Ersten folgt das Zweite nicht.

Aber ganz wichtig ist natürlich der zweite Part: Der return Befehl beendet die Methode, in der das return steht. Und danach geht es hinter der Stelle, an der die Methode aufgerufen wurde, weiter!
 

Zurück
Oben