Ga naar het forum
Java-probleempje!
 
Meldingen
Alles wissen

[Gesloten] Java-probleempje!

17 Berichten
4 Gebruikers
0 Reacties
1,929 Weergaven

Wie heeft er hier veel verstand van programmeren met java? Ik kom zelf ook een aardig eind, maar ik krijg nu iets heel raars. Ik gebruik namelijk twee dubbele arrays, beide van de vorm int[][]. Noem ze even 'a' en 'b'.

Het probleem is nu, dat als ik zoiets zeg als: a[5][5] = a[5][5] - 4, dat dan niet alleen element a[5][5] wordt aangepast, maar dat ook b[5][5] verandert. Om het te testen drukte ik de waarde van a[5][5] en b[5][5] af, en direct na het bovenstaande commando laat ik weer beide waarden afdrukken, en dan blijkt dat beide waarden met 4 verlaagd zijn. Terwijl ik verder helemaal niks met de waarden van b[][] doe. Dit kan toch helemaal niet? Het lijkt wel alsof de pc die twee arrays niet goed uit elkaar kan houden of zo, net alsof ze hetzelfde geheugenplekje hebben gekregen.

Weet iemand misschien of het kan dat java verschillende arrays door elkaar kan halen? Daar lijkt het namelijk verdacht veel op!

EDIT: Zie net dat het mijn 400ste post is. Laat die nou net totaal niks met poker te maken hebben. :P


16 reacties

Hy,

zou het kunnen dat je ergens de instructies gelinkt hebt? Je mag me de desbetreffende code altijd doorzenden naar robert.stohr@ hotmail.com, het zal waarschijnlijk een nietigheid zijn dat je over het hoofd ziet


Post de code is.

Ik ben al heel de voorbije week aan't leren voor het programmeren-exaam van morgen.


Gezien de vlotte reacties zal ik maar een stuk code posten. Ik maakte het eigenlijk voor de lol, naar aanleiding van een lezing over zandhoopmodellen. Ik post niet alle code, alleen het relevante stuk. De methode wordt ergens anders aangeroepen in een main.

Een stuk code. Die stomme #@#^$&%^$# gaat helaas alle regels naar links uitlijnen, zelfs als ik een punt aan het begin van elke regel plaats. Helaas, ik krijg die harde tabs niet in deze post.

-----------------------------------------------------------------
private int[][] gr;
private int[][] grid;

public tijdverdrijf(int[][] g)
{
gr = g;
grid = g;
int teller;
int teller2;

...

for(int i = 0; i < 10; i++)
{
for(int j = 0; j < 10; j++)
{
teller2 = 0;
while(gr[j] - teller2 >= 4)
{
System.out.println("gr[" + i + "][" + j + "] = " + gr[j]);
teller = 0;
if(i>0)
{
grid[i-1][j]++;
teller++;
}
if(i<9)
{
grid[i+1][j]++;
teller++;
}
if(j<9)
{
grid[j+1]++;
teller++;
}
if(j>0)
{
grid[j-1]++;
teller++;
}
grid[j] = grid[j] - teller;
teller2 = teller2 + teller;
System.out.println("gr[" + i + "][" + j + "] = " + gr[j]);
System.out.println("grid[" + i + "][" + j + "] = " + grid[j] + "\n");
}
}
}
gr = grid;
setVisible(true);
repaint();
}

-----------------------------------------------------------------

Deze methode krijgt dus een dubbele array van ints binnen. In de dubbele for-loop wordt elk punt uit gr[][] langs gegaan. De waarde van elk punt stelt het aantal zandkorrels voor. Ik wil nu, dat elk gridpunt met waarde groter of gelijk aan 4, één zandkorrel aan elk van zijn vier buren afstaat, net zo lang totdat er minder dan 4 korrels over zijn. Ik gebruik "teller2" in de while om te controleren of het gridpunt al kleiner dan 4 is. "teller" heb ik alleen nodig bij het controleren van randpunten die maar twee of drie buren hebben. Het is de bedoeling dat heel gr[][] uitgelezen wordt en dat de wijzigingen dan in grid[][] worden doorgevoerd. Dus ik wil dat gr[][] ongewijzigd blijft in de loops, en dat grid[][] dus het nieuwe plaatje wordt.

