# Primzahlen und Rekursive Liste



## DeDudeZz (19. Nov 2012)

Hallo zusammen. 

ich habe folgendes Problem. Das nachfolgende Programm soll nach eingabe von a oder b oder beidem jeweils 1 program, entweder zur überprüfung der primzahl oder zur auflistung einer liste bis zu einer bestimmten zahl. ich habe aber folgendes problem, nämlich dass das unterprogramm nicht die liste sondern einfach stumpf die eingegebene Zahl wieder ausspuckt. was mach ich falsch?


```
import java.util.Scanner;

// Klasse Aufgabe 1
public class unter {
    //Hauptmethode der Klasse Aufgabe1
    public static void main (String[] args) {
        //Scanner mit dem Namen scanner anlegen
        Scanner scanner = new Scanner(System.in);
        
        //Auswahlmöglichkeit für den Benutzer / Ausgabetext
        System.out.println("Was moechten Sie tun?");
        System.out.println("\t  <1> - Aufgabenteil A: Primzahl-Test");
        System.out.println("\t  <2> - Aufgabenteil B: Rekursive Aufzaehlung");
        System.out.println("\n");
        System.out.println("\t  Jede andere Zahl ruft beide Aufgabenteile auf.");
        System.out.println("\n");
        
        //Einlesen der Zahl um den jeweiligen Aufgabenteil aufzurufen
        int operator = scanner.nextInt();
        
        //switch case zum Aufruf von Aufgabenteil A, B oder auch beiden.
        switch(operator) {
        //Aufgabenteil A
        case 1:
            System.out.println(" - Primzahl-Test - ");
            System.out.println(" Geben Sie nun eine Zahl ein um zu pruefen ob diese eine Primzahl ist:");
            //Einlesen der möglichen Primzahl
            int eingabe = scanner.nextInt();
            //Anlegen des Boolean für das Unterprogramm
            boolean primA = primA(eingabe);
            break;     
        //Aufgabenteil B
        case 2:
            System.out.println(" - Rekursive Zahlenausgabe - ");
            System.out.println(" Geben Sie eine Zahl ein bis zu der gezaehlt werden soll.");
            int n = scanner.nextInt();
            int zahlenB = zahlenB(n);
            break;
        //beide Aufgabenteile
        default:
            System.out.println(" - Beide Aufgabenteile - ");
            
        }
    }
    
    //Unterprogramm für Aufgabenteil A (Primzahl)
    public static boolean primA(int eingabe) {
    //Anlegen des Booleans ob es eine Primzahl ist, dieser wird auf true gesetzt.
    boolean istPrimzahl = true;
    //Bedingung 0, 1
    if (eingabe == 0 || eingabe == 1) {
            System.out.println(eingabe + " ist keine Primzahl.");
            return istPrimzahl;
            }
    // Schleife zum ermitteln der Primzahl anlegen
    for(int i = 2;i < eingabe;i++) {   
        if (eingabe % i == 0){
            istPrimzahl = false;
            System.out.println(eingabe + " ist keine Primzahl.");
                return istPrimzahl;
            }
        }
			System.out.println(eingabe + " ist eine Primzahl.");
				return istPrimzahl;
    }
        
    // B  Unterprogramm Aufzählung
    public static void zahlenB(int n, int eingabe) {
        if(eingabe == 0) {
			System.out.println(" Ihre Zahl muss größer als 0 sein ");
        }else if(n == eingabe) {
            System.out.print(n);
		}else {
			System.out.println(n + ",");
			n = n + 1;
			zahlenB(n,eingabe);
		}
	}
}
```


----------



## TryToHelp (19. Nov 2012)

Also deinem Code Nach macht dein Programm nur etwas wenn du die eins eingibst, bei allen anderen ausgaben kommt entweder nur eine Ausgabe " - Beide Aufgabenteile - " oder zwei ausgaben " - Rekursive Zahlenausgabe - " & " Geben Sie eine Zahl ein bis zu der gezaehlt werden soll." sowie ein einlesen einer Zahl statt.


----------



## D4rkscr43m (19. Nov 2012)

ich weiß zwar nicht genau, was du meinst oder wo dein Problem ist, aber du rufst die Methode "zahlenB" nicht auf.


