Logik Fehler erkennen

Hallo1234

Bekanntes Mitglied
Hallo,
bei dieser Aufgabe soll die ISBN Nummer auf Gültigkeit überprüft werden. Schon beim ersten Schritt habe ich ein Problem:
Java:
public static void isbn() {
        Scanner s = new Scanner(System.in);

        System.out.println("Geben Sie die ISBN Nummer ein: ");            //Eingabe ISBN Nummer
        String isbn = s.next();                                            //ISBN wird eingelesen

        String praefix = praefix(isbn);                                    //Methodenaufruf für präfix
        //String laKe = landesKennung(isbn);                            //Methodenaufruf für landesKennung

    }

    public static String praefix(String isbn) {
        String praefix = "";                                            //Deklaration präfix

        String[] ersteDreiZiffern = new String[3];                        //Array mit drei Schubladen
        for(int i=0; i<ersteDreiZiffern.length; i++) {                    //for-Schleife läuft von 0 bis 3
            praefix = isbn;                                                //präfix werden nur die ersten 3 Zahlen von isbn zu geordnet
        }
        if(!praefix.equals("979")|| !praefix.equals("978")) {            //wenn präfix nicht 979 oder 978 ist -> false
            System.out.println("Kein zulässiger Präfix. Bitte Eingabe wiederholen!");
        }
        return praefix;                                                    //Rückgabe präfix
    }

Wenn ich 979 oder 978 als Präfix eingebe, wird mir jedes Mal "Kein zulässiger Präfix" ausgegeben. Woran liegt das? Wie ihr seht, habe ich es mit Kommentaren zur Veranschaulichung versucht. Aber ich komme nicht drauf.
 
Habe es noch Mal komplett verändert:
Java:
public static void isbn() {
        Scanner s = new Scanner(System.in);

        System.out.println("Geben Sie die ISBN Nummer ein: ");            //Eingabe ISBN Nummer
        String isbn = s.next();                                            //ISBN wird eingelesen

        String praefix = praefix(isbn);                                    //Methodenaufruf für präfix
        //String laKe = landesKennung(isbn);                            //Methodenaufruf für landesKennung

    }

    public static String praefix(String isbn) {
        String praefix = "";                                           
        int isbnTest = 0;
        
        for(int i=1; i<=3; i++) {
            isbnTest = isbn.charAt(isbn.length()-9);
        }
        System.out.println(isbnTest);
    
        if(isbnTest!=979|| isbnTest!=978) {           
            System.out.println("Kein zulässiger Präfix. Bitte Eingabe wiederholen!");
        }
        
        return praefix;                                                   
    }
Damit wollte ich erreichen, dass durch isbnTest nur die ersten 3 Ziffern ausgegeben werden und ich sie somit überprüfen kann.
Jetzt bekomme ich bei Eingabe von weniger als 13 Zeichen eine Fehlermeldung. Wenn es 13 Zeichen sind, wird mir irgendeine zweistellige Zahl ausgegeben, die nichts damit zutun hat. Wie schaffe ich es, nur die ersten 3 Zahlen zu überprüfen?
 
Erst einmal sorry, wenn ich erst ein paar andere Punkte anbringe:

a) Sinnvolle Bezeichner! Was macht die Methode praefix? Der Name sagt nicht wirklich aus, was die Methode macht. Methoden sollten immer genau sagen, was sie machen. Soll die Methode den praefix zurück geben? Dann wäre es eine Art getPrefix. Soll es den Praefix prüfen? Dann wäre es evtl. ein checkPrefix. Etwas in der Art.

b) String hat einige interessante Methoden. Eine Dokumentation lässt sich einfach finden, wenn Du nach "java 8 String" oder "java 16 String" (Die Zahl gibt die Java Version an, die Du nutzt)
Zum prüfen des Anfangs eines Strings gibt es z.B. startsWith. Zeichen aus dem String kannst Du dir mittels substring ausgeben lassen.
 
Ach ja - ganz vergessen:
Bei deiner Schleife musst Du natürlich jede Ziffer hinzu fügen.

Am Anfang ist es ja 0 und es kommt z.B. die 9 hinzu.
Dann ist es 9 und es soll die 7 dazu kommen - eine Zuweisung ist das ja nicht mehr sondern es soll 97 raus kommen ... Wie kriege ich aus der 9 und der 7 die 97?
Dann ist es 97 und von mir aus die 9 kommt dazu ... es soll 979 raus kommen, welche Berechnung macht aus der 97 und der 9 eine 979?
 
