www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - foreach(ubyte j;0 .. num) is bugging out

reply Ruby The Roobster <michaeleverestc79 gmail.com> writes:
So, I have the following function:
```d
	public Sprite ReadSpriteFromFile(immutable(char)[] filename)	{ 
//Reads a sprite in my made up .spr format(trash, why does this 
even exist)
		ubyte[] ftext;
		Color[] colors;
		Point[][] points;
		import std.file;
		import std.stdio;
		ftext = cast(ubyte[])read(filename);
		foreach(i;0 .. cast(uint)ftext.length)	{ //Parse the file...
			long main;
			short exp;
			uint x = 0;
			++colors.length;
			++points.length;
			colors[x].r = ftext[i]; //Set r color...
			++i;
			colors[x].g = ftext[i];
			++i;
			colors[x].b = ftext[i];
			++i;
		ubyte tempcolor = ftext[i];
		++i;
		long temp;
	        writeln(tempcolor); //For this matter, the program 
correctly reports tempcolor as 1...
		for(ubyte j = 0;j < tempcolor; j++ /*trying ++j has same 
effect*/ )	{ //tempcolor is 1, yet this sloop gets executed 
twice...
			writeln();
			posfunc(ftext, main, exp, temp, i, j, points , x);             
                            //Orignally foreach loop, but 
switching to for loop has same effect...
		}
	}
	return Sprite(colors, points);
}
```

Here is the rest of the source:

```d
/*sprite.d by Ruby The Roobster*/
/*Version 0.3.5 Release*/
/*Last Update: 08/23/2021*/
/*Module for sprites in the D Programming Language 2.0*/
module dutils.sprite;
import skeleton : Point;

version(USE_BUILT_IN_SPRITES)	{ //Use built in sprites(garbage 
.spr format coded by me, that still needs an editor: Editor using 
GtKD for .spr comes out later this year, if I can get myself to 
do it)...
	public struct Color	{
		ubyte r = 0;
		ubyte g = 0;
		ubyte b = 0;
		void opAssign(Color rhs)	{
			this.r = rhs.r;
			this.g = rhs.g;
			this.b = rhs.b;
		}
	}

	public struct Sprite	{
		Color[] colors;
		Point[][] points;
		invariant()	{
			assert(colors.length == points.length, "Assertion failure: 
Sprite.colors.length and Sprite.points.length must always be 
equal...");
		}
		void opAssign(Sprite rhs)	{
			this.colors.length = rhs.colors.length;
			this.points.length = rhs.points.length;
			foreach(i;0 .. this.colors.length)	{
				this.colors[i] = rhs.colors[i];
			}
			foreach(i;0 .. this.points.length)	{
				this.points[i].length = rhs.points[i].length;
				foreach(j;0 .. this.points[i].length)	{
					this.points[i][j] = rhs.points[i][j];
				}
			}
		}
		package void ChangeLengths(uint c)	{ //Change both lengths so 
invariant doesn't get triggered...
			this.colors.length = c;
			this.points.length = c;
		}
	}

//ReadSpriteFromFile was here...
	
	package void posfunc(const ubyte[] ftext, ref long main, ref 
short exp, ref long temp, ref uint i, const ubyte j, ref 
Point[][] points, ref uint x)	{
		++points[x].length;
		import std.stdio;
		writeln(__LINE__);
		foreach(z;0 .. 3)	{
			short shift = 56;
			main = ftext[i];
			main <<= shift;
			++i;
			shift -= 8;
			while(shift >= 0)	{
				writeln(shift);
				writeln(i);
				temp = ftext[i];
				main = (main <= (-0)) ? (main - temp) : (main + temp);
				++i;
				shift -= 8;
			}
			exp = ftext[i];
			exp <<= 8;
			++i;
			exp += ftext[i];
			if(i+1 == ftext.length)	{
			}
			else	{
			++i;
			}
			switch(z)	{
				case 0:
					points[x][j].x = (main * 10^^exp);
					break;
				case 1:
					points[x][j].y = (main * 10^^exp);
					break;
				case 2:
					points[x][j].z = (main * 10^^exp);
					break;
				default:
					assert(false); //bruh...
			}
		}
	}
}

version(USE_OTHER_SPRITE)	{ //If the user wants to work with 
sprites their own way...
	public alias Sprite = uint function();
}

version(USE_FILE_SPRITE)	{  //If the user wants to read the 
sprites from a file and do it that way...
	public alias Sprite = wchar[];
}
```
skeleton.d source:

```d
/*skeleton.d by Ruby The Roobster*/
/*Version 1.0 Release*/
/*Module for representing skeletons in the D Programming Language 
2.0*/

public struct Point	{ //Point structure...
	real x;
	real y;
	real z;
	void opAssign(Point rhs)	{
		this.x = rhs.x;
		this.y = rhs.y;
		this.z = rhs.z;
	}
	void opOpAssign(string op)(Point rhs)	{
		mixin("this.x " ~ op ~ "= rhs.x;");
		mixin("this.y " ~ op ~ "= rhs.y;");
		mixin("this.z " ~ op ~ "= rhs.z;");
	}
}

public struct Face	{ //Face(of a 3D shape) structure...
	Line[] lines;
	Point center;
	void opAssign(Face rhs)	{
		this.lines.length = rhs.lines.length;
		foreach(i;0 .. this.lines.length)	{
			this.lines[i] = rhs.lines[i];
		}
	}
}

public struct Skeleton	{ //Skeleton of a 3D structure...
	Face[] faces;
	Point center;
	void opAssign(Skeleton rhs)	{
		this.faces.length = rhs.faces.length;
		foreach(i;0 .. this.faces.length)	{
			this.faces[i] = rhs.faces[i];
		}
		this.center = rhs.center;
	}
}


public struct Line	{ //Line struct...
	Point[] mid_points;
	Point start;
	Point stop;
	void opAssign(Line rhs)	{
		this.start = rhs.start;
		this.stop = rhs.stop;
		this.mid_points.length = rhs.mid_points.length;
		foreach(i;0 .. this.mid_points.length)	{
			this.mid_points[i] = rhs.mid_points[i];
		}
	}
}
```

Here is my test program for these:

```d
//This file is called nid.d
import dutils.sprite;
import std.stdio;
void main()	{
	Sprite sprite = ReadSpriteFromFile("abc.txt");
	writeln(sprite);
}
```

abc.txt in hexadecimal:

00 00 00 01 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 
00 01 00 00 00 00 00 00 00 00 00 01

Compiler Version: DMD 2.097.2

Command line: dmd nid.d sprite.d skeleton.d 
-version=USE_BUILT_IN_SPRITES

Sorry for this being long, but whole source files were provided 
for clarity.  Why the heck is the loop being executed twice(check 
output for blank lines).

Also, if this is somehow relevant, I am on Windows 10 20H1 build 
19043.1237.
Sep 22 2021
parent reply jfondren <julian.fondren gmail.com> writes:
On Thursday, 23 September 2021 at 00:06:42 UTC, Ruby The Roobster 
wrote:
 So, I have the following function:
 ```d
 	        writeln(tempcolor); //For this matter, the program 
 correctly reports tempcolor as 1...
 		for(ubyte j = 0;j < tempcolor; j++ /*trying ++j has same 
 effect*/ )	{ //tempcolor is 1, yet this sloop gets executed 
 twice...
 			writeln();
 			posfunc(ftext, main, exp, temp, i, j, points , x);           
                              //Orignally foreach loop, but 
 switching to for loop has same effect...
 		}
 ```
Needs more print in your print debugging: ```d writeln("tempcolor: ", tempcolor); ... writeln("in tempcolor with j: ", j); ``` output: ``` tempcolor: 1 in tempcolor with j: 0 ... ... numbers ... tempcolor: 0 tempcolor: 0 tempcolor: 0 tempcolor: 0 tempcolor: 0 tempcolor: 0 tempcolor: 0 tempcolor: 0 tempcolor: 0 tempcolor: 1 in tempcolor with j: 0 ... ... numbers ... ``` Here's a oneliner to reproduce to abc.txt: ``` rdmd --eval '"00 00 00 01 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 01 00 00 00 00 00 00 00 00 00 01".split(" ").map!(s => cast(char) s.to!ubyte).write' > abc.txt ```
Sep 22 2021
parent reply Ruby The Roobster <michaeleverestc79 gmail.com> writes:
On Thursday, 23 September 2021 at 00:17:49 UTC, jfondren wrote:
 On Thursday, 23 September 2021 at 00:06:42 UTC, Ruby The 
 Roobster wrote:
 So, I have the following function:
 ```d
 	        writeln(tempcolor); //For this matter, the program 
 correctly reports tempcolor as 1...
 		for(ubyte j = 0;j < tempcolor; j++ /*trying ++j has same 
 effect*/ )	{ //tempcolor is 1, yet this sloop gets executed 
 twice...
 			writeln();
 			posfunc(ftext, main, exp, temp, i, j, points , x);          
                               //Orignally foreach loop, but 
 switching to for loop has same effect...
 		}
 ```
Needs more print in your print debugging: ```d writeln("tempcolor: ", tempcolor); ... writeln("in tempcolor with j: ", j); ``` output: ``` tempcolor: 1 in tempcolor with j: 0 ... ... numbers ... tempcolor: 0 tempcolor: 0 tempcolor: 0 tempcolor: 0 tempcolor: 0 tempcolor: 0 tempcolor: 0 tempcolor: 0 tempcolor: 0 tempcolor: 1 in tempcolor with j: 0 ```
I figured out something weird. The variable 'i' is passed by reference, yet the variable 'i' of the loop isn't being incremented by posfunc. I assume foreach creates a new i variable at the start of each new loop. Swapping the original loop with a while loop fixes the problem. Thank you very much for trying to help.
Sep 22 2021
parent jfondren <julian.fondren gmail.com> writes:
On Thursday, 23 September 2021 at 00:30:45 UTC, Ruby The Roobster 
wrote:
 I figured out something weird. The variable 'i' is passed by 
 reference, yet the variable 'i' of the loop isn't being 
 incremented by posfunc.  I assume foreach creates a new i 
 variable at the start of each new loop.
Yep: ``` $ rdmd --eval 'foreach (i; 0 .. 5) { writeln(i); i++; }' 0 1 2 3 4 ```
Sep 22 2021