Het gaat echter onverwacht fout. In de 'while' heb ik een paar printopdrachten neergezet om de waarden te controleren. Als ik deze methode aanroep, geef ik hem een grid mee met alle waarden gelijk aan nul, alleen g[4][4] = 24. De output die ik dan krijg uit die System.out.println 's is als volgt:

gr[4][4] = 24
gr[4][4] = 20
grid[4][4] = 20

gr[4][4] = 20
gr[4][4] = 16
grid[4][4] = 16

gr[4][4] = 16
gr[4][4] = 12
grid[4][4] = 12

Terwijl grid[4][4] dus binnen de 'while' steeds met 4 verlaagd wordt, wordt op mysterieuze wijze ook gr[4][4] steeds met 4 verlaagd. "teller2" wordt steeds keurig met 4 verhoogd. Na drie stappen geldt de 'while' niet meer, omdat 12 - 12 niet >= 4 is. Ik had dus verwacht dat de output zou zijn:

gr[4][4] = 24
gr[4][4] = 24
grid[4][4] = 20

gr[4][4] = 24
gr[4][4] = 24
grid[4][4] = 16

...

gr[4][4] = 24
gr[4][4] = 24
grid[4][4] = 0

Iemand enig idee hoe het mogelijk is dat de waarde van gr[4][4] binnen de 'while' ook steeds verlaagd wordt, terwijl ik helemaal niks met gr[][] doe? Merk op dat de regel "gr = grid;" pas helemaal aan het einde van alle loops komt en dus niks met het probleem te maken heeft.


Hou je er rekening mee dat arrays beginnen te tellen bij 0 ?

Voor de rest is het zonder uitlijning echt wel moeilijk om zien. Je moet het maar es doorsturen via skype/msn ofzo -> Dit zal echter niet voor deze week zijn want ik heb echt een ontzettend drukke periode voor de boeg.

Hetgeen je zegt van die gr = grid op het einde enzo -> quote dit eens ff uit en kijk of je probleem zich nog steeds voordoet.


Oorspronkelijk gepost door Deltathree
Hou je er rekening mee dat arrays beginnen te tellen bij 0 ?

Voor de rest is het zonder uitlijning echt wel moeilijk om zien. Je moet het maar es doorsturen via skype/msn ofzo -> Dit zal echter niet voor deze week zijn want ik heb echt een ontzettend drukke periode voor de boeg.

Hetgeen je zegt van die gr = grid op het einde enzo -> quote dit eens ff uit en kijk of je probleem zich nog steeds voordoet.

Ja, ik houd er rekening mee dat arrays bij 0 beginnen. Dit staat ook goed in de for-loops. Ik krijg die uitlijning helaas niet echt goed hier. Ik heb het ook al getest zonder die regel "gr=grid;" en het ging nog steeds fout. Ik heb echter geen msn/skype en was ook niet van plan daar iets aan te veranderen. Maar eigenlijk hoef je alleen die 'while-loop' te bekijken. Als het programma de eerste keer in die while-loop komt, dan print hij bij die System.out.println dus waarde 24 uit, en bij die tweede keer print hij waarde 20 uit. Dit gebeurt nog binnen één en dezelfde keer. Dit betekent dat in de code ertussen de waarde met 4 verlaagd wordt.

Het gaat dus al fout in het uitvoeren van één keer deze code:

System.out.println("gr[" + i + "][" + j + "] = " + gr[j]); // geeft waarde 24
teller = 0;
if(i>0)
{
grid[i-1][j]++;
teller++;
}
if(i<9)
{
grid[i+1][j]++;
teller++;
}
if(j<9)
{
grid[j+1]++;
teller++;
}
if(j>0)
{
grid[j-1]++;
teller++;
}
grid[j] = grid[j] - teller;
teller2 = teller2 + teller;
System.out.println("gr[" + i + "][" + j + "] = " + gr[j]); // geeft waarde 20

De rest van de code was puur ter context. Maar in dit bovenstaande stukje code gaat het dus fout, want de waarde van gr[4][4] wordt met 4 verlaagd. Dit kan toch nooit als ik nergens in dit stuk een regel heb van de vorm "gr[j]= ... ;"?


Ik weet wat je fout is.

Maak eens andere variablen aan voor de indexering van die arrays : BV voor gr m & n en voor grid ij zoals het nu is.

Je waarde daar veranderd niet, maar in dat stukje code pas je wel de waarde van i & j aan waardoor je in je array naar een ander element verwijst

