digitalmars.D.learn - Dynamic array and foreach loop
- Binarydepth (80/80) Aug 08 2015 I'm writing a program that rotates numbers then asks the user if
- Binarydepth (44/44) Aug 08 2015 Here's what happens :
- DarthCthulhu (24/68) Aug 08 2015 This is happening because 'num' is reading the value of each
- Binarydepth (7/23) Aug 08 2015 Thanks that fixed it. I just realized that I'm doing it wrong.
- Binarydepth (3/20) Aug 08 2015 Even better :
- Jay Norwood (9/18) Aug 08 2015 I believe they usually do something like:
- Binarydepth (13/33) Aug 09 2015 So I should use the REF like this ?
- Alex Parrill (5/17) Aug 09 2015 No. `ele` is the array element; reindexing the array with it is
- Jay Norwood (21/33) Aug 09 2015 The reference v is to the array member in this case, rather than
- Binarydepth (14/30) Aug 09 2015 Oooh... I like how this works
- Jay Norwood (12/26) Aug 09 2015 you can also do something like this to accept blank separated
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
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
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 ??? ???:0This 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
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
On Saturday, 8 August 2015 at 18:24:48 UTC, Binarydepth wrote:On Saturday, 8 August 2015 at 17:19:08 UTC, DarthCthulhu wrote:Even better : foreach(num; 0..liaOrig.lengthNow '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
On Saturday, 8 August 2015 at 18:28:25 UTC, Binarydepth wrote: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.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
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: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 } }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.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 09 2015
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
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
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
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