A loop (for) inside a loop (for)
#1

Hi guys, I've got a problem with this code:

Code:
LoadTerrain()
{
	new lString[128];
	for(new j; j<MAX_TERRAINS; j++){
		format(Query, sizeof(Query), "SELECT * FROM Terrain WHERE ID = '%d'", j);
		mysql_query(Query);
		mysql_store_result();
		if(mysql_num_rows() != 0){
			if(mysql_fetch_row_format(Query,"|")){
				sscanf(Query, "p<|>e<ds[24]ddfffffffddddf>", TerrainInfo[j]);
				TerrainCount++;
			}
			if(TerrainInfo[j][tStatus] == true)	{
			    format(lString, 128, "Lotto{FFFFFF} N: %d", TerrainInfo[j][tID]);
			}
			else{
			    format(lString, 128, "Lotto{FFFFFF} N: %d\nIn vendita", TerrainInfo[j][tID]);
			}
			TerrainInfo[j][tPick] = CreatePickup(1239, 1, TerrainInfo[j][tX], TerrainInfo[j][tY], TerrainInfo[j][tZ], 0);
			TerrainInfo[j][tLabel] = Create3DTextLabel(lString, 0xC4C400FF, TerrainInfo[j][tX], TerrainInfo[j][tY], TerrainInfo[j][tZ]+0.5, 40.0, 0, 0);
			TerrainInfo[j][tZone] = GangZoneCreate(TerrainInfo[j][tminX], TerrainInfo[j][tminY], TerrainInfo[j][tmaxX], TerrainInfo[j][tmaxY]);
			if(TerrainInfo[j][tNPlants] > 0){
				for(new x; x<TerrainInfo[j][tNPlants]; x++){
				    new
			 			Float: rX = RandomXY(TerrainInfo[j][tminX], TerrainInfo[j][tmaxX]),
			    		Float: rY = RandomXY(TerrainInfo[j][tminY], TerrainInfo[j][tmaxY]),
			      		Float: rZ;

					GetPointZPos(rX, rY, rZ);
					TerrainInfo[j][tObject][x] = CreateObject(19473, rX, rY, rZ-1, 0, 0, 0, 0);
				}
			}			
			if(TerrainInfo[j][tGrowing] == 1){
                SetTimerEx("GrowUP", 1000, true, "i", j);
            }
		}
	}
	printf("Sono stati caricati %d terreni", TerrainCount);
	mysql_free_result();
	return 1;
}
It doesn't run because of the second loop, if I delete him it run succesfully.
These are the results of crashdetect:

[debug] Run time error 4: "Array index out of bounds"
[debug] Accessing element at index 20 past array upper bound 19
[debug] AMX backtrace:
[debug] #0 0000b350 in ?? () from farmer.amx
[debug] #1 000069c4 in public zcmd_OnGameModeInit () from farmer.amx
[debug] #2 native CallLocalFunction () from samp-server.exe
[debug] #3 00006110 in public SSCANF_OnGameModeInit () from farmer.amx
[debug] #4 native CallLocalFunction () from samp-server.exe
[debug] #5 000003ec in public OnGameModeInit () from farmer.amx
Reply
#2

Why do you want to run 2 loops inside of each other?
Reply
#3

Let's start by saying that this
pawn Code:
for(new j; j<MAX_TERRAINS; j++){
        format(Query, sizeof(Query), "SELECT * FROM Terrain WHERE ID = '%d'", j);
is a horrible way to load data. You should send one query (select * from terrain) and then use a while loop to progress through the resultset.
pawn Code:
mysql_store_result(); // once
while(mysql_fetch_row_format(Query, "|"))
{
    // sscanf
    /*
        blah blah other stuff
    */

}
mysql_free_result(); // once
You're also not properly freeing the result which may be the cause of the errors. It should be (in your inefficient code) inside the terrain loop.

I recommend upgrading to the latest version of the MySQL plugin. Besides the fact that it performs a lot better, it is also a lot cleaner and a lot easier to use once you're used to it. You don't have to explicitly store and free results and whatnot.
Reply
#4

Quote:
Originally Posted by Vince
View Post
Let's start by saying that this
pawn Code:
for(new j; j<MAX_TERRAINS; j++){
        format(Query, sizeof(Query), "SELECT * FROM Terrain WHERE ID = '%d'", j);
is a horrible way to load data. You should send one query (select * from terrain) and then use a while loop to progress through the resultset.
pawn Code:
mysql_store_result(); // once
while(mysql_fetch_row_format(Query, "|"))
{
    // sscanf
    /*
        blah blah other stuff
    */

}
mysql_free_result(); // once
You're also not properly freeing the result which may be the cause of the errors. It should be (in your inefficient code) inside the terrain loop.

I recommend upgrading to the latest version of the MySQL plugin. Besides the fact that it performs a lot better, it is also a lot cleaner and a lot easier to use once you're used to it. You don't have to explicitly store and free results and whatnot.
Thank you very much for the nice tips now I changed my code how you said but I still have the problem with the second loop could you help me?

Code:
function LoadTerrain()
{
	new lString[128], j;
	mysql_query("SELECT * FROM Terrain");
	mysql_store_result();
	while(mysql_fetch_row_format(Query, "|")){
		if(mysql_num_rows() != 0){
			sscanf(Query, "p<|>e<ds[24]ddfffffffddddf>", TerrainInfo[j]);
			TerrainCount++;

			if(TerrainInfo[j][tStatus] == true)	{
			    format(lString, 128, "Lotto{FFFFFF} N: %d", TerrainInfo[j][tID]);
			}
			else{
			    format(lString, 128, "Lotto{FFFFFF} N: %d\nIn vendita", TerrainInfo[j][tID]);
			}
			TerrainInfo[j][tPick] = CreatePickup(1239, 1, TerrainInfo[j][tX], TerrainInfo[j][tY], TerrainInfo[j][tZ], 0);
			TerrainInfo[j][tLabel] = Create3DTextLabel(lString, 0xC4C400FF, TerrainInfo[j][tX], TerrainInfo[j][tY], TerrainInfo[j][tZ]+0.5, 40.0, 0, 0);
			TerrainInfo[j][tZone] = GangZoneCreate(TerrainInfo[j][tminX], TerrainInfo[j][tminY], TerrainInfo[j][tmaxX], TerrainInfo[j][tmaxY]);
			if(TerrainInfo[j][tNPlants] > 0){
				for(new x; x<TerrainInfo[j][tNPlants]; x++){
				    new
			 			Float: rX = RandomXY(TerrainInfo[j][tminX], TerrainInfo[j][tmaxX]),
			    		Float: rY = RandomXY(TerrainInfo[j][tminY], TerrainInfo[j][tmaxY]),
			      		Float: rZ;

					GetPointZPos(rX, rY, rZ);
					TerrainInfo[j][tObject][x] = CreateObject(19473, rX, rY, rZ-1, 0, 0, 0, 0);
				}
			}			
			if(TerrainInfo[j][tGrowing] == 1){
                SetTimerEx("GrowUP", 1000, true, "i", j);
            }
		}
		++j;
	}
	printf("Sono stati caricati %d terreni", TerrainCount);
	mysql_free_result();
	return 1;
}
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)