gr[m][n]

...
code met oa grid[j]
...

gr[m][n]

dit zou moeten werken


Oorspronkelijk gepost door Deltathree
Ik weet wat je fout is.

Maak eens andere variablen aan voor de indexering van die arrays : BV voor gr m & n en voor grid ij zoals het nu is.

Je waarde daar veranderd niet, maar in dat stukje code pas je wel de waarde van i & j aan waardoor je in je array naar een ander element verwijst

gr[m][n]

...
code met oa grid[j]
...

gr[m][n]

dit zou moeten werken

Ik zie totaal niet in waarom dit zou moeten werken. Ik verander nergens de waarden van i en j zoals jij zegt. Die waarden veranderen pas als je in de volgende stap van een for-loop komt.

Bovendien: als ik gr[m][n] neem en dan iets wil wijzigen in grid[j], dan is niet bekend wat i en j zijn. Dat kan ik natuurlijk wel declareren door binnen de while te zeggen: i = m; j = n; maar in feite doe ik dan precies hetzelfde als wat ik nu doe.

De reden dat ik voor beide arrays dezelfde index gebruik: als een element i,j van gr aan een bepaalde voorwaarde voldoet, dan moet element i,j van grid (en zijn buren) aangepast worden.

Ik heb echt genoeg verstand van java om te beseffen dat je voor beide arrays dezelfde indexletters mag gebruiken. Als je maar begrijpt wat de consequenties zijn. Als je bijvoorbeeld twee arrays van elk 100 getallen wilt "vullen", dan doe je toch ook gewoon zoiets als dit:
-------------
for(int i = 0; i < 100; i++)
{
array1 = ...;
array2 = ...;
}
-------------
Dit werkt namelijk ook prima, en hier gebruik je toch ook twee keer de letter 'i' voor verschillende arrays? Dit mag gewoon hoor!

Ik ben trouwens best bereid om jouw voorstel te proberen hoor, maar dan ben ik wel benieuwd hoe ik volgens jou dan duidelijk moet maken wat 'i' en 'j' zijn, als de 'loops' over de variabelen 'm' en 'n' lopen.


Ja ok!

Je hebt absoluut gelijk, maar ik had totaal niet door dat je dezelfde indexes nodig had.

'k Heb het verkeerd gezien.

Wat als je nu eens ff een system.out.println doet op die indexes en ff kijkt of het de indexes zijn die veranderen of de waarden in de array zelf


Oorspronkelijk gepost door Deltathree
Ja ok!

Je hebt absoluut gelijk, maar ik had totaal niet door dat je dezelfde indexes nodig had.

'k Heb het verkeerd gezien.

Wat als je nu eens ff een system.out.println doet op die indexes en ff kijkt of het de indexes zijn die veranderen of de waarden in de array zelf

System.out.println("gr[" + i + "][" + j + "] = " + gr[j]);

Zoals je ziet uit bovenstaande printregel laat ik gr[j] afdrukken, waarbij ik dus de waarde van die 'i' en die 'j' laat afdrukken tussen die rechte haken. Dat zijn dus ook de waardes die die 'i' en die 'j' echt hebben. En elke keer weer wordt er iets van de vorm gr[4][4] = ... geprint, dus die waarde 'i' en 'j' die veranderen niet tijdens het uitvoeren van die 'while'. In dit geval blijven die dus beide gelijk aan 4 gedurende die hele 'while'.

Je hebt onderhand vast wel gemerkt dat ik geen totale beginner ben in java. Ik heb al een vak programmeren in java gehad en ik heb laatst met een groepje een heel programma moeten maken in java. Ik maak dus geen foutjes met foute indexnummers en ik haal ook niet zomaar dingen door elkaar. Ik kan de code lezen en ik begrijp bijna bij elke regel precies wat het programma doet en wat de waardes van alle variabelen zijn. Als ik tóch van die standaardfoutjes maak, dan snap ik aan de hand van de errors meestal wel wat ik fout doe. Het probleem is hier dus dat het programma een element in beide arrays wijzigt, terwijl ik slechts de opdracht geef om maar één van de arrays te wijzigen. Ik zie gewoon nergens een coderegel die ook maar iets in array gr[][] wijzigt binnen die 'while' en toch wordt die wel gewijzigd.

