Jump to page: 1 2
Thread overview
Foreach loop behaviour and manipulation
Nov 28, 2013
Binarydepth
Nov 28, 2013
H. S. Teoh
Nov 29, 2013
Binarydepth
Nov 29, 2013
bearophile
Dec 02, 2013
Maxim Fomin
Jan 07, 2014
Binarydepth
Jan 07, 2014
Binarydepth
Jan 07, 2014
H. S. Teoh
Nov 28, 2013
Binarydepth
Dec 02, 2013
Binarydepth
Dec 02, 2013
Binarydepth
November 28, 2013
Hi guys I'm having some problems. Calculations are not working as expected and I get segmentation fault. I used the 2.059 version and it runs after compilation on compileonline.com

But I imagine is either a rookie mistake or a bug, what I'm curious about is the foreach loop.

I'm wondering in the case of manipulating the variable from the foreach loop, Do I have to reset that variable so the loop can work as intended ?(chronologically).

If you don't get what I'm saying check for the comment on the code below.

Code :
------------------------------------------------------------------------
import std.stdio : write, readf;
void main()
{
int a, r, f, temp;
int[102] arr;
write("Digite su año de nacimiento : ");
readf(" %d", &a);
write("\n");
foreach(t; 1..51)
    {
	temp=t;
	t*=20;
	t+=420;
	t*=5;
	t+=3;
    arr[temp-1]=t-a;
	t=temp;
	t*=5;
	t+=50;
	t*=20;
	t+=1013;
    arr[temp]=t-a;
    t=temp;//Do I need this for the foreach loop to work as intended ?
	}
write("BD\tAnonimo\n");
foreach(count; 0..102)
    {
        write(arr[count]);
        if(count%2==0)
        write("\n");
        else
        write(" : ");
    }
}
-------------------------------------------------------------------------------
November 28, 2013
On Fri, Nov 29, 2013 at 12:36:18AM +0100, Binarydepth wrote:
> Hi guys I'm having some problems. Calculations are not working as expected and I get segmentation fault. I used the 2.059 version and it runs after compilation on compileonline.com
[...]
> foreach(t; 1..51)
>     {
> 	temp=t;
> 	t*=20;

Modifying the loop variable of a foreach is, in general, a risky move. If you need to make loop indices jump around, you should use a plain for loop instead:

	for (t=1; t < 51; t++)
	{
		// modify t at will, just make sure your loop
		// condition(s) / loop increments still work correctly.
	}

or, if the loop indices are truly wildly jumping around, use a while loop:

	t = 1;
	while (t < 51 /* or whatever condition you may have */)
	{
		... // Do stuff
		t = ... // compute next index to jump to
	}


T

-- 
The computer is only a tool. Unfortunately, so is the user. -- Armaphine, K5
November 28, 2013
I fixed a formatting problem on the code just now. And also a note is that the numbers are supposed to display a number depending on the initial value of the variable that the foreach loop is increasing and the users age.

So if you were born in 1977 you input your birth year to the program and you'll get :

136:136
236:236
336:336
436:436
536:536
...
1036:1036
1136:1136
1236:1236
...
2036:2036
2136:2136
....
5036:5036
end

------------------------------------------------------------------------
import std.stdio : write, readf;
void main()
{
int a, r, f, temp;
int[102] arr;
write("Digite su año de nacimiento : ");
readf(" %d", &a);
write("\n");
foreach(t; 1..51)
    {
	temp=t;
	t*=20;
	t+=402;
	t*=5;
	t+=3;
    arr[temp-1]=t-a;
	t=temp;
	t*=5;
	t+=50;
	t*=20;
	t+=1013;
    arr[temp]=t-a;
    t=temp;//Do I need this for the foreach loop to work as intended ?
	}
write("BD\tAnonimo\n");
foreach(count; 0..102)
    {
        write(arr[count]);
        if(count%2!=0 && count!=0)
        write("\n");
        else
        write(" : ");
    }
}
-------------------------------------------------------------------------------
November 29, 2013
On Thursday, 28 November 2013 at 23:45:26 UTC, H. S. Teoh wrote:
> On Fri, Nov 29, 2013 at 12:36:18AM +0100, Binarydepth wrote:
>> Hi guys I'm having some problems. Calculations are not working as
>> expected and I get segmentation fault. I used the 2.059 version and
>> it runs after compilation on compileonline.com
> [...]
>> foreach(t; 1..51)
>>     {
>> 	temp=t;
>> 	t*=20;
>
> Modifying the loop variable of a foreach is, in general, a risky move.
> If you need to make loop indices jump around, you should use a plain for
> loop instead:
>
> 	for (t=1; t < 51; t++)
> 	{
> 		// modify t at will, just make sure your loop
> 		// condition(s) / loop increments still work correctly.
> 	}
>
> or, if the loop indices are truly wildly jumping around, use a while
> loop:
>
> 	t = 1;
> 	while (t < 51 /* or whatever condition you may have */)
> 	{
> 		... // Do stuff
> 		t = ... // compute next index to jump to
> 	}
>
>
> T

Thank you for you response! That's exactly what I was thinking.  It can be really chaotic to make that mistake in a for loop. But it can be fixed with a temporary variable and reset the value of the counter at the end of the execution of the loop just before it gets incremented.

Here is the C version of this program. I made a mistake the first time I made this version. I left the function as an INT function and didn't return any value.

On the D version the compiler warned me about that which makes a lot of sense. I liked that! :D .

S I went and fixed both codes but the D compiler is not doing a good compilation and i get segmentation fault when I run the D version.

Finally here's the C code that gives the correct output :
----------------------------------------------------------------------------
#include <stdio.h>
void funcion(int a, int t)
{
int temp, bd, an;
temp=t;
	temp*=20;
	temp+=402;
	temp*=5;
	temp+=3;
bd=temp-a;
temp=t;
	temp*=5;
	temp+=50;
	temp*=20;
	temp+=1013;
an=temp-a;
printf("%d:%d\n", bd, an);
}
void main()
{
int r, f, count, b;
printf("Input your birth year : ");
scanf("%d", &b);
printf("Input the range of sizes for the calculation (# #) : ");
scanf("%d %d", &r, &f);
for(count=r; count<=f; count++)
	{
		funcion(b, count);
	}
}
--------------------------------------------------------------
November 29, 2013
H. S. Teoh:

> Modifying the loop variable of a foreach is, in general, a risky move.

Right. In my opinion D programmers should learn that this is the preferred idiom of using foreach ranged loops:

foreach (immutable i; 0 .. n) {}

If a D programmers really needs to modify the index inside the loop body, then it's better to use a for() loop, that makes it much more explicit and clear what's happening.

Bye,
bearophile
November 29, 2013
On 29/11/13 00:36, Binarydepth wrote:
> I'm wondering in the case of manipulating the variable from the foreach loop, Do
> I have to reset that variable so the loop can work as intended ?(chronologically).

I think that you are approaching this problem in the wrong way.  Instead of using a temporary variable to preserve the loop value, why not keep the loop value constant (immutable, in fact) and use a temporary variable to calculate the values that you wish to write to the array?

Like so:

////////////////////////////////////////////////////////////////////////
import std.stdio : write, readf;
void main()
{
    int a, r, f;
    int[102] arr;
    write("Digite su año de nacimiento : ");
    readf(" %d", &a);
    write("\n");
    foreach (immutable t; 1 .. 51)
    {
        int temp = (((t * 20) + 420) * 5) + 3;
        arr[t - 1] = temp - a;
        temp = (((t * 5) + 50) * 20) + 1013;
        arr[t] = temp - a;
    }
    write("BD\tAnonimo\n");
    foreach(count; 0..102)
    {
        write(arr[count]);
        if(count%2==0)
            write("\n");
        else
            write(" : ");
    }
}
////////////////////////////////////////////////////////////////////////

This gives same results as your existing code but (to me at least) is much simpler and easier to follow.

2nd thing -- do I assume right that you are getting incorrect output and that the later output values shouldn't be all zero?  I think this is because you are incorrectly choosing array indexes to write to, but we should perhaps talk about what your program is _supposed_ to do before addressing that.

Am I also right to assume that you're used to languages where the array index starts from 1 rather than from 0?

Best wishes,

    -- Joe
December 02, 2013
On Friday, 29 November 2013 at 09:15:28 UTC, Joseph Rushton Wakeling wrote:
> On 29/11/13 00:36, Binarydepth wrote:
>> I'm wondering in the case of manipulating the variable from the foreach loop, Do
>> I have to reset that variable so the loop can work as intended ?(chronologically).
>
> I think that you are approaching this problem in the wrong way.
>  Instead of using a temporary variable to preserve the loop value, why not keep the loop value constant (immutable, in fact) and use a temporary variable to calculate the values that you wish to write to the array?
>
> Like so:
>
> ////////////////////////////////////////////////////////////////////////
> import std.stdio : write, readf;
> void main()
> {
>     int a, r, f;
>     int[102] arr;
>     write("Digite su año de nacimiento : ");
>     readf(" %d", &a);
>     write("\n");
>     foreach (immutable t; 1 .. 51)
>     {
>         int temp = (((t * 20) + 420) * 5) + 3;
>         arr[t - 1] = temp - a;
>         temp = (((t * 5) + 50) * 20) + 1013;
>         arr[t] = temp - a;
>     }
>     write("BD\tAnonimo\n");
>     foreach(count; 0..102)
>     {
>         write(arr[count]);
>         if(count%2==0)
>             write("\n");
>         else
>             write(" : ");
>     }
> }
> ////////////////////////////////////////////////////////////////////////
>
> This gives same results as your existing code but (to me at least) is much simpler and easier to follow.
>
> 2nd thing -- do I assume right that you are getting incorrect output and that the later output values shouldn't be all zero?  I think this is because you are incorrectly choosing array indexes to write to, but we should perhaps talk about what your program is _supposed_ to do before addressing that.
>
> Am I also right to assume that you're used to languages where the array index starts from 1 rather than from 0?
>
> Best wishes,
>
>     -- Joe

Completely agree with you. That's actually what I ended up doing. :)
December 02, 2013
>     foreach (immutable t; 1 .. 51)
>     {
>         int temp = (((t * 20) + 420) * 5) + 3;
>         arr[t - 1] = temp - a;
>         temp = (((t * 5) + 50) * 20) + 1013;
>         arr[t] = temp - a;
>     }

Good work with the parenthesis. :)
December 02, 2013
On Friday, 29 November 2013 at 00:41:16 UTC, bearophile wrote:
> H. S. Teoh:
>
>> Modifying the loop variable of a foreach is, in general, a risky move.
>
> Right. In my opinion D programmers should learn that this is the preferred idiom of using foreach ranged loops:
>
> foreach (immutable i; 0 .. n) {}
>
> Bye,
> bearophile

Unfortunately if you iterate over delegates, this may break immutability.

See http://forum.dlang.org/thread/felqszcrbvtrepjtfpul@forum.dlang.org?page=1
January 07, 2014
On Thursday, 28 November 2013 at 23:45:26 UTC, H. S. Teoh wrote:
> On Fri, Nov 29, 2013 at 12:36:18AM +0100, Binarydepth wrote:
>> Hi guys I'm having some problems. Calculations are not working as
>> expected and I get segmentation fault. I used the 2.059 version and
>> it runs after compilation on compileonline.com
> [...]
>> foreach(t; 1..51)
>>     {
>> 	temp=t;
>> 	t*=20;
>
> Modifying the loop variable of a foreach is, in general, a risky move.
> If you need to make loop indices jump around, you should use a plain for
> loop instead:
>
> 	for (t=1; t < 51; t++)
> 	{
> 		// modify t at will, just make sure your loop
> 		// condition(s) / loop increments still work correctly.
> 	}
>
> or, if the loop indices are truly wildly jumping around, use a while
> loop:
>
> 	t = 1;
> 	while (t < 51 /* or whatever condition you may have */)
> 	{
> 		... // Do stuff
> 		t = ... // compute next index to jump to
> 	}
>
>
> T

This excersice is an example :

"Escriba un programa que determine los números (de cantidad de cifras par) divisores de 11
aplicando el siguiente concepto: cuando la suma de los dígitos alternos del número son iguales,
ese número es exactamente divisible por once. Por ejemplo 5841: 5 + 4 = 8 + 1, por lo tanto
el número 5841 es divisible por once."

The important part is "los números (de cantidad de cifras par)" The number of pair digits 10 to 99,  1000 to 9999, 100000 to 999999, etc...

I immediately thought of this thread. Surely you can use a series of if inside the loop that will make it jump the undesired numbers.

or ... for(count=1;count>0 && count<100 || count>999 && count<10000 || etc...; count++ )
« First   ‹ Prev
1 2