Erst einmal sorry, wenn ich erst ein paar andere Punkte anbringe:

a) Sinnvolle Bezeichner! Was macht die Methode praefix? Der Name sagt nicht wirklich aus, was die Methode macht. Methoden sollten immer genau sagen, was sie machen. Soll die Methode den praefix zurück geben? Dann wäre es eine Art getPrefix. Soll es den Praefix prüfen? Dann wäre es evtl. ein checkPrefix. Etwas in der Art.

b) String hat einige interessante Methoden. Eine Dokumentation lässt sich einfach finden, wenn Du nach "java 8 String" oder "java 16 String" (Die Zahl gibt die Java Version an, die Du nutzt)
Zum prüfen des Anfangs eines Strings gibt es z.B. startsWith. Zeichen aus dem String kannst Du dir mittels substring ausgeben lassen.
String (Java Platform SE 8 )
Du hast völlig Recht. Ich werde an den Bezeichnungen für die Methoden arbeiten 🙂
Danke für die Hinweise, werde nachschauen.
 
Sie soll alle Werte im bereich length()-9 ausgeben, also nur die ersten drei.
Die Länge verändert sich ja nicht und damit ist length() - 9 invariant. So wie Du es geschrieben hast, liest Du also in jeder Wiederholung das gleiche Zeichen (= Unicode Codepoint!) und weist es der Variablen isbnTest zu. Das bringt es jetzt nicht wirklich 🙂
 
Ach ja - ganz vergessen:
Bei deiner Schleife musst Du natürlich jede Ziffer hinzu fügen.

Am Anfang ist es ja 0 und es kommt z.B. die 9 hinzu.
Dann ist es 9 und es soll die 7 dazu kommen - eine Zuweisung ist das ja nicht mehr sondern es soll 97 raus kommen ... Wie kriege ich aus der 9 und der 7 die 97?
Dann ist es 97 und von mir aus die 9 kommt dazu ... es soll 979 raus kommen, welche Berechnung macht aus der 97 und der 9 eine 979?
Vielleicht isbnTest++; ?
Ich versuchs mal.
 
Soweit ich sehe, ist diese Methode
Java:
    public static String praefix(String isbn) {
        String praefix = "";                                       
        int isbnTest = 0;
    
        for(int i=1; i<=3; i++) {
            isbnTest = isbn.charAt(isbn.length()-9);
        }
        System.out.println(isbnTest);

        if(isbnTest!=979|| isbnTest!=978) {       
            System.out.println("Kein zulässiger Präfix. Bitte Eingabe wiederholen!");
        }
    
        return praefix;                                               
    }
identisch mit dieser
Java:
    public static String praefix(String isbn) {
        System.out.println(isbn.charAt(isbn.length()-9));
        System.out.println("Kein zulässiger Präfix. Bitte Eingabe wiederholen!");
        return "";                                               
    }

Wenn du die ersten drei Zeichen von isbn möchtest, dann verwende einfach isbn.substring(0,3). Du solltest allerdings vorher prüfen, ob der String überhaupt drei Zeichen enthält, ansonsten erhältst du eine IndexOutOfBounds-Exception.
 
Zuletzt bearbeitet:
Vielleicht isbnTest++; ?
Ich versuchs mal.

Nein, vielleicht einfach einmal noch kurz auf die Bedeutung / Wertigkeit eingehen:

Eine Zahl 123 -> kannst du das zergliedern? Welche Wertigkeit hat die 1? Und welche Wertigkeit hat die 2? Und dann die 3?
Also kannst Du es ausdrücken als: 1*x + 2*y + 3*z?
Was wären x, y und z hier?

Das ist der Aufbau und das kannst Du dann auf die Thematik anwenden, dass Du eine Variable mit 9 und eine Variable mit 7 hast und Du willst dann eine 97 bekommen ...

Dann die zweite Thematik, die angeklungen ist: Du willst ja mit charAt einzelne Zeichen auslesen. Da ist dann de Dokumentation wichtig, so findet sich bei charAt an Dokumentation (Auszug):
Returns the char value at the specified index. An index ranges from 0 to length() - 1.
Das erst Zeichen ist also bei index = 0, das zweite bei index = 1 und das dritte bei index = 2.