Het lijkt er dus gewoon verdacht veel op dat beide arrays op dezelfde geheugenplek bewaard worden, zodat hij altijd allebei tegelijk verandert. Dus als ik element [4][4] wijzig in de ene, dat ie dat dan tegelijk ook in de andere doet, zonder dat ik daar opdracht toe geef.


Ja ok, ik twijfel niet aan het feit dat je kan programmeren in java hoor

Dit is inderdaad wel een rare. Het enige dat ik me nu kan bedenken is dat java die arrays op dezelfde geheugenadressen wegschrijft. Probeer eens een andere naam te gebruiken voor gr en grid , hoewel dit waarschijnlijk niets uithaalt kan je het wel altijd proberen. Java kan soms moeilijk doen op dat gebied. run ook eens de garbage collector die wss wel in je compiler zit (bv. netbeans)

Als dit niet werkt wil ik het project echt wel zelf eens bekijken


Ik heb het ook al geprobeerd door ze niet 'gr' en 'grid' te noemen, maar 'grid' en 'nieuw'. Dit veranderde helemaal niks aan het probleem.

Oorspronkelijk gepost door Deltathree
run ook eens de garbage collector die wss wel in je compiler zit (bv. netbeans)

Leg even uit wat je hiermee bedoelt, want hier heb ik geen verstand van.


Ik heb nog iets anders getest. Ik maakte het even zo, dat ik binnen de 'while' eerst van beide arrays de waarde uitprintte in [j], dan komt alléén de regel "grid[j] = grid[j] - 4;" en direct daarna print ik weer van beide arrays de waarde in [j]. Het resultaat: het element [j] van beide arrays is met 4 verlaagd. Het lijkt er dus verdacht veel op dat hij inderdaad beide arrays in dezelfde geheugenplaats zet.

Het van te voren opgeven van de size van de arrays helpt trouwens ook niet, heb ik net ook geprobeerd.


Heb het probleem opgelost (nou ja, omzeild eigenlijk).

Ik heb de ene dubbele array vervangen door een enkele array. Dit is wat lastig in de loopjes. Heb nog steeds een dubbele loop met zowel 'i' als 'j', en als voorwaarde binnen de 'while' heb ik nu die enkele array met index [10*i+j]. Staat een beetje raar natuurlijk en onlogisch, maar ik heb het door goede redenatie opgesteld en het werkt. Omdat de twee arrays nu dus echt structureel verschillen, maakt java niet meer de fout ze beiden aan te passen.

Ik kan met mijn programma nu hele leuke plaatjes laten maken, door zulke 'grids' te laten tekenen op een scherm waarbij de waarde van een punt de kleur in dat punt bepaald.

Maar wel bedankt voor de reacties allen.


Misschien dom dat ik hier nog op reageer :P Maar ik heb straks examen C# en ineens kwam ik een fout tegen die hier ook van toepassing kon zijn.

public tijdverdrijf(int[][] g)
{
gr = g;
grid = g;
int teller;
int teller2;

Hier zit volgens mij de fout al. Je geeft hier een array mee en dan stel je beiden arrays gelijk aan g, hierdoor gaan ze dus ook allebei naar dezelfde geheugenplaats verwijzen als de oorspronkelijke g.
gr = g en grid = g, kopieert niet de gegevens maar laat ze gewoon naar dezelfde geheugenplaats verwijzen.
Oplossing zou zijn om 1 array ernaar te laten verwijzen en de andere met een loop op te vullen en 1 voor 1 de elementen te kopieren.


Nee hoor, helemaal niet dom, reageer gerust. Bedankt voor je opmerking, want misschien heb je wel gelijk. Ik heb niet zo veel verstand van de manier waarop objecten een verwijzing naar een geheugenplaats hebben. Ik dacht dat gr = g en grid = g twee nieuwe arrays zou maken, die dan ook nieuwe geheugenplaatsen krijgen, maar gezien de rare fouten die ik eerder in deze thread omschreef, kan ik haast niets anders dan concluderen dat je gelijk hebt.

Bedankt voor het aanwijzen van de plek waar het fout gaat, en nog veel succes met je tentamen gewenst.


Hey.

Sorry dat ik deze thread nogis bump, maar dit semester krijg ik ook Java en tijdens een recente opzoeking kwam ik ook iemand tegen met dit soort fout, en het bleek gewoon geheugenallocatie-problemen te zijn :(