Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Nesting For Statements Revisited


November 1996/Nesting For Statements Revisited

Sometimes the best way to capture looping logic is not in the program control structures but in an object that lets you decide at run time how many loops to iterate over.


When C and C++ provide insufficient loop control using existing constructs, use a C++ class to extend the loop control's capabilities. In the July 1996 issue of CUJ ("Nested for Statements, CUJ, July 1996), James Bell presented a solution to a problem concerning nested for statements. To recap, C/C++ programs frequently use nested for statements to cycle through a range of variables. For example, three nested for loops can be used as follows:

for (int i=0; i<p; i++)
    for (int j=0; j<q; j++)
        for (int k=0; k<r; k++)
            DoSomething( i, j, k);

It is often the case that the number of cycles in each loop, controlled by the values of the p, q, and r variables above, are not known until run time. Usually, however, the number of loops themselves (three in this example) are known in advance, allowing them to be hard-coded. The problem that James addressed concerned the situation where the number of for statements cannot be predetermined, and is only known at run time. His solution was to define a function that could be called in place of the nested for loops, and which used recursion to iterate over the required number of loops.

I have recently had to implement a nested for loop with an unknown number of loops, and was interested in the algorithm used. However, the solution given seemed to me to suffer from a few limitations. First, the way that it was coded meant that a specific recursive subroutine needed to be defined for each implementation. Second, although not dogmatic about this, I am personally inclined to avoid recursion if possible; recursion can all too easily result in run-time stack overflows that are difficult to diagnose. Third, the implementation doesn't resemble a normal for-loop construct, which makes following the program logic more difficult and could affect maintenance. Finally, it was coded in C, and my personal preference is for C++.

My solution is the CMultiFor class shown in listings 1 and 2. The big advantage of this class is that it can be used in a manner resembling a standard for loop. This class lends itself to general-purpose use, and does not require a specific routine to be coded for each implementation. Using CMultiFor, you can rewrite the three-loop construct above as:

CMultiFor mfor;
mfor.Add( 0, p );
mfor.Add( 0, q );
mfor.Add( 0, r );
for ( mfor.Initialize();
      mfor.CarryOn();
      mfor.Increment() )
    DoSomething( mfor.Index(0),
                 mfor.Index(1),
                 mfor.Index(2) );

Implementation Details

CMultiFor uses the CArray template class, which is part of the Microsoft Foundation Classes -- replace this with an STL container class if you prefer. In addition, CMultiFor uses the relatively primitive Windows BOOL type to hold the result of the logical comparison; swap this for C++'s new bool if your compiler can cope.

The CMultiFor class contains various member functions:

void CMultiFor::Add( int start,
                     int end )

This adds a for loop. The for loop is equivalent to:

for (i = start; i < end; i++ )

where start and end are defined by the Add function, and i is the loop index for this for loop. The for loops are executed in the order that they are added. For example,

mfor.Add( a, b );
mfor.Add( c, d );
mfor.Add( e, f );

will be equivalent to:

for (int i=a; i<b; i++)
    for (int j=c; j<d; j++)
        for (int k=e; k<f; k++)

As defined, CMultiFor assumes that the loop indices increment at the end of each loop, and that the loop continues while the loop index is less than the end value. In addition, your code must define the values for start and end before any of the loops are executed.


void CMultiFor::Initialize();

Call this member function to initialize the loop indices.


BOOL CMultiFor::CarryOn();

This function tests whether the loop should continue, and returns FALSE when the all loops have exhausted their indices.

void CMultiFor::Increment();

This increments the loop counters.


int CMultiFor::Count()

This function returns the number of nested for loops that have been defined.


int CMultiFor::Index( int i )

The Index function returns the current value of the loop counter for loop i.

Dr. Robin J. Leatherbarrow is a lecturer in Chemistry at Imperial College, University of London, UK. He has a D.Phil. from Oxford University, and uses C++ for various data analysis applications. Robin can be reached at [email protected].


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.