How not to abuse a "for loop": examples?

T

Toby Newman

At the page:
http://www.strath.ac.uk/IT/Docs/Ccourse/subsection3_8_3.html#SECTION0008300000000000000
or
http://tinyurl.com/4ptzs

the author warns:
"The for loop is frequently used, usually where the loop will be
traversed a fixed number of times. It is very flexible, and novice
programmers should take care not to abuse the power it offers."

Could someone give an example of this abuse? I'm googling for
c misuse "for loop"
c abuse "for loop"
with little luck.

I'd like to see what *not* to do :)

Toby
 
T

Tak-Shing Thomas Chan

the author warns:
"The for loop is frequently used, usually where the loop will be
traversed a fixed number of times. It is very flexible, and novice
programmers should take care not to abuse the power it offers."

Could someone give an example of this abuse? I'm googling for
c misuse "for loop"
c abuse "for loop"
with little luck.

I'd like to see what *not* to do :)

for (a(), b(), c(), d(), e(), f(), g();
h(), i(), j(), k(), l(), m(), n(), o(), p();
q(), r(), s(), t(), u(), v(), w(), x(), y(), z())
;

Tak-Shing
 
P

Peter Nilsson

Toby Newman said:
"The for loop is frequently used, usually where the loop will be
traversed a fixed number of times. It is very flexible, and novice
programmers should take care not to abuse the power it offers."

Could someone give an example of this abuse? I'm googling for
c misuse "for loop"
c abuse "for loop"
with little luck.

I'd like to see what *not* to do :)

for (i = 0; i < 100; i += (i == 98) ? -97 : 2)

for (; *++argv
&& (fp = fopen(*argv, "rb"))
&& fread(buffer, 10, 10, fp) == 10
&& fclose(fp) != EOF; )

Although, I'm guilty of both. ;)
 
T

Thomas Matthews

Toby said:
At the page:
http://www.strath.ac.uk/IT/Docs/Ccourse/subsection3_8_3.html#SECTION0008300000000000000
or
http://tinyurl.com/4ptzs

the author warns:
"The for loop is frequently used, usually where the loop will be
traversed a fixed number of times. It is very flexible, and novice
programmers should take care not to abuse the power it offers."

Could someone give an example of this abuse? I'm googling for
c misuse "for loop"
c abuse "for loop"
with little luck.

I'd like to see what *not* to do :)

Toby

for (i = 0; i < 100; ++i)
{
--i;
}

float j;
for (j = 0.0; j != 10.0; j += 0.1)
{
}

unsigned int m;
for (m = 9; m > 0; m -= 2)
{
}

--
Thomas Matthews

C++ newsgroup welcome message:
http://www.slack.net/~shiva/welcome.txt
C++ Faq: http://www.parashift.com/c++-faq-lite
C Faq: http://www.eskimo.com/~scs/c-faq/top.html
alt.comp.lang.learn.c-c++ faq:
http://www.comeaucomputing.com/learn/faq/
Other sites:
http://www.josuttis.com -- C++ STL Library book
 
D

Does It Matter

At the page:
http://www.strath.ac.uk/IT/Docs/Ccourse/subsection3_8_3.html#SECTION0008300000000000000
or
http://tinyurl.com/4ptzs

the author warns:
"The for loop is frequently used, usually where the loop will be
traversed a fixed number of times. It is very flexible, and novice
programmers should take care not to abuse the power it offers."

Could someone give an example of this abuse? I'm googling for
c misuse "for loop"
c abuse "for loop"
with little luck.

I'd like to see what *not* to do :)

There is nothing you can do with the for loop that you cannot do with the
while loop. For some bizzare reason, people tend to abuse the comma
operator in a for loop but not in a while loop. The for loop has three
sections:

for(init; check; incr)

The init section is where you initialize variables used in the for loop. A
little abuse happens here. People initialize a number of variables here
when they could have been initialized before the loop. I like to do this
if the variables are relative to the loop. If I initialize them at the top
of scope the initialization might not be visible while I step through the
for loop.

The big abuse is in the check section. Here you should be checking to see
if the for loop should exit of not. Some times programmers will stick a
number of statements that could just as easily fit in the body of the loop
into this section. This often makes for a hard to read bit of code.

