# Code Analyse



## Tommy1169 (5. Jun 2006)

Hallo an alle:

Ich bin hier sowas von neu, daß ich gleich mal mein erstes Posting mache.

Ich habe folgenden Code zu analysieren und die Ausgabe in der Konsole zu bestimmen:


```
package de.Inf1_KlausurAufgabe1;

public class Array_org 
{
	public final byte NOTHING = -1;
	public int[] myList = {9,0,9,7,5,1,2,4,9,5};
	
	public Array_org()
	{
		do_operation();
		int[] y = go(myList);
		for (int i = 0; i < y.length; i++)
		{
			System.out.println("::y[" +i+ "] = " + y[i]);
		}
	}
	
	public int[] go(int[] x)
	{
		int counter = 0;
		
		for (int i = 0; i < x.length; i++)
			if (!(x[i] == NOTHING)) 
					counter++;
					int[] y = new int[counter];
					int j = 0;
		
					for (int i = 0; i < x.length; i++)
					{
						if (x[i] != NOTHING)
						{
							y[j] = x[i] * x[i];
							j++;
						}
					}
	return y;
	}
	
	private void do_operation()
	{
		int[] x = myList; 
		int i = 0; 
		int j = i+1;
		
		while (i < x.length)
		{
			while (j < x.length)
			{
				if (x[i] == x[j]) 
				x[j] = NOTHING;
				j++;
			}
			i++;
			j = i + 1;
		}
		System.out.print("[do] x[] = { ");
		
		for (i = 0; i < x.length; i++)
		{
			System.out.print(x[i]);
			if (i != x.length - 1) 
				System.out.print(", ");
			else
				System.out.print(" }\n");
		}
	}

	public static void main(String[] args)
	{
		Array_org  gg = new Array_org ();
	}
}
```

Soweit, sogut.

Bisher ist mir folgendes einigermaßen klar:

In der Mainmethode(zeile 68) wird die Instanz "gg" erzeugt.
Diese ruft standartmässig den Konstruktor(zeile 8) der Klasse "Array_org" auf.

Nun wird ein Array names "int[]y"(zeile 11) deklariert und es bekommt die Werte aus dem Array "myList" 
über den Aufruf der Methode "go" zugewiesen.

Die Methode "go"(zeile 18) ruft nun als erstes die Methode "do_operation"(zeile 39) auf, in der als erstes ein Array 
namens "x" erzeugt und mit den Werten des Ursprungsarrays "myList" gefüllt wird.
Weiter werden die Variablen "i" und "j" deklariert. "i" wird mit dem Wert 1 und "j" mit dem Wert i+1 also 2 initialisiert.
Die folgende While-Schleife läuft solange, wie "i" kleiner ist, als die Länge des Arrays "x".
In der ersten While-Schleife kommt eine neue While-Schleife die solange läuft, wie j kleiner ist als 
die Länge des Arrays "x" dessen Länge = 10 ist, also 10 mal.

Mit der if-Verzweigung(zeile 49) wird nun das Array "x" auf Gleichheit der Laufzeitvariablen "i" und "j" geprüft.
Ist Gleichheit gegeben, wird die LZ-Variable "j" auf den Wert von "NOTHING" also -1 gesetzt.
Danach wird "j" um 1 erhöht, ist dann also 0. Das wird solange durchgeführt, bis "j" den Wert 9
erreicht hat, danach wird der Schleifenrumpf verlassen, "i" um eins erhöht und "j" bekommt den
Wert von "i" +1.

Nun kommt die erste Ausgabe: "[do] x[]={" gefolgt von der Ausgabe des durchlaufabhängigen Wertes
der Elemente des Arrays "x" bzw. "myList". Die for-Schleife läuft 10 mal durch und bricht dann ab. 
Bei jedem Durchlauf wird der aktuelle Wert der Elemente vom Array "x" ausgegeben.
Die Verzweigung danach dient nur der Formatierung der Ausgabe.

Als ersten Wert dieser Ausgabe erhalte ich die 9, allerdings fehlt mir für die weiter ausgegebenen Werte die Erklärung wie das zustande kommt und genau da liegt mein Problem!

Wenn irgendjemand weiß wie die weiteren Werte zustande kommen wäre ich für eine Erklärung sehr dankbar.
Ich hoffe ich hab das hier nach den Forenrules gepostet, wenn nicht sorry

Gruß Tom  :roll:


----------



