StackOverflowError, finde den Fehler nicht

xyt4n

Aktives Mitglied
Hallo nochmal,

also ich habe ein Program geschrieben, das fast vollständig funktioniert. Kurz dazu: 2 Arrays werden lexigrofisch vergleicht.
Leider im Falle a[]=b[] stürzt das Programm ab, da ein Overstockflow fehler passiert. Wobei das m.M.n. gar nicht passieren könnte wegen dem Befehl in Zeile 24

Ich stelle jetzt nur 3 Methoden rein, zum Verständnis und da der Rest m.M.n. entweder richtig ist oder zu komplett anderen Algorithmen gehört.

Java:
	public static int compareArrays(int[] a, int[] b) {

		if (a.length == 0 && b.length > 0)
			return -1;
		else if (a.length == 0 && b.length == 0)
			return 0;
		else if (a.length > 0 && b.length == 0)
			return 1;
		else if (a[0] < b[0])
			return -1;
		else if (a[0] == b[0])
			return compareArrays(tail(a), tail(b));
		else if (a[0] > b[0])
			return 1;
		return 0;
	}

	public static int[] tail(int[] a) {
		if (a.length > 1) {
			for (int i = 1; i < a.length; i++)
				a[0] = a[i];
			return a;
		}
		int b[] = {}; // Fuer den letzten Durchlauf bei Länge 1
		return b;

// mehrere Methoden wie cut usw.

	public static void main(String[] args) {
		int[][] a1 = { { 0, 2, 3 }, { 0, 2, 3, 8 } };
		int[][] a2 = { { 3, 4, 7, 8 }, { 3, 4, 8, 0 } };
		int[][] a3 = { { 7, 8 }, { 7, 8 } };
		System.out.println(compareArrays(cut1(a1), cut2(a1)));
		System.out.println(compareArrays(cut1(a2), cut2(a2)));
		System.out.println(compareArrays(cut1(a3), cut2(a3))); //Fehler!! Overstockflow

// mehrere weitere Methoden die nicht zum Problem gehören 
}

}
	}
 
Der Java-Compiler nimmt keine Tail-Recursion-Optimizations vor. Du wirst also dein
Code:
return compareArrays(tail(a), tail(b));
zu einer geeigneten Schleife umschreiben müssen.

Dein Code erinnert zwar ganz stark an funktionale Programmierung, aber auf diese Weise wird man in Java nicht weit kommen. (Was nicht heißen soll, dass es keine anderen Konstrukte in Java gäbe, die funktional aussehen, und ebensowenig sei damit die funktionale Programmierung als solche abgewertet.)

Ark
 
Der Java-Compiler nimmt keine Tail-Recursion-Optimizations vor. Du wirst also dein
Code:
return compareArrays(tail(a), tail(b));
zu einer geeigneten Schleife umschreiben müssen.

Dein Code erinnert zwar ganz stark an funktionale Programmierung, aber auf diese Weise wird man in Java nicht weit kommen. (Was nicht heißen soll, dass es keine anderen Konstrukte in Java gäbe, die funktional aussehen, und ebensowenig sei damit die funktionale Programmierung als solche abgewertet.)

Ark

Okay, gibt es also keinen genauen Fehler? Es ist komisch da der Befehl return compareArrays(tail(a), tail(b)); 1zu1 von meinem Prof erwartet wird :/

Was meinst du mit der Kritik an meinen Programmierstil? Soll ich etwa objektorientierter arbeiten? Bin erst Erstsemestler.
 
Okay, ich gebe zu, ich habe wohl was übersehen. Hier mal eine (hoffentlich funktionierende) Korrektur:
Java:
	public static int[] tail(int[] a) {
		int b[] = new int[a.length - 1]; // fails if a is empty or null
		for (int i = 0; i < b.length; i++){
			b[i] = a[i + 1];
		}
		return b;
	}
[EDIT]Dennoch wird man mit diesem Stil in Java nur eher selten (etwa in speziellen Multithreading-Szenarien) auf einen grünen Zweig kommen. Ach, ja, und "Overstockflow" klingt nach DAX-Allzeithoch. 😀[/EDIT]
Ark
 
