www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Dynamic array and foreach loop

reply "Binarydepth" <binarydepth gmail.com> writes:
I'm writing a program that rotates numbers then asks the user if 
a new set of numbers should be rotated. I'm having trouble using 
a Foreach loop to fill a dynamic array with the elements to be 
rotated.

Here's my code, I add a TAB when a loop is inside a loop and and 
do that too to the statements inside and to IF's also.

import std.stdio;

/*Input : Quantity of elements, elements y positions to be 
rotated*/
/*Output : Elements rotated as requested*/
void main()        {
int liEle, liCount, liRot, liAcc;
int[] liaOrig, liaFinal;
immutable kArr=50;
/*Variables : Quantity of elements to be used, Counter variable 
for loops,
Array for original sequence, Array for final sequence, Variable 
for positions to rotate and
Action counter variable.

*/
char lcRot;//Variable for options

do	{//Complete program. Also runs when an other sequence is to be 
used

         do	{//Validation loop for the array. Must be positive


		 write ("How many elements need to be used? ");
		 readf(" %d", &liEle);
		        if(liEle<2)
			        write("Must be a number greater than 1\n");
	}while(liEle<2 || liEle>kArr);
	liaOrig.length = liEle;
	liaFinal.length = liEle;
	foreach(num; liaOrig[0..$])	{//Data input loop

		write("Input the element : ", num+1, " ");
		readf(" %d", &liaOrig[num]);
	}

	do	{
	        do	{
		        write("How many positions do you wish to rotate ? ");
		        readf(" %d", &liRot);
		        if(liRot<1)
		        	write("Input a positive number\n");
         	}while(liRot<1);//Keep asking if a negatice number


			liRot%=liEle;// Reduce rotations for minimal executino

		for(liCount=liEle-1, liAcc=liRot-1; liAcc>=0; liCount--, 
liAcc--)	{//Revrse loop for rotation
			liaFinal[liAcc]=liaOrig[liCount];
		}
		for(liCount=0; liRot<liEle; liCount++, liRot++) 
{//Complementary loop for missed elements
			liaFinal[liRot]=liaOrig[liCount];
		}
		write("The original patter is : ");//Output the original 
sequence
		for(liCount=0; liCount<liEle; liCount++)	{
			write(liaOrig[liCount], " ");
		}
		write("\n");//New line for next loop output
		write("The final is : ");//Final sequence output
		for(liCount=0; liCount<liEle; liCount++)	{//loop for Final 
sequence output
			write(liaFinal[liCount], " ");
		}
		write("\nDo you want to rotate again ? y/n ");//Option to 
rotate again
		readf(" %c", &lcRot);
		if(lcRot == 'y' || lcRot == 'Y')	{
			for(liCount=0; liCount<liEle; liCount++)//Keep the Final 
sequence
				liaOrig[liCount]=liaFinal[liCount];
		}
		else	{
			write("Do you want to make an adicional  sequence ? a/A 
");//Option to make a new sequence
			readf(" %c", &lcRot);
		}
	        }while(lcRot == 'y' || lcRot == 'Y');
}while(lcRot == 'A' || lcRot == 'a');//Loop for restarting the 
program
write("End of program\n");//Nothing else to do
}
Aug 08 2015
parent reply "Binarydepth" <binarydepth gmail.com> writes:
Here's what happens :

How many elements need to be used? 5
Input the element : 1 1
Input the element : 1 2
Input the element : 1 3
Input the element : 1 4
Input the element : 1 5
How many positions do you wish to rotate ? 3
The original patter is : 5 0 0 0 0
The final is : 0 0 0 5 0
Do you want to rotate again ? y/n y
How many positions do you wish to rotate ? 2
The original patter is : 0 0 0 5 0
The final is : 5 0 0 0 0
Do you want to rotate again ? y/n n
Do you want to make an adicional  sequence ? a/A a
How many elements need to be used? 4
Input the element : 1 1
Input the element : 1 2
Input the element : 1 3
core.exception.RangeError gen014.d(31): Range violation
----------------
0x4077ef _Dmain
	???:0
0x41684e void rt.dmain2._d_run_main(int, char**, extern (C) int 
function(char[][])*).runAll().void __lambda1()
	../../../../src/libphobos/libdruntime/rt/dmain2.d:408
0x416abe void rt.dmain2._d_run_main(int, char**, extern (C) int 
function(char[][])*).tryExec(scope void delegate())
	../../../../src/libphobos/libdruntime/rt/dmain2.d:383
0x416d18 void rt.dmain2._d_run_main(int, char**, extern (C) int 
function(char[][])*).runAll()
	../../../../src/libphobos/libdruntime/rt/dmain2.d:408
0x416abe void rt.dmain2._d_run_main(int, char**, extern (C) int 
function(char[][])*).tryExec(scope void delegate())
	../../../../src/libphobos/libdruntime/rt/dmain2.d:383
0x416c45 _d_run_main
	../../../../src/libphobos/libdruntime/rt/dmain2.d:416
0x7f8c84eeda3f __libc_start_main
	???:0
0x406058 _start
	???:0
0xffffffffffffffff ???
	???:0
Aug 08 2015
parent reply "DarthCthulhu" <spam spam.com> writes:
On Saturday, 8 August 2015 at 15:57:15 UTC, Binarydepth wrote:
 Here's what happens :

 How many elements need to be used? 5
 Input the element : 1 1
 Input the element : 1 2
 Input the element : 1 3
 Input the element : 1 4
 Input the element : 1 5
 How many positions do you wish to rotate ? 3
 The original patter is : 5 0 0 0 0
 The final is : 0 0 0 5 0
 Do you want to rotate again ? y/n y
 How many positions do you wish to rotate ? 2
 The original patter is : 0 0 0 5 0
 The final is : 5 0 0 0 0
 Do you want to rotate again ? y/n n
 Do you want to make an adicional  sequence ? a/A a
 How many elements need to be used? 4
 Input the element : 1 1
 Input the element : 1 2
 Input the element : 1 3
 core.exception.RangeError gen014.d(31): Range violation
 ----------------
 0x4077ef _Dmain
 	???:0
 0x41684e void rt.dmain2._d_run_main(int, char**, extern (C) int 
 function(char[][])*).runAll().void __lambda1()
 	../../../../src/libphobos/libdruntime/rt/dmain2.d:408
 0x416abe void rt.dmain2._d_run_main(int, char**, extern (C) int 
 function(char[][])*).tryExec(scope void delegate())
 	../../../../src/libphobos/libdruntime/rt/dmain2.d:383
 0x416d18 void rt.dmain2._d_run_main(int, char**, extern (C) int 
 function(char[][])*).runAll()
 	../../../../src/libphobos/libdruntime/rt/dmain2.d:408
 0x416abe void rt.dmain2._d_run_main(int, char**, extern (C) int 
 function(char[][])*).tryExec(scope void delegate())
 	../../../../src/libphobos/libdruntime/rt/dmain2.d:383
 0x416c45 _d_run_main
 	../../../../src/libphobos/libdruntime/rt/dmain2.d:416
 0x7f8c84eeda3f __libc_start_main
 	???:0
 0x406058 _start
 	???:0
 0xffffffffffffffff ???
 	???:0
This is happening because 'num' is reading the value of each element in the array; it's not a count. Once it reads the 5 in element, it attempts to put the next number into element 5, which of course doesn't exist. This is also why the first time through there is only one value in the array that isn't 0: 'num' the first time through is always zero because the values of the dynamic array are .init-ed to zero. You can fix it like the following: foreach(num, element; liaOrig) {//Data input loop writefln("num: %s current element: %s liaOrig.length: %s", num, element, liaOrig.length); write("Input the element : ", num+1, " "); readf(" %d", &liaOrig[num]); } Now 'num' is just an iterative number starting from 0 (the .init value of an int), while the actual element value is stored in 'element'. I added the writefln() statement to make it a bit more clear during runtime. As an addenum, you don't need the liaOrig[0 .. $] in the foreach statement; just the name of the array variable is required to walk the entire array. Hope this helps!
Aug 08 2015
parent reply "Binarydepth" <binarydepth gmail.com> writes:
On Saturday, 8 August 2015 at 17:19:08 UTC, DarthCthulhu wrote:
 You can fix it like the following:

 foreach(num, element; liaOrig)	{//Data input loop
 		
 			writefln("num: %s current element: %s liaOrig.length: %s", 
 num, element, liaOrig.length);

 			write("Input the element : ", num+1, " ");
 			readf(" %d", &liaOrig[num]);
 		}

 Now 'num' is just an iterative number starting from 0 (the 
 .init value of an int), while the actual element value is  
 stored in 'element'. I added the writefln() statement to make 
 it a bit more clear during runtime.

 As an addenum, you don't need the liaOrig[0 .. $] in the 
 foreach statement; just the name of the array variable is 
 required to walk the entire array.

 Hope this helps!
Thanks that fixed it. I just realized that I'm doing it wrong. This is the new code : foreach(num; 0..liEle) {//Data input loop write("Input the element : ", num+1, " "); readf(" %d", &liaOrig[num]); }
Aug 08 2015
parent reply "Binarydepth" <binarydepth gmail.com> writes:
On Saturday, 8 August 2015 at 18:24:48 UTC, Binarydepth wrote:
 On Saturday, 8 August 2015 at 17:19:08 UTC, DarthCthulhu wrote:
 Now 'num' is just an iterative number starting from 0 (the 
 .init value of an int), while the actual element value is  
 stored in 'element'. I added the writefln() statement to make 
 it a bit more clear during runtime.

 As an addenum, you don't need the liaOrig[0 .. $] in the 
 foreach statement; just the name of the array variable is 
 required to walk the entire array.

 Hope this helps!
Thanks that fixed it. I just realized that I'm doing it wrong. This is the new code : foreach(num; 0..liEle) {//Data input loop write("Input the element : ", num+1, " "); readf(" %d", &liaOrig[num]); }
Even better : foreach(num; 0..liaOrig.length
Aug 08 2015
parent reply "Jay Norwood" <jayn prismnet.com> writes:
On Saturday, 8 August 2015 at 18:28:25 UTC, Binarydepth wrote:
 This is the new code :

 	foreach(num; 0..liEle)	{//Data input loop

 		write("Input the element : ", num+1, " ");
 		readf(" %d", &liaOrig[num]);
 	}
Even better : foreach(num; 0..liaOrig.length
I believe they usually do something like: foreach( num, ref elem; liaOrig){ } which creates the index num and the reference to the element of range liaOrig. It also seems that a lot of discussion is going on about reducing use of foreach loops in their preferred style, so you might want to try some of that.
Aug 08 2015
parent reply "Binarydepth" <binarydepth gmail.com> writes:
On Sunday, 9 August 2015 at 00:22:53 UTC, Jay Norwood wrote:
 On Saturday, 8 August 2015 at 18:28:25 UTC, Binarydepth wrote:
 This is the new code :

 	foreach(num; 0..liEle)	{//Data input loop

 		write("Input the element : ", num+1, " ");
 		readf(" %d", &liaOrig[num]);
 	}
Even better : foreach(num; 0..liaOrig.length
I believe they usually do something like: foreach( num, ref elem; liaOrig){ } which creates the index num and the reference to the element of range liaOrig. It also seems that a lot of discussion is going on about reducing use of foreach loops in their preferred style, so you might want to try some of that.
So I should use the REF like this ? import std.stdio : writeln; void main() { immutable a=5; int[a] Arr; foreach(num; 0..a) { Arr[num] = num; } foreach(num, ref ele; Arr) { writeln(Arr[ele]+1);//Using the REF } }
Aug 09 2015
next sibling parent "Alex Parrill" <initrd.gz gmail.com> writes:
On Sunday, 9 August 2015 at 15:37:23 UTC, Binarydepth wrote:
 So I should use the REF like this ?

 import std.stdio : writeln;
 void main()     {
         immutable a=5;
         int[a] Arr;
         foreach(num; 0..a)      {
                 Arr[num] = num;
         }
         foreach(num, ref ele; Arr)      {
                 writeln(Arr[ele]+1);//Using the REF
         }
 }
No. `ele` is the array element; reindexing the array with it is incorrect. `ref` just means that you can assign back to the array (like `ele = 123; assert(Arr[num] == 123);`); it's unnecessary here though.
Aug 09 2015
prev sibling parent reply "Jay Norwood" <jayn prismnet.com> writes:
On Sunday, 9 August 2015 at 15:37:23 UTC, Binarydepth wrote:
 So I should use the REF like this ?

 import std.stdio : writeln;
 void main()     {
         immutable a=5;
         int[a] Arr;
         foreach(num; 0..a)      {
                 Arr[num] = num;
         }
         foreach(num, ref ele; Arr)      {
                 writeln(Arr[ele]+1);//Using the REF
         }
 }
The reference v is to the array member in this case, rather than making a copy. In the last loop c is a copy. No big deal for this case of int Arr members, but if Arr was made up of struct members, you might not want to be making copies. The i+3 initialization is just so you can see that v is the Arr member (not the index) in the other loops. import std.stdio : writeln; void main() { immutable a=5; int[a] Arr; foreach(i, ref v; Arr) { v = i+3; } foreach( ref v; Arr) { writeln(v); } foreach( c; Arr) { writeln(c); } }
Aug 09 2015
parent reply "Binarydepth" <binarydepth gmail.com> writes:
On Sunday, 9 August 2015 at 16:42:16 UTC, Jay Norwood wrote:
 The i+3 initialization is just so you can see that v is the Arr 
 member (not the index) in the other loops.

 import std.stdio : writeln;
 void main()     {
 	immutable a=5;
 	int[a] Arr;
 	foreach(i, ref v; Arr)      {
 		v = i+3;
 	}
 	foreach( ref v; Arr)      {
 		writeln(v);
 	}
 	foreach( c; Arr)      {
 		writeln(c);
 	}
 }
Oooh... I like how this works import std.stdio : writeln, readf; void main() { immutable a=5; int[a] Arr; int nim; foreach(num, ref nem; Arr) { readf(" %s", &nem); } foreach(num; Arr) { writeln(num); } }
Aug 09 2015
parent "Jay Norwood" <jayn prismnet.com> writes:
On Sunday, 9 August 2015 at 19:10:01 UTC, Binarydepth wrote:
 On Sunday, 9 August 2015 at 16:42:16 UTC, Jay Norwood wrote:
 Oooh... I like how this works

 import std.stdio : writeln, readf;
 void main()     {
         immutable a=5;
         int[a] Arr;
         int nim;
         foreach(num, ref nem; Arr)      {
                 readf(" %s", &nem);
         }
         foreach(num; Arr)      {
                 writeln(num);
         }
 }
you can also do something like this to accept blank separated input values on a single line. import std.stdio : writeln, readln; import std.string: split; import std.conv: to; import std.algorithm: each; void main() { double [] Arr; Arr = readln().split().to!(double[]); Arr.each!writeln(); }
Aug 09 2015