----------



## DeDudeZz (19. Nov 2012)

Das Program erwartet als erstes eine Eingabe von einer Zahl. Bei 1 geht es in den Primzahlchecker, bei 2 in die Aufzählliste und bei jeder anderen Zahl sollten beide Programme gleichzeitig geladen werden, was ich auch noch nicht hinbekommen habe. 
Der Primzahlchecker funktioniert, nur die Listenerstellung hackt. Egal welche Zahl ich eingebe, er gibt immer nur die eingebene Zahl wieder und dabei belässt er es.

/edit: Java Code geändert. neuer Fehler


----------



## TryToHelp (19. Nov 2012)

Wie von mir und D4rkscr43m gesagt, solltest du dann auch einfach mal deine 2 Funktion aufrufen, weil


```
case 2: // gehe hier rein wenn 2 gewählt
            System.out.println(" - Rekursive Zahlenausgabe - "); // gebe text aus
            System.out.println(" Geben Sie eine Zahl ein bis zu der gezaehlt werden soll."); // gebe noch mehr text aus
            int n = scanner.nextInt(); // lese zahl ein
// hier sollte sowas rein wie zahlenB(0, n);
            break; // beende duesen zweig
```


----------



## TryToHelp (19. Nov 2012)

[EDIT]Eine Funktion mit 2 Parametern braucht auch 2 Parameter, siehe meinen code (im Komentar)[/EDIT]


----------



## TryToHelp (19. Nov 2012)

[EDIT]Und sie liefert nix zurück, als das 
	
	
	
	





```
int zahlenB=
```
 weglassen[/EDIT]


----------



## DeDudeZz (19. Nov 2012)

Danke es funzt =). Jetzt ist nur die Frage wie ich es einstelle , dass beim "Auswahlbildschirm" bei jeder anderen Zahl beide Aufgaben auspuckt.


----------



## TryToHelp (19. Nov 2012)

Und damit dein egal was eingeben auch funktioniert

```
default:
            System.out.println(" - Beide Aufgabenteile - ");
            System.out.println(" Geben Sie nun eine Zahl ein:");
            int eingabe = scanner.nextInt();
            zahlenB(0, eingabe );
            primA(eingabe);
```
oder

```
default:
            System.out.println(" - Beide Aufgabenteile - ");
            zahlenB(0, operator);
            primA(operator);
```


----------



## DeDudeZz (19. Nov 2012)

Alles perfekt Vielen dank für die Hilfe :toll:


----------



## Anfängerin256 (11. Nov 2016)

Hallo 
Ich habe mir das Programm auch mal angeschaut und habe zwei Fragen:
1. Bei Case 2 beginnt bei mir die Auflistung der Zahlen bei 0. Also wenn ich 6 eingebe, werden 0, 1, 2, 3, 4, 5, 6 ausgegeben. Wie bekomme ich es hin, dass ab 1 angefangen wird zu zählen?

2. Bei default beziehen wir uns ja erneut auf die Variablen "n" und "eingabe". Da kommt bei mir jetzt der Fehler "variable n is already defined in method main(String[]). Genau das gleiche natürlich bei der Variable "eingabe". Wie kann ich diesen Fehler beheben?

Danke für die Hilfe!


----------



## Xyz1 (11. Nov 2016)

@Anfängerin256 : Kannst du (in diesem uraltThema) nochmal verständlich beschreiben, was das Programm machen soll? Den Code oben kann man eigentlich wegwerfen.


----------



## Anfängerin256 (11. Nov 2016)

@DerWissende : Klar 
Zu Beginn soll man sich per Zahleneingabe für einen Aufgabenteil entscheiden (1= Aufgabenteil A, 2= Aufgabenteil B, bei Eingabe einer anderen Zahl sollen beide Aufgabenteile ausgegeben werden).
Im ersten Aufgabenteil wird eine Zahl (>1) eingelesen und ausgegeben, ob die eingegebene Zahl eine Primzahl ist. Da passt auch alles. 
Im zweiten Aufgabenteil soll eine weitere Zahl (>0) eingelesen werden und bis zu dieser Zahl sollen alle ganzen Zahlen rekursiv ausgegeben werden. 
Hier würde mich interessieren, wie ich den Code ändern kann, damit die rekursive Ausgabe der Zahlen ab 1 und nicht ab 0 beginnt.
So und wenn ich jetzt über Default versuche beide Aufgabenteile bei Eingabe einer anderen Zahl als 1 oder 2 auszugeben (siehe letzter Post von TryToHelp), kommt die oben erwähnte Fehlermeldung, da man sich ja erneut auf die gleichen Variable bezieht. Wie kann ich diesen Fehler beheben?