Another place for abuse is the incr section. This is the section that you
should be incrementing something. If you use a for loop for stepping
through a known number of iterations then this section should just be
incrementing the counter used to keep track of the iterations.

There are no hard and fast rules on this. I often see:

while((c = getchar()) != EOF) {
/* code */
}

getting converted to:

for(; (c = getchar()) != EOF; /* code */);

It is all a matter of coding conventions or style.
 
D

Dave Vandervies

At the page:
http://www.strath.ac.uk/IT/Docs/Ccourse/subsection3_8_3.html#SECTION0008300000000000000
or
http://tinyurl.com/4ptzs

the author warns:
"The for loop is frequently used, usually where the loop will be
traversed a fixed number of times. It is very flexible, and novice
programmers should take care not to abuse the power it offers."

Could someone give an example of this abuse? I'm googling for
c misuse "for loop"
c abuse "for loop"
with little luck.

I'd like to see what *not* to do :)

--------
for(in=fopen(filename,"r");in&&fgets(buf,sizeof buf,in);)
{
/*do stuff with this line of the file*/
}
--------
/*i is unsigned*/
for(i=1;i;i*=2)
{
/*do stuff with this power of 2*/
}
/*we fall out when we hit max(i)+1 and the unsigned arithmetic wraps
back around to 0
*/
 
C

Christian Kandeler

Dave said:
A favorite of mine, that falls under "uncommon" but not "abuse", is:
--------
for(curr=head;curr;curr=curr->next)
{
/*Do stuff with this list node*/
}