Zuletzt bearbeitet:
Okay, ich gebe zu, ich habe wohl was übersehen. Hier mal eine (hoffentlich funktionierende) Korrektur:
Java:
	public static int[] tail(int[] a) {
		int b[] = new int[a.length - 1]; // fails if a is empty or null
		for (int i = 0; i < b.length; i++){
			b[i] = a[i + 1];
		}
		return b;
	}
[EDIT]Dennoch wird man mit diesem Stil in Java nur eher selten (etwa in speziellen Multithreading-Szenarien) auf einen grünen Zweig kommen. Ach, ja, und "Overstockflow" klingt nach DAX-Allzeithoch. 😀[/EDIT]
Ark

Super! Auch wenn ich nicht weiß wieso meins falsch ist.
Vielen Dank!

Aber was für ein Problem gibt es mit meinem Programmierstil?
Ich will langfristig gut programmieren können, darum würde es mich sehr interessieren was du meinst.
Das einzigste was mir einfallen würde wäre Ineffizienz, wobei es für mich auch ein schweres Thema ist.
 
Super! Auch wenn ich nicht weiß wieso meins falsch ist.
Sieh mal genau hin, welche Länge das Array hat, das du in deiner ursprünglichen tail()-Implementierung zurückgegeben hast.

Aber was für ein Problem gibt es mit meinem Programmierstil?
Ich will langfristig gut programmieren können, darum würde es mich sehr interessieren was du meinst.
Das einzigste was mir einfallen würde wäre Ineffizienz, wobei es für mich auch ein schweres Thema ist.
Dito. An der Quelltext-Formatierung gibt es fast nichts auszusetzen.* Das ständige Hin- und Herkopieren ist allerdings nur selten wirklich nützlich. Auch unnötige Endrekursionen sollten vermieden werden (zumindest bei Sprachen, bei denen das nicht vom Compiler in eine Schleife umgebaut wird). Das hat alles etwas mit dem Laufzeitverhalten zu tun (Stichwort: Komplexität).

Der Code erinnert ein wenig an den Versuch (eines Profs?), das Gefühl von funktionaler Programmierung von Java zu bekommen. Wenn du eher funktional programmieren willst/sollst, wäre z.B. Haskell wesentlich geeigneter.

Als Anfänger ist es aber tatsächlich wichtiger, das Schreiben von korrektem Code zu üben (was nicht heißen soll, dass dies später nicht auch wichtig wäre). Tendentiell, so meine Erfahrung, ist korrekter Code meist klarer/einfacher/übersichtlicher als eine (frühere) fehlerhafte Implementierung.** Auch in dem Punkt lohnt ein Blick zu Haskell. Insofern: Mach einfach weiter, so schlecht sieht das für den Anfang gar nicht aus. Sei dir aber dessen bewusst, dass da noch viel Luft ist, um das Laufzeitverhalten zu verbessern. 😉



*: Mehr {…} würden deinem Code durchaus guttun. Vor allem Schleifen sollten immer mit einem Anweisungsblock versehen werden. Bei if/else sehe ich das dagegen nicht so eng, vor allem nicht bei
Code:
return
,
Code:
throw
,
Code:
break
,
Code:
continue
. Wo andere lieber
Java:
if(abc) {
	return 0;
}
schreibe ich eben
Java:
if(abc) return 0;
Dieser Schreibstil ist zwar nicht allzu verbreitet, spart aber viele fast leere Zeilen. Versehentlich die Klammern {…} zu vergessen, wenn man Anweisungen hinzufügen möchte, ist so auch eher unwahrscheinlich, weil man dazu entweder noch einen Zeilenumbruch einarbeiten müsste oder mehrere Anweisungen in eine Zeile schreiben würde (und das wird man wohl noch mitkriegen).


**: Darüber hinaus gibt es in sauberem und korrektem Code meist viel Spielraum für Performance-Optimierungen.

Ark
 
Zuletzt bearbeitet:

Neue Themen


Zurück
Oben