Ich hoffe das ist soweit verständlich...
Vielen Dank schonmal


----------



## Tarrew (11. Nov 2016)

Zu case 2: Einfach als ersten Parameter die 1 übergeben.

Wenn du den default Teil von TryToHelp übernimmst kann ich die Fehlermeldung nicht so wirklich nachvollziehen auf Anhieb: 

```
switch (operator) {
    //Aufgabenteil A
    case 1:
        System.out.println(" - Primzahl-Test - ");
        System.out.println(" Geben Sie nun eine Zahl ein um zu pruefen ob diese eine Primzahl ist:");
        //Einlesen der möglichen Primzahl
        int eingabe = scanner.nextInt();
        //Anlegen des Boolean für das Unterprogramm
        boolean primA = primA(eingabe);
        break;
    //Aufgabenteil B
    case 2:
        System.out.println(" - Rekursive Zahlenausgabe - ");
        System.out.println(" Geben Sie eine Zahl ein bis zu der gezaehlt werden soll.");
        int n = scanner.nextInt();
        zahlenB(1, n);
        break;
    //beide Aufgabenteile
    default:
        System.out.println(" - Beide Aufgabenteile - ");
        zahlenB(1, operator);
        System.out.println();
        primA(operator);

}
```


----------



## Anfängerin256 (11. Nov 2016)

Super, Case 2 hat geklappt, danke 

Ich möchte auch beim Default Werte einlesen, mit dem dann der jeweilige Aufgabenteil berechnet wird (so wie angegeben rechnet er die Teile ja mit der Zahl, die man zu Beginn eingibt, wenn sie nicht 1, oder 2 ist...), also so:

```
[System.out.println("Teil B:");
int n= scanner.nextInt();
zahlenB(1,operator);]
```
und im gleichen Schema für Teil A.

Und dann kommt halt leider die Fehlermeldung, dass die Variable bereits definiert ist.
Muss ich die Variable neu benennen und dann dafür wieder neue Unterprogramme schreiben, oder lässt sich das vereinfachen?


----------



## Xyz1 (11. Nov 2016)

Hier mal meine Variante, wie ich das verstehe:

```
private static void methode1() throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        System.out.println("1 Primzahltest");
        System.out.println("2 Liste (rekursiv)");
        System.out.println("x Verlassen:");
        try {
            int i = Integer.parseInt(reader.readLine());
            if (i == 1) {
                System.out.println("Zu testende Zahl:");
                int x = Integer.parseInt(reader.readLine());
                methode2(x);
            } else if (i == 2) {
                System.out.println("Bis:");
                int x = Integer.parseInt(reader.readLine());
                methode3(1, x);
            } else {
                return;
            }
        } catch (NumberFormatException numberFormatException) {
        }
        methode1();
    }

    private static void methode2(int x) {
        // TODO: naiv
        for (int i = 2; i < x; i++) {
            if (x % i == 0) {
                System.out.println(false);
                return;
            }
        }
        System.out.println(true);
    }

    private static void methode3(int i, int x) {
        if (x < i) {
            return;
        }
        methode3(i, x - 1);
        System.out.println(x);
    }
```


```
1 Primzahltest
2 Liste (rekursiv)
1
Zu testende Zahl:
57
false
1 Primzahltest
2 Liste (rekursiv)
1
Zu testende Zahl:
59
true
1 Primzahltest
2 Liste (rekursiv)
2
Bis:
9
1
2
3
4
5
6
7
8
9
1 Primzahltest
2 Liste (rekursiv)

1 Primzahltest
2 Liste (rekursiv)
3
```