Is that really so uncommon? It seems like the natural way to traverse a
linked list. (Except that I would explicitly test for curr != NULL, since
curr is not a boolean value. But that's also a matter of taste).


Christian
 
M

Mabden

Christian Kandeler said:
Is that really so uncommon? It seems like the natural way to traverse a
linked list. (Except that I would explicitly test for curr != NULL, since
curr is not a boolean value. But that's also a matter of taste).

curr != NULL or curr != 0?
I'm confused now, after the Null Pointer thread... "Keith!!! Where are
you?!!"
 
P

pete

Mabden said:
curr != NULL or curr != 0?

Since the point of writing curr != NULL or curr != 0
instead of just (;curr;) is to enhance legibility,
I think it makes sense to write curr != NULL
When I read (curr != NULL), that tells me that the author
thought that curr was a pointer, when he wrote the code.
 
R

RoSsIaCrIiLoIA

At the page:
http://www.strath.ac.uk/IT/Docs/Ccourse/subsection3_8_3.html#SECTION0008300000000000000
or
http://tinyurl.com/4ptzs

the author warns:
"The for loop is frequently used, usually where the loop will be
traversed a fixed number of times. It is very flexible, and novice
programmers should take care not to abuse the power it offers."

Could someone give an example of this abuse? I'm googling for
c misuse "for loop"
c abuse "for loop"
with little luck.

I'd like to see what *not* to do :)

Toby

Something like this?

for(i=0; i<1000; ++i)
for(j=0; j<1000; ++j)
for(k=0; k<1000; ++k)
for(ii=0; ii<1000; ++ii)
for(jj=0; jj<1000; ++jj)
for(kk=0; kk<1000; ++kk)
for(z=0; z<1000; ++z)
f(i,j,k,ii, jj, kk, z);
 
T

Toby Newman

# Thomas Matthews
for (i = 0; i < 100; ++i)
{
--i;
}

Gets the program stuck in a loop. I guess you could do the same with
while(1)
{}
float j;
for (j = 0.0; j != 10.0; j += 0.1)
{
}

Keeps the program occupied for a little while. I guess better to time
the pause some other way, more accurately and less dependant upon
processor speed.
unsigned int m;
for (m = 9; m > 0; m -= 2)
{
}

I guess the problem with this one is that m being an unsigned integer
will cause problems when you perform
9 - 2 - 2 - 2 - 2 - 2...
and never get to be lessthan or equal to 0, so the loop goes on forever.
 
B

boa

Toby said:
# James Dow Allen
http://tinyurl.com/2452h/wnim.htm
(scroll about half way down.)

Hope this helps,
James


This bit?

for (numpile = 1; numpile <= plast; numpile++)
for (numrem = 1; numrem <= psize[plast]; numrem++)
if (WINNER)
goto contin_3;

He's nesting them. That's frowned upon?

Did you miss the definition of the NFOR macro? Worry not, here's a copy.

#define NFOR(N) \
for (psize[N] = 0; \
psize[N] <= psize[N-1] \
&& (N > NROW - 2 || N == NROW - 2 && \
(winbits = (unsigned short *)(*grow[N-1]++ \
= calloc(1, WID * sizeof (unsigned short)))) \
|| (grow[N] = (Node *)(*grow[N-1]++ \
= calloc(1, ((unsigned)psize[N]+1) \
* sizeof (Node))))); psize[N]++, plast = N)


And note how it is used:
/*
* After the foregoing preliminaries, a brief nested
* loop suffices to solve every position.
*/
NFOR(1) NFOR(2) NFOR(3) NFOR(4) NFOR(5) NFOR(6)
NFOR(7) NFOR(8) NFOR(9) NFOR(10) NFOR(11) NFOR(12) {
if (plast) {
for (numpile = 1; numpile <= plast; numpile++)
for (numrem = 1; numrem <= psize[plast]; numrem++)
if (WINNER)
goto contin_3;
winbits[INDX(10)] |= 1 << INDX(11);
contin_3: ;
}
}

I tried to preprocess (gcc -E -P) and indent it to be able to post it,
but that wasn't possible with 14 nested for loops and a couple of
if-tests as well. Clearly a winner, IMHO <g>

boa@home
 
T

Toby Newman

# boa
Toby said:
# James Dow Allen
(e-mail address removed) (Toby Newman) wrote in message
"The for loop is ... very flexible, and novice
programmers should take care not to abuse the power it offers."

Could someone give an example of this abuse? ...
I'd like to see what *not* to do :)

http://tinyurl.com/2452h/wnim.htm
(scroll about half way down.)

Hope this helps,
James


This bit?

for (numpile = 1; numpile <= plast; numpile++)
for (numrem = 1; numrem <= psize[plast]; numrem++)
if (WINNER)
goto contin_3;

He's nesting them. That's frowned upon?

Did you miss the definition of the NFOR macro? Worry not, here's a copy.

#define NFOR(N) \
for (psize[N] = 0; \
psize[N] <= psize[N-1] \
&& (N > NROW - 2 || N == NROW - 2 && \
(winbits = (unsigned short *)(*grow[N-1]++ \
= calloc(1, WID * sizeof (unsigned short)))) \
|| (grow[N] = (Node *)(*grow[N-1]++ \
= calloc(1, ((unsigned)psize[N]+1) \
* sizeof (Node))))); psize[N]++, plast = N)


And note how it is used:
/*
* After the foregoing preliminaries, a brief nested
* loop suffices to solve every position.
*/
NFOR(1) NFOR(2) NFOR(3) NFOR(4) NFOR(5) NFOR(6)
NFOR(7) NFOR(8) NFOR(9) NFOR(10) NFOR(11) NFOR(12) {
if (plast) {
for (numpile = 1; numpile <= plast; numpile++)
for (numrem = 1; numrem <= psize[plast]; numrem++)
if (WINNER)
goto contin_3;
winbits[INDX(10)] |= 1 << INDX(11);
contin_3: ;
}
}

I tried to preprocess (gcc -E -P) and indent it to be able to post it,
but that wasn't possible with 14 nested for loops and a couple of
if-tests as well. Clearly a winner, IMHO <g>

boa@home

So, do I understand correctly that the extreme nesting of for loops is
bad behaviour because it makes the code hard to read and hard for pre-
processors to parse?
 
B

boa

Toby said:
# boa
Toby Newman wrote:

# James Dow Allen


(e-mail address removed) (Toby Newman) wrote in message

"The for loop is ... very flexible, and novice
programmers should take care not to abuse the power it offers."

Could someone give an example of this abuse? ...
I'd like to see what *not* to do :)

http://tinyurl.com/2452h/wnim.htm
(scroll about half way down.)

Hope this helps,
James



This bit?

for (numpile = 1; numpile <= plast; numpile++)
for (numrem = 1; numrem <= psize[plast]; numrem++)
if (WINNER)
goto contin_3;

He's nesting them. That's frowned upon?

Did you miss the definition of the NFOR macro? Worry not, here's a copy.

#define NFOR(N) \
for (psize[N] = 0; \
psize[N] <= psize[N-1] \
&& (N > NROW - 2 || N == NROW - 2 && \
(winbits = (unsigned short *)(*grow[N-1]++ \
= calloc(1, WID * sizeof (unsigned short)))) \
|| (grow[N] = (Node *)(*grow[N-1]++ \
= calloc(1, ((unsigned)psize[N]+1) \
* sizeof (Node))))); psize[N]++, plast = N)


And note how it is used:
/*
* After the foregoing preliminaries, a brief nested
* loop suffices to solve every position.
*/
NFOR(1) NFOR(2) NFOR(3) NFOR(4) NFOR(5) NFOR(6)
NFOR(7) NFOR(8) NFOR(9) NFOR(10) NFOR(11) NFOR(12) {
if (plast) {
for (numpile = 1; numpile <= plast; numpile++)
for (numrem = 1; numrem <= psize[plast]; numrem++)
if (WINNER)
goto contin_3;
winbits[INDX(10)] |= 1 << INDX(11);
contin_3: ;
}
}

I tried to preprocess (gcc -E -P) and indent it to be able to post it,
but that wasn't possible with 14 nested for loops and a couple of
if-tests as well. Clearly a winner, IMHO <g>

boa@home


So, do I understand correctly that the extreme nesting of for loops is
bad behaviour because it makes the code hard to read

IMO, yes.
and hard for pre-processors to parse?

That was probably just bad english by me. The preprocessor had no
problems processing the code at all, but the preprocessed code was
unreadable (at least to me).

boa@home
 
D

Dave Vandervies

Is that really so uncommon? It seems like the natural way to traverse a
linked list.

Most linked list traversals I've seen use while instead:
--------
curr=head;
while(curr)
{
/*do stuff*/
curr=curr->next;
}
--------
I suspect that this may be a result of most languages having less general
for loops that are only suitable for counting, so most programmers don't
come up with it on their own. (I don't think I came up with it on my own,
but I have no idea where I first encountered it.)


dave
 
A

Arthur J. O'Dwyer

# Thomas Matthews

Gets the program stuck in a loop. I guess you could do the same with
while(1) {}

Correct. However, I'm not sure if Thomas was also meaning to
refer to the more common but IMHO equally abusive

for (i=0; i < 100; ++i) {
if (foo(i)) {
/* You know what? Let's process this |i| again. */
--i; continue;
}
}

However, just because it's abusive doesn't necessarily mean you
should never do it. ;)
Keeps the program occupied for a little while. I guess better to time
the pause some other way, more accurately and less dependant upon
processor speed.

You missed the point. Google up "comp.lang.c FAQ" and read
Section 14, which is all about floating-point numbers. (In a
nutshell: 'j' may never be equal to 10.0, due to rounding errors
in the addition operations.)
I guess the problem with this one is that m being an unsigned integer
will cause problems when you perform
9 - 2 - 2 - 2 - 2 - 2...
and never get to be lessthan or equal to 0, so the loop goes on forever.

Correct. But note that somebody else already posted abusive but
possibly useful code that looked something like this:

unsigned m;
for (m = 9; m > 0; m -= 2) {
if (m > 9) m = 8;
foo(m);
}

I didn't see any FAQ about unsigned arithmetic, but here's something
just as good:
http://www.eskimo.com/~scs/cclass/int/sx4ca.html

HTH,
-Arthur
 
O

Old Wolf


If that page is meant to be a troll then ignore this, but why didn't
you malloc the whole array in one go? This would have saved
screeds of memory and code complexity (although I suppose if you had
then you would have been unable to contribute to this thread).
Quoting from your page:
char Posvalue[13][13][13][13][13][13][13][13][13][13][13][13];

When I try to compile the above statement with FSF's C compiler
I get:
bonzo.c:1: size of array `Posvalue' is too large

typedef char Nodes[13][13][13][13][13][13][13][13][13][13][13][13];
Nodes *Posvalue = calloc(1, sizeof *Posvalue);
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,145
Messages
2,570,826
Members
47,372
Latest member
LucretiaFo

Latest Threads

Top