## mattulla (8. Jun 2006)

Also ich versuche dir den Code mal zu erklaeren:

zunaechst wird eine Instanz der Klasse Array_org erstellt, im Konstruktor wird dann die Methode dperation aufgerufen. Dort wird dann zunaechst die Referenz auf das Feld list kopiert. Das heisst es gibt nun 2 Referenzen (myList und x) welche beide auf das gleiche Feld zeigen. Die erste der beiden while-Schleifen durchlauft dann die Kopie von dem array einmal komplett von vorne nach hinten. Die zweite Schleife hingegen startet immer eine Position hinter der aktuellen Position der erstn Schleife und laeuft ebenfalls bis hinten durch. In der zweiten while-Shcleife werden die beiden aktuellen Felder (i und j) verglichen, sind diese gleich so wird der wert von x[j] auf NOTHING gesetzt. NOTHING ist eine Konstante und steht fuer -1.....siehe Zeile 5. Sind beide Schleifen komplett durchgelaufen stehen in dem Feld x nun also keine doppelten Werte mehr drin. An den Stellen wo eine Zahl zum zweiten mal auftaucht wurde -1 in das Feld geschrieben. In der dann folgenden for-Schleife wird das ganze Feld dann einfach nur noch ausgegeben.

Danach wird im Konstruktor go(myList) aufgerufen. In den ersten drei Zeilen der Funktion wird abgezaehlt wie oft in myList noch was anderes als Null drin steht. Die for-Schleife geht also nur bis zur Zeile 24 ienschliesslich. Man koennte zunaechst meinen, dass sie weiter geht, dies ist aber nicht der Fall. Die Einrueckungen sind hier shclicht falsch. Danach wird ein neues Feld j von vorher errechneter Groesse angelegt. In dem Feld j werden nun in der naechsten for-Schleife alle Quadratzahlen aus myList gespeichert (Ausnahme auch hier wieder -1, bzw. NOTHING). Das Feld y wird nun an den Konstruktor zurueckgegeben.

In der for-Schleife des Konstruktors wird nun lediglich noch die Ausgabe gemacht. 


Hoffe das hilft dir etwas weiter!

Gruesse
mattulla


----------



## Tommy1169 (8. Jun 2006)

Erst einmal vielen Dank daß Du Dich meinem Problem angenommen hast.  :toll: 



> in myList noch was anderes als Null drin steht


Frage: 
muss es nicht heissen: "in my List noch was anderes als -1 drin steht"? 

Warum sind die Einrückungen falsch? Im Ergebnis verändert sich aber aber nichts dadurch oder?
Wie sähe denn eine bessere Einrückung in diesem Bereich aus?

Gruß Tom   

Ps: Ich habe den Code heute zuende analysiert und bin auch auf das richtige Ergebnis gekommen, aber ist es Deiner Einschätzung nach möglich, die Ausgabe innerhalb von 30 Min zu bestimmen? Ich hab daran 6h gesessen und mir 6 volle Seiten Notizen gemacht. Es müsste doch ein/en einfachen Weg/Schema geben sich durch die Zahlreichen Schleifendurchläufe zu arbeiten.  ???:L


----------



## Redfrettchen (8. Jun 2006)

Hi,
die Einrückungen suggerieren, dass der eingerückte Code an dieser Stelle zur if-Verzweigung gehört, obwohl er nicht mal mehr zu der Zählschleife gehört. Eindeutiger wäre z.B.:

```
for (int i = 0; i < x.length; i++) 
         if (!(x[i] == NOTHING)) 
               counter++;
      int[] y = new int[counter]; 
      int j = 0; 

      for (int i = 0; i < x.length; i++) 
      { 
          if (x[i] != NOTHING) 
          { 
              y[j] = x[i] * x[i]; 
              j++; 
          } 
      }
```