Bearbeitung: Besser ist auch, so eine Methode einfügen:

```
private static int readInt(String msg) throws IOException {
        System.out.println(msg);
        try {
            int i = Integer.parseInt(new BufferedReader(new InputStreamReader(System.in)).readLine());
            return i;
        } catch (NumberFormatException igno) {
            return readInt(msg);
        }
    }
```


----------



## Anfängerin256 (11. Nov 2016)

Hui, da ist noch einiges dabei, das ich noch nie gesehen hab  aber ich glaube ich verstehe den Großteil 
Vielen Dank für Deine Mühe! 
Hast Du eventuell noch eine Idee zu dem "Default-Problem"?
Gibt es eine Möglichkeit die Variablen doch zu nutzen, oder sollte ich die Variablen für Default neu benennen und dann wieder Unterprogramme schreiben?


----------



## Xyz1 (11. Nov 2016)

Mit readInt() sieht's so aus:

```
private static void methode1() throws IOException {
        int i = readInt("1 Primzahltest\n2 Liste (rekursiv)\nx Verlassen:");
        if (i == 1) {
            int x = readInt("Zu testende Zahl:");
            methode2(x);
        } else if (i == 2) {
            int x = readInt("Bis:");
            methode3(1, x);
        } else {
            return;
        }
        methode1();
    }
```

Eigentlich ich auch eher alles mit Schleifen schreiben.

Was soll denn im default-Teil/-Block passieren?

Freut mich, wenn ich helfen konnte, ist ja mal ein hth erfüllt^

(Fault, error, failure - heute alles dabei  )


----------



## Anfängerin256 (11. Nov 2016)

Also zu Beginn soll der Nutzer ja eine Zahl eingeben. Gibt er eine 1 ein wird Case 1, also der Primzahltest, durchgeführt. Gibt er eine 2 ein, wird Case 2 ausgeführt, also wird er erneut zur Eingabe einer Zahl aufgefordert bis zu dieser werden dann alle Zahlen rekursiv ausgegeben. Das klappt mittlerweile auch alles 

Wenn der Nutzer jetzt aber zu Beginn keine 1 oder 2 eingibt, sondern bspw. eine 3, sollen beide Aufgabentypen durchgeführt werden.
Also zuerst soll vom Nutzer eine Zahl eingegeben werden, mit der wieder Case 1 (der ja bereits in einem Unterprogramm beschrieben ist) ausgeführt wird und danach soll noch eine weitere Zahl eingegeben werden, mit der Case 2 (ebenfalls im Unterprogramm beschrieben) ausgeführt werden soll.
Dazu war dann meine Idee der Code, den ich gepostet hatte. Dort lasse ich wieder einen bestimmten Text jeweils passend zum Aufgabentyp ausgeben und dann wollte ich wieder die vorherige Variable eingeben, damit das Unterprogramm nochmal genutzt werden kann.
Da kommt dann ja der Fehler, dass die Variable bereits definiert ist.

Also gehe ich richtig in der Annahme, dass ich zur Korrektur dieses Fehlers die Variablen im Default-Teil (also zur Eingabe der Werte durch den Nutzer) nochmal neu deklarieren und dann auch wieder neue Unterprogramme schreiben muss, da ja sonst die Variablen nicht mehr passen? Oder geht es vielleicht doch einfacher und ich übersehen eine Möglichkeit?
Ich hoffe Du steigst noch durch meine Gedanken durch 

Danke!


----------



## Xyz1 (12. Nov 2016)

Ja, doch, ist verständlich...

Also in Pseudocode hätte ich:

```
Start;
start:
/Take a/;
switch(a) {
  case empty:
        break;
    case 1:
        /Take b/;
        Primzahltest b;
        loop start;
    case 2:
        /Take b/;
        Liste ausgeben b;
        loop start;
    case default:
        /Take b/;
        Primzahltest b;
        Liste ausgeben b;
        loop start;
}
Stop;
```



Ist das ungefähr der Programmablauf/PAP? Muss ich nochmal nachdenken, wie man es ohne Labels löst.