=> Somit kannst Du die Schleife so schreiben, dass die Schleifenvariable von 0 bis einschließlich 2 geht? Und dann greifst Du auf das Zeichen mit index der Schleifenvariable zu.

Jetzt greife ich aber erneut ein weiteres Problem auf:
Wenn Du da als Zeichen eine '9' zurück bekommst, dann ist es leider keine Zahl 9. Du hast ein Zeichen zurück bekommen und das hat andere Werte. Die Werte der Zeichen kannst Du z.B. bei einer ASCII Tabelle finden (Das ist nicht ganz korrekt - es ist kein ASCII Zeichen sondern ein Unicode Zeichen. Aber die wichtigen Werte stimmen überein).
So eine ASCII Tabelle findet sich z.B. unter https://www.torsten-horn.de/techdocs/ascii.htm
Dort findest Du neben Scan Code (den ignorierst Du - den brauchen wir hier nicht) den ASCII Wert einmal in hexadezimal und einmal in Dezimalschreibweise und dann das eigentliche Zeichen. Das Zeichen '9' ist demnach die 57 bzw. 0x39 in hexadezimal.
Daher musst Du jedem Zeichen noch den Wert der '0' (= 48) abziehen.

Das macht diesen Lösungsweg relativ komplex. Aber als Übung solltest Du es einmal durchführen und auch im Detail verstehen, denn das wirst Du später als Basiswissen durchaus brauchen.
 
Ach deshalb wurde mir so oft die 57 ausgegeben. Ich habe mich schon gewundert. Naja, darauf werde ich jetzt aufbauen. Vielen Dank für die Tipps 🙂
 
Sieht so aus, als hätte ich es jetzt.
Java:
public static void checkIsbn() {
        Scanner s = new Scanner(System.in);
        System.out.println("Geben Sie die ISBN Nummer ein: ");
        String isbn = s.next();
    
        String praefix = checkPraefix(isbn);
        String landesKennung = checkLandesKennung(isbn);
    }
    
    public static String checkPraefix(String isbn) {
        String praefix = isbn.substring(0,3);
        if(praefix.equals("979")||praefix.equals("978")) {
        }else {
            System.out.println("Ungültiger Praefix! Bitte Widerholen Sie die Eingabe");
        }
        
        return praefix;
    }
    
    public static String checkLandesKennung(String isbn) {
        String landesKennung = isbn.substring(4,5);
        
        if(landesKennung.equals("3")) {
        }else {
            System.out.println("Ungültige Landeskennung! Bitte Eingabe wiederholen.");
        }
        return landesKennung;
    }
Die Methode Substring wirkt doch Wunder. Für die anderen Lösungswege habe ich noch nicht genügend Erfahrung und Geduld. Bin einfach froh, das es jetzt funktioniert.
1618671392506.png
Vielen Dank für eure Hilfe 🙂
 
Ja, das ist eine deutlich einfachere Methode.

Da ich ja einiges aufgestellt habe, möchte ich es aber nicht versäumen, es sozusagen "aufzulösen".

Bei einer Zahl im Dezimalsystem 123 hat man von rechts nach Links ja die 10er Potenzen. Also 3 * 10^0 + 2 * 10^1 + 1 * 10^2

Daher wäre das bei einer Berechnung, bei denen die Ziffern in dieser Reihenfolge kommen: 1, 2, 3 dann einfach so:
zahl := 0
Für jede Ziffer: zahl := 10 * zahl + Ziffer

Also wenn man es durchspielt: Zahl ist 0.
Es kommt die 1: Zahl ist 10 * 0 + 1 = 1
Es kommt die 2: Zahl ist 10 * 1 + 2 = 12
Es kommt die 3: Zahl ist 10 * 12 + 3 = 123

Das kann man dann natürlich umsetzen:

Eine Schleife von 0 bis einschließlich 2 wäre:
for (int i=0; i<=2; i++) oder
for (int i=0; i<3; i++)

In der Schleife rechnen wir wie oben angegeben, Zahl ist prefix und Ziffer ist die Ziffer an Position i. Damit wir die Zahl bekommen, nehmen wir hier noch den Abzug von '0'. Damit erhalten wir einen Code wie:
Java:
        int praefix = 0;
        for(int i=0; i<3; i++) {
            praefix = 10 * praefix + isbn.charAt(i) - '0';
        }

