How do I wind this into a nested loop?

Discussion in 'C Programming' started by Robbie Hatley, Feb 29, 2008.

  1. Greetings, group. I've got a big MESS of code in one of the source
    files of my employer's primary software product. It's basically
    assignments of automatically-generated control-id macros to arrays,
    so they can be easily accessed by nested for loops. This mess
    looks like:

    AuxChanId [0] [0] = IG1_CH1;
    AuxTypeId [0] [0] = IG1_TYPE1;
    AuxOperId [0] [0] = IG1_OP1;
    AuxThreId [0] [0] = IG1_THRESH1;
    AuxMinuId [0] [0] = IG1_MM1;
    AuxSecoId [0] [0] = IG1_SS1;
    AuxHoldId [0] [0] = IG1_HOLD1;
    AuxChanId [0] [1] = IG1_CH2;
    AuxTypeId [0] [1] = IG1_TYPE2;
    AuxOperId [0] [1] = IG1_OP2;
    AuxThreId [0] [1] = IG1_THRESH2;
    AuxMinuId [0] [1] = IG1_MM2;
    AuxSecoId [0] [1] = IG1_SS2;
    AuxHoldId [0] [1] = IG1_HOLD2;
    AuxChanId [0] [2] = IG1_CH3;
    AuxTypeId [0] [2] = IG1_TYPE3;
    AuxOperId [0] [2] = IG1_OP3;
    AuxThreId [0] [2] = IG1_THRESH3;
    AuxMinuId [0] [2] = IG1_MM3;
    AuxSecoId [0] [2] = IG1_SS3;
    AuxHoldId [0] [2] = IG1_HOLD3;
    .
    .
    .
    AuxChanId [1] [0] = IG2_CH1;
    AuxTypeId [1] [0] = IG2_TYPE1;
    AuxOperId [1] [0] = IG2_OP1;
    AuxThreId [1] [0] = IG2_THRESH1;
    AuxMinuId [1] [0] = IG2_MM1;
    AuxSecoId [1] [0] = IG2_SS1;
    AuxHoldId [1] [0] = IG2_HOLD1;
    .
    .
    .
    (continuing likewise for hundreds more lines)
    .
    .
    .

    Ugly as hell and takes up a lot of space. Is this any way to wind this
    into nested for loops, perhaps by using preprocessor commands to
    generate the macro name strings and insert them on the right?
    Perhaps something using the stringizing and concatenation commands?
    I don't see how to go about it, though... or even if it CAN be done.

    --
    Cheers,
    Robbie Hatley
    lonewolf aatt well dott com
    www dott well dott com slant user slant lonewolf slant
    Robbie Hatley, Feb 29, 2008
    #1
    1. Advertising

  2. On Feb 29, 10:29 pm, "Robbie Hatley"
    > Greetings, group. I've got a big MESS of code in one of the source
    > files of my employer's primary software product. It's basically
    > assignments of automatically-generated control-id macros to arrays,
    > so they can be easily accessed by nested for loops. This mess
    > looks like:
    >
    > AuxChanId [0] [0] = IG1_CH1;
    > AuxTypeId [0] [0] = IG1_TYPE1;
    >


    Personally, I would use some other language to generate
    the code. But, you could try something like the
    following, which will work to generate code for
    a 2x2 array for AuxTypeI. It should be straightforward
    to expand it to larger arrays. (Once again, it's
    a good thing the trailing comma is allowed in
    initializers!):

    #define _TYPE(x) { IG##x##_TYPE1, IG##x##_TYPE2 },
    #define TYPE _TYPE(1) _TYPE(2)

    int AuxTypeId [][2] = { TYPE };
    William Pursell, Feb 29, 2008
    #2
    1. Advertising

  3. Robbie Hatley

    Guest

    "Robbie Hatley" <> writes:

    > Greetings, group. I've got a big MESS of code in one of the source
    > files of my employer's primary software product. It's basically
    > assignments of automatically-generated control-id macros to arrays,
    > so they can be easily accessed by nested for loops. This mess
    > looks like:
    >
    > AuxChanId [0] [0] = IG1_CH1;
    > AuxTypeId [0] [0] = IG1_TYPE1;
    > .
    > .
    > (continuing likewise for hundreds more lines)
    > .
    > Ugly as hell and takes up a lot of space. Is this any way to wind this
    > into nested for loops, perhaps by using preprocessor commands to
    > generate the macro name strings and insert them on the right?
    > Perhaps something using the stringizing and concatenation commands?
    > I don't see how to go about it, though... or even if it CAN be done.


    Personally, I would generate it with a shell (sh) script and then
    either include the generated source or compile it to a seperate object
    file and then link it in.

    Or, the C preprocessor macros (as suggested by another) could clean it
    up quite a bit.

    But then again, if it ain't broke...

    --
    burton
    , Feb 29, 2008
    #3
  4. William Pursell <> wrote:
    > ...
    > Personally, I would use some other language to generate
    > the code.  But, you could try something like the
    > following, which will work to generate code for
    > a 2x2 array for AuxTypeI.  It should be straightforward
    > to expand it to larger arrays.  (Once again, it's
    > a good thing the trailing comma is allowed in
    > initializers!):
    >
    > #define _TYPE(x) { IG##x##_TYPE1, IG##x##_TYPE2 },


    With the exception of predefined macros, identifiers
    with a leading underscore followed by an upper case
    letter are reserved for any use.

    This goes for _TYPE1 and _TYPE2 as well as _TYPE.

    > #define TYPE _TYPE(1) _TYPE(2)
    >
    > int AuxTypeId [][2] = { TYPE };


    A more detailed sample is...

    enum { /* some dummy values for testing */
    IG1_CH1, IG1_TYPE1,
    IG1_CH2, IG1_TYPE2,
    IG1_CH3, IG1_TYPE3,
    IG2_CH1, IG2_TYPE1,
    IG2_CH2, IG2_TYPE2,
    IG2_CH3, IG2_TYPE3,
    IG3_CH1,
    IG3_CH2,
    IG3_CH3
    };

    #define ARRAY(T,R,C) ROWS_ ## R (T,C)

    #define ROWS_1(T,C) ROW(T,C,1)
    #define ROWS_2(T,C) ROW(T,C,1), ROW(T,C,2)
    #define ROWS_3(T,C) ROW(T,C,1), ROW(T,C,2), ROW(T,C,3)
    /* : */

    #define ROW(T,C,r) { COL_ ## C (T,r) }

    #define COL_1(T,r) ITEM(T,r,1)
    #define COL_2(T,r) ITEM(T,r,1), ITEM(T,r,2)
    #define COL_3(T,r) ITEM(T,r,1), ITEM(T,r,2), ITEM(T,r,3)
    /* : */

    #define ITEM(T,r,c) IG ## r ## _ ## T ## c

    int AuxChanID[3][3] = { ARRAY(CH, 3, 3) };
    int AuxTypeID[2][3] = { ARRAY(TYPE, 2, 3) };

    --
    Peter
    Peter Nilsson, Mar 1, 2008
    #4
  5. William Pursell wrote:

    > On Feb 29, 10:29 pm, "Robbie Hatley"
    > > Greetings, group. I've got a big MESS of code in one of the source
    > > files of my employer's primary software product. It's basically
    > > assignments of automatically-generated control-id macros to arrays,
    > > so they can be easily accessed by nested for loops. This mess
    > > looks like:
    > >
    > > AuxChanId [0] [0] = IG1_CH1;
    > > AuxTypeId [0] [0] = IG1_TYPE1;
    > >

    >
    > Personally, I would use some other language to generate
    > the code. But, you could try something like the
    > following, which will work to generate code for
    > a 2x2 array for AuxTypeI. It should be straightforward
    > to expand it to larger arrays. (Once again, it's
    > a good thing the trailing comma is allowed in
    > initializers!):
    >
    > #define _TYPE(x) { IG##x##_TYPE1, IG##x##_TYPE2 },
    > #define TYPE _TYPE(1) _TYPE(2)
    >
    > int AuxTypeId [][2] = { TYPE };


    Wow, that's cool! So it *can* be done. I've got 7 4x8 arrays, so let
    me see if I can take that ball and run with it....

    #define CH_ROW(x) \
    { IG##x##_CH1, IG##x##_CH2, IG##x##_CH3, IG##x##_CH4, \
    IG##x##_CH5, IG##x##_CH6, IG##x##_CH7, IG##x##_CH8, },

    #define CH_INIT { CH_ROW(1) CH_ROW(2) CH_ROW(3) CH_ROW(4) }

    ( ... and the same kind of thing for the other 6 arrays ... )

    So now, my definition/initialization for my arrays looks like:

    int AuxChanId [4] [8] = CH_INIT;
    int AuxTypeId [4] [8] = TYPE_INIT;
    int AuxOperId [4] [8] = OP_INIT;
    int AuxThreId [4] [8] = THRESH_INIT;
    int AuxMinuId [4] [8] = MM_INIT;
    int AuxSecoId [4] [8] = SS_INIT;
    int AuxHoldId [4] [8] = HOLD_INIT;

    Perhaps a little complicated, but I think it still beats my old way,
    which was to assign all 224 elements individually:

    AuxChanId [0] [0] = IG1_CH1;
    AuxTypeId [0] [0] = IG1_TYPE1;
    AuxOperId [0] [0] = IG1_OP1;
    AuxThreId [0] [0] = IG1_THRESH1;
    AuxMinuId [0] [0] = IG1_MM1;
    AuxSecoId [0] [0] = IG1_SS1;
    AuxHoldId [0] [0] = IG1_HOLD1;
    ... etc ...
    AuxChanId [3] [7] = IG4_CH8;
    AuxTypeId [3] [7] = IG4_TYPE8;
    AuxOperId [3] [7] = IG4_OP8;
    AuxThreId [3] [7] = IG4_THRESH8;
    AuxMinuId [3] [7] = IG4_MM8;
    AuxSecoId [3] [7] = IG4_SS8;
    AuxHoldId [3] [7] = IG4_HOLD8;
    // 224 lines of code, total

    The C preprocessor is truly an amazing machine.

    Thanks for the tips!

    --
    Cheers,
    Robbie Hatley
    lonewolf aatt well dott com
    www dott well dott com slant user slant lonewolf slant
    Robbie Hatley, Mar 1, 2008
    #5
  6. Peter Nilsson wrote:

    ========BEGIN QUOTE=======================
    A more detailed sample is...

    enum { /* some dummy values for testing */
    IG1_CH1, IG1_TYPE1,
    IG1_CH2, IG1_TYPE2,
    IG1_CH3, IG1_TYPE3,
    IG2_CH1, IG2_TYPE1,
    IG2_CH2, IG2_TYPE2,
    IG2_CH3, IG2_TYPE3,
    IG3_CH1,
    IG3_CH2,
    IG3_CH3
    };

    #define ARRAY(T,R,C) ROWS_ ## R (T,C)

    #define ROWS_1(T,C) ROW(T,C,1)
    #define ROWS_2(T,C) ROW(T,C,1), ROW(T,C,2)
    #define ROWS_3(T,C) ROW(T,C,1), ROW(T,C,2), ROW(T,C,3)
    /* : */

    #define ROW(T,C,r) { COL_ ## C (T,r) }

    #define COL_1(T,r) ITEM(T,r,1)
    #define COL_2(T,r) ITEM(T,r,1), ITEM(T,r,2)
    #define COL_3(T,r) ITEM(T,r,1), ITEM(T,r,2), ITEM(T,r,3)
    /* : */

    #define ITEM(T,r,c) IG ## r ## _ ## T ## c

    int AuxChanID[3][3] = { ARRAY(CH, 3, 3) };
    int AuxTypeID[2][3] = { ARRAY(TYPE, 2, 3) };

    ===========END QUOTE=====================================

    (For some reason, my mail prog refuses to prefix lines of
    that message with "> " for quoting in reply. Weird.)

    I didn't even realize that function-like macros could have
    multiple arguments! Fascinating! I used just 1 argument,
    so what I came up with (based on Peter Nilsson's technique),
    was this:

    #define CH_ROW(x) \
    { IG##x##_CH1, IG##x##_CH2, IG##x##_CH3, IG##x##_CH4, \
    IG##x##_CH5, IG##x##_CH6, IG##x##_CH7, IG##x##_CH8, },

    #define CH_INIT { CH_ROW(1) CH_ROW(2) CH_ROW(3) CH_ROW(4) }

    #define TYPE_ROW(x) \
    { IG##x##_TYPE1, IG##x##_TYPE2, IG##x##_TYPE3, IG##x##_TYPE4, \
    IG##x##_TYPE5, IG##x##_TYPE6, IG##x##_TYPE7, IG##x##_TYPE8, },

    #define TYPE_INIT { TYPE_ROW(1) TYPE_ROW(2) TYPE_ROW(3) TYPE_ROW(4) }

    (... and likewise for the other 5 arrays as well ...)

    Certainly that could be simplified a lot by using multiple arguments.
    And that would reduce the likelyhood of errors, as well.
    I'll get to work on that. Thanks for the tips!

    By the way, are you sure it's legal to #define ARRAY, then ROW,
    then ITEM, in that order? Isn't that going to cause "undefined
    identifier" errors? Or does the preprocessor handle that by
    doing multiple passes?

    --
    Cheers,
    Robbie Hatley
    lonewolf aatt well dott com
    www dott well dott com slant user slant lonewolf slant
    Robbie Hatley, Mar 1, 2008
    #6
  7. Re: How do I wind this into a nested loop? (Attribution Correction)

    I'd written:

    > ... so what I came up with (based on Peter Nilsson's technique),
    > was this: ...


    Oops, that should have been "William Pursell", not "Peter Nilsson".
    Hate to self-nit-pick, but gotta give credit to *BOTH* gentlemen
    for their asistance on this matter.

    I finally got my 224 lines of messy code boiled down to this:

    #define AUXI_ITEM(t,r,c) IG ## r ## _ ## t ## c

    #define AUXI_ROW(t,r) \
    { AUXI_ITEM(t,r,1), AUXI_ITEM(t,r,2), AUXI_ITEM(t,r,3), AUXI_ITEM(t,r,4), \
    AUXI_ITEM(t,r,5), AUXI_ITEM(t,r,6), AUXI_ITEM(t,r,7), AUXI_ITEM(t,r,8) }

    #define AUXI_ARRAY(t) \
    {AUXI_ROW(t,1), AUXI_ROW(t,2), AUXI_ROW(t,3), AUXI_ROW(t,4)}

    EXTERN int AuxChanId [4] [8] INIT_TO(AUXI_ARRAY(CH) );
    EXTERN int AuxTypeId [4] [8] INIT_TO(AUXI_ARRAY(TYPE) );
    EXTERN int AuxOperId [4] [8] INIT_TO(AUXI_ARRAY(OP) );
    EXTERN int AuxThreId [4] [8] INIT_TO(AUXI_ARRAY(THRESH) );
    EXTERN int AuxMinuId [4] [8] INIT_TO(AUXI_ARRAY(MM) );
    EXTERN int AuxSecoId [4] [8] INIT_TO(AUXI_ARRAY(SS) );
    EXTERN int AuxHoldId [4] [8] INIT_TO(AUXI_ARRAY(HOLD) );

    *MUCH* better! Thanks to Willam Pursell and Peter Nilsson for all their
    help!

    --
    Cheers,
    Robbie Hatley
    lonewolf aatt well dott com
    www dott well dott com slant user slant lonewolf slant
    Robbie Hatley, Mar 1, 2008
    #7
  8. On Mar 1, 12:13 am, Peter Nilsson <> wrote:
    > William Pursell <> wrote:


    > > #define _TYPE(x) { IG##x##_TYPE1, IG##x##_TYPE2 },

    >
    > With the exception of predefined macros, identifiers
    > with a leading underscore followed by an upper case
    > letter are reserved for any use.



    Thank you for the reminder. For some reason, I
    know this fact and apply it carefully to 'real'
    symbols, but continue to misapply it to
    pre-processor names. Apparently, I will need
    to be burned by it in real life before I
    finally learn.
    William Pursell, Mar 1, 2008
    #8
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. kashumoto_tokugawa
    Replies:
    1
    Views:
    1,695
  2. Mathematician
    Replies:
    0
    Views:
    559
    Mathematician
    Dec 24, 2006
  3. Caleb

    Wind Resistance

    Caleb, Apr 10, 2007, in forum: Java
    Replies:
    7
    Views:
    561
    Christian
    Apr 10, 2007
  4. Trevor L.

    Whistling in the wind

    Trevor L., Dec 31, 2006, in forum: ASP General
    Replies:
    2
    Views:
    311
    Trevor L.
    Jan 1, 2007
  5. Isaac Won
    Replies:
    9
    Views:
    364
    Ulrich Eckhardt
    Mar 4, 2013
Loading...

Share This Page