Frage nach dem default, die Eingabe von b muss vor Primzahltest und vor Liste ausgeben schreiben, darf nicht in diesen Methoden schreiben - und muss diesen Methoden übergeben werden. Ist das die Frage gewesen? Wenn es aber umfangreicherer wird, ist Loop und Switch nicht mehr die richtige wahl.


----------



## Xyz1 (12. Nov 2016)

Noch eins, etwas anders:


----------



## JStein52 (12. Nov 2016)

Um in den verschiedenen switch/case/default-Bereichen Variablen mit gleichem Namen anzulegen musst du das in geschweiften Klammern einschliessen. Etwa so:

```
switch(pruefSumme) {
            case 1: {
                    int n=1;
                    // tue irgendwas mit n
                    break;
            }
            case 2: {
                    int n = 2;
                    // tue was anderes mit n
                    break
            }
            default: {
                    int n = 3;
                    // tue das was bei default getan werden soll
            }
        }
```
Ist es das was du wissen willst ?


----------



## Anfängerin256 (12. Nov 2016)

Danke für eure Hilfe, es hat jetzt geklappt.
Ich hatte erst die neuen Variablen im Default noch mit einer 1 versehen (also n1 und eingabe1) und dann neue Unterprogramme angelegt.
Dann hab ich diese auf gut Glück nochmal rausgenommen und das Programm funktioniert jetzt auch ohne die beiden extra Unterprogramme


----------



## JStein52 (12. Nov 2016)

Anfängerin256 hat gesagt.:


> funktioniert jetzt auch ohne die beiden extra Unterprogramme


Ja klar. Das Problem hatte ja auch nichts mit diesen Methoden zu tun sondern nur mit den Namen der Variablen. Lies dir in einem Java-Buch noch mal die Infos zu Gültigkeitsbereichen von Variablen durch.

Den Gültigkeitsbereich kannst du eben auch mit { ... } eingrenzen


----------



## Xyz1 (12. Nov 2016)

Achso, es ging um den Scope gleichnamiger Variablen innerhalb von switch-case-Konstrukten...

Man muss alles innerhalb von switch { ... } wahrscheinlich als ein Sichtbarkeitsbereich ansehen - aber nicht Definitionsbereich.

Wie es auch sei, mir stellt sich diese Frage selten bis gar nicht, weil ich einen "passenden" namen wähle.

Ich bringe hier mal das Zauberwort ins Spiel: Modi .


----------



## JStein52 (12. Nov 2016)

DerWissende hat gesagt.:


> weil ich einen "passenden" namen wähle.


Aber hier war in allen case's/default der passende Name "eingabe", das war ja gerade das Problem.


----------



## Xyz1 (12. Nov 2016)

Also muss man konstatieren, dass der gesamte "Bereich" zwischen switch { ... } einen "Gültigkeitsbereich" (wie du ihn nennst) bildet! Innerhalb des Bereichs ist eine Variable also auch case-/default-übergreifend bis zum Ende des switch definiert und sichtbar. Richtig, oder zu ungenau/inkohärent?


----------



## JStein52 (12. Nov 2016)

Es sei denn du arbeitest mit { ... } in den cases. Aber z.B. so würde es auch gehen:


```
switch(pruefSumme) {
            case 1:
                    int n=1;
                    // tue irgendwas mit n
                    break;
           
            case 2:
                    n = 2;
                    System.out.println("N: "+n);
                    // tue was andees mit n
           
            default: {
                    n = 3;
                    // tue das was bei default getan werden soll
            }
        }
```


----------



## JStein52 (12. Nov 2016)

DerWissende hat gesagt.:


> einen "Gültigkeitsbereich" (wie du ihn nennst) bildet!


Auf neudeutsch "Scope"


----------



## Xyz1 (13. Nov 2016)

Hier nochmal wunderschön:
 
Ich sollte öfterss was mit diesem Flow charts machen... Eckige Kanten habe ich aber noch nicht gefunden. Darf das eigentlich hier 'veröffentlicht' werden?

Jetzt nur noch die frage, wie man es umsetzt:
entweder, wähle unterschiedliche Namen,
oder einen lokalen inneren Block. 

Über Scope will ich mich nicht streiten, im Zweifelsfall ist die genaue Definition nachzulesen.


----------