Also es ist schon möglich, das ganze in ein paar Minuten (max. 5) zu überblicken, aber es bedarf dazu viel Übung, sowohl im Schreiben als auch im Lesen von Programmcode.
Beim prozeduralen/objektorientiert-prozeduralen Programmieren kann man (fast) immer einen Einstieg finden, nämlich wie in diesem Beispiel in der main-Methode. Man schaut sich jede Zeile an und notiert oder merkt sich Änderungen in Eingabedaten (oder erzeugte Objekte). Im vorliegenden Fall kann man sogar tricky schauen, was im Endeffekt ausgegeben wird, nämlich immer Elemente eines Arrays. Also muss man sich im Grunde nur die Änderungen des Arrays, dass ja, wie sich schnell herausstellt, das Eingabearray myList ist, konzentrieren. Bei komplexeren Strukturen, wie verschachtelte Schleifen und if-Verzweigungen sollte man stark an den Ausgangsdaten arbeiten und sich vorstellen, was das Programm genau macht. Beim Array zum Beispiel kann man sich bei Indexnummern, wie im vorliegenden Code i und j, immer Zeiger vorstellen, die auf Zellen von Zahlen zeigen. i++ bedeutet dann eben, dass der Zeiger (also die Repräsentation als Pfeil) weitergeschoben wird. Bei Zählschleifen wie im vorliegenden Beispiel handelt es sich meist um den kompletten Durchlauf eines Arrays. usw.
Also man muss sich eben vorstellen können, was intern passiert. Und das lernt man eben, wenn man selber Code produziert und sich überlegen muss, wie das Programm die Aufgabe lösen soll.


----------



## Tommy1169 (8. Jun 2006)

Ja OK vielen Dank.
Das mit der Einrückung hab ich denke ich, verstanden.

Also Codes analysieren bis der Arzt kommt? Oha


----------



## DEvent (9. Jun 2006)

Ich weis nicht obs wichtig ist aber die Methode:

```
public int[] go(int[] x) 
   { 
      int counter = 0; 
       
      for (int i = 0; i < x.length; i++) 
         if (!(x[i] == NOTHING)) 
               counter++; 
               // ----------------------------
               int[] y = new int[counter];
               // ----------------------------
               int j = 0; 
       
               for (int i = 0; i < x.length; i++) 
               { 
                  if (x[i] != NOTHING) 
                  { 
                     y[j] = x[i] * x[i]; 
                     j++; 
                  } 
               } 
   // ----------------------------
   return y; 
   // ----------------------------
   }
```
ist nicht korrekt.
Was liefert sie denn wenn das Array x 0 Elemente hat, oder wenn im x - Array nur NOTHING steht ?
Die Variable y wurde dann nicht definiert.


----------



## Tommy1169 (9. Jun 2006)

Wenn x 0 Elemente hat wird auch y 0 Elemente haben!?

Wenn alle Elemente von x NOTHING sind, wird y keine Werte erhalten!?
Sehe ich das richtig?

Ok, das war eine Klausuraufgabe von vor über einem Jahr. 
Sowas nennt man dann wohl Definitionslücke   
Aber da der Code so vorgegeben war...

Tom


----------



## Murray (9. Jun 2006)

Tommy1169 hat gesagt.:
			
		

> Sowas nennt man dann wohl Definitionslücke



Man könnte daraus aber auch eine schnelle Lösungsvariante der Aufgabe ableiten:
1. y ist innerhalb des if-Blocks deklariert und daher auch nur dort sichtbar
2. Die return-Anweisung der Methode go verwendet also eine in diesem Scope nicht sichtbare Variable
3. Damit ist die Klasse nicht übersetzbar
4. Ohne Bytecode keine Ausgabe  :wink:


----------



## mattulla (9. Jun 2006)

Tommy1169 hat gesagt.:
			
		

> > in myList noch was anderes als Null drin steht
> 
> 
> Frage:
> muss es nicht heissen: "in my List noch was anderes als -1 drin steht"?




Da hast natuerlich Recht.....also was das zeitliche angeht, ich habe das ganze in ca. 20 Minuten geschrieben. Wenn man bedenkt, dass das nicht ganz vollstaendig ist passt das mit den 30 Minuten schon. Ueberblicken kann man das ganze auch schneller, allerdings muss es ja auch noch aufs Papier gebracht werden. Naja die richtigen Freaks schaffen es vll trotzdem in 15 min oder so


----------



## Tommy1169 (10. Jun 2006)

Ich wollte nicht klugscheissen,
dafür bin ich in Java wirklich nicht gut genug, wollte bloss auf diesem Wege ausdrücken dasich Deine Erklärung nachvollziehen kann. 
Wenn ich das inner halben Stunde könnte...  :cry: 

Aber Thx an alle, ich geb mir Mühe und dann wird datt schon  

***Oh verdammt nu hab ich ais Versehen das Ding 3 mal abgeschickt. Kann die letzten beiden jemand löschen?***

_[Edit by einem Heinzelmännchen: Ja]_

sorry


----------