Damit hätte man den prefix soweit erst einmal berechnet. Aber wir rechnen hier jetzt aber auch mit Buchstaben und so ....
Daher müssen wir prüfen, ob die Ziffer zwischen 0 und 9 ist und wir haben dann etwas wie:
Java:
        int praefix = 0;
        for(int i=0; i<3; i++) {
            int ziffer = isbn.charAt(i) - '0';
            if (ziffer < 0 || ziffer > 9) ziffer = 0; // ziffer auf 0 setzen sorgt für einen negativen Check ...
            praefix = 10 * praefix + ziffer;
        }

Die Prüfung habe ich eingebaut, aber das, was man da macht, muss man sich genau überlegen. In der Regel würde eine Exception geworfen, aber das ist evtl. etwas für euch noch Unbekanntes. Daher habe ich die ziffer einfach auf 0 gesetzt. Ein "97X" wird dann zu 970 und die Prüfung wird negativ sein...

Das aber einfach nur als Erläuterung, damit ich nicht nur Fragen aufgeworfen habe sondern auch die Antworten zu finden sind.

Die Lösung, die Du gefunden hast, ist so aber super und voll in Ordnung (Und besser als dieses Berechnen... Wobei Du damit ruhig aktiv noch etwas herum spielen solltest um es besser zu verstehen (So Du die Zeit dazu findest)
 
Das ist wirklich klasse erklärt, wie immer 😄.
Wobei Du damit ruhig aktiv noch etwas herum spielen solltest um es besser zu verstehen (So Du die Zeit dazu findest)
Das werde ich sowieso, denn die nächste Aufgabe hat mit der Ascii Tabelle und dem Dezimalsystem zu tun. Deine Erläuterung wird mir auf jeden Fall weiter helfen. Vielen Dank für deine Hilfe und dass du dir noch mal die Mühe gemacht- und alles "aufgelöst" hast 🙂
 
Da es im Thementitel ja um Logik geht, noch dieses:

Deine Lösung ist schon sehr gut, aber die etwas umständliche if-Struktur mit dem leeren Anweisungsblock könntest du etwas verbessern.
Java:
// anstatt => WENN A ODER B {mach nichts} ANSONSTEN {mach was} => NICHT(A ODER B)

if(praefix.equals("979") || praefix.equals("978")) {

}
else {
    System.out.println("Ungültiger Praefix! Bitte Widerholen Sie die Eingabe");
}

// NICHT ( A ODER B)

if (!(praefix.equals("979") || praefix.equals("978"))) {
    System.out.println("Ungültiger Praefix! Bitte Widerholen Sie die Eingabe");
}

// NICHT A UND NICHT B

if (!praefix.equals("979") && !praefix.equals("978")) {
    System.out.println("Ungültiger Praefix! Bitte Widerholen Sie die Eingabe");
}

Siehe: De-morgansche Gesetz

Weiterhin noch ein paar Anmerkungen:

Bei einer Eingabe, die weniger als drei Stellen hat, erhältst du eine Fehlermeldung, siehe #14.

Die Länderkennung muss nicht nur aus einem Zeichen bestehen (laut Wikipedia). Insgesamt wäre es also besser die einzelnen Bestandteile der ISBN anhand des "-" zu trennen. Dazu bietet die Klasse String auch entsprechende Methoden und irgendwann kannst du das ja mal ausprobieren. Dann kannst du evtl. auch die Prüfsumme berücksichtigen.
 
Zuletzt bearbeitet:
Guter Einwand werde das ändern.
Dann kannst du evtl. auch die Prüfsumme berücksichtigen.
Ja, die Aufgabe ist ohnehin noch nicht komplett fertig programmiert. Ich war gestern einfach froh, dass es endlich geklappt hat, um den Rest kümmere ich mich noch.
Die Länderkennung muss nicht nur aus einem Zeichen bestehen (laut Wikipedia).
In der Aufgabe soll nur die Landeskennung für Deutschland überprüft werden. Ich werde mich erst mal darauf beschränken, denn die Prüfsumme will auch berechnet werden. Danke für deine Hinweise 🙂
 

Zurück
Oben