Home     |     .Net Programming    |     cSharp Home    |     Sql Server Home    |     Javascript / Client Side Development     |     Ajax Programming

Ruby on Rails Development     |     Perl Programming     |     C Programming Language     |     C++ Programming     |     IT Jobs

Python Programming Language     |     Laptop Suggestions?    |     TCL Scripting     |     Fortran Programming     |     Scheme Programming Language


 
 
Cervo Technologies
The Right Source to Outsource

MS Dynamics CRM 3.0

C++ Programming

Macro question


Hi,

I'm initialising unit test structures using a macro as follows:

#define UTMACRO(x) UT##x

typedef struct
{
        char * key;
        char * arr[5];

}unit_test;

unit_test UT1 = { "three",  { "five", "four", "one", "three",
"two" } };
unit_test UT2 = { "two",    { "five", "four", "one", "three",
"two" } };

int main()
{

        int i;
        unit_test unitTest[2];

        for(i = 0; i < TEST_NUM; i++)
        {
                unitTest[i] = UTMACRO(i + 1);
        }

}

but the compiler is resolving UTMACRO(i + 1) as UT rather than UT1 and
then UT2.

Why? Can this be fixed or does anyone have a better way of performing
this task.

A macro does code subtitutions and nothing else.

    unitTest[i] = UTMACRO(i + 1);

is turned into

    unitTest[i] = UTi + 1;

which then goes to the compiler exactly like that.

> Can this be fixed or does anyone have a better way of performing
> this task.

I'm not quite sure I know what "this task" is.
On 30 May, 18:06, Rolf Magnus <ramag@t-online.de> wrote:

I've got a series of unit test structures UT1, UT2, and so on. I'd
like to use each in turn within the for loop to populate the unit test
array structure. I thought the macro could be used to change the name
from UT1 to UT2 and so on.

Peithon wrote:
> [...]
> I've got a series of unit test structures UT1, UT2, and so on. I'd
> like to use each in turn within the for loop to populate the unit test
> array structure. I thought the macro could be used to change the name
> from UT1 to UT2 and so on.

(i + 1) is a run-time expression.  UT is a compile-time macro.  You
really cannot expect a run-time expression to have any affect on
a compile-time construct.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask

On 30 May, 19:24, "Victor Bazarov" <v.Abaza@comAcast.net> wrote:

> Peithon wrote:
> > [...]
> > I've got a series of unit test structures UT1, UT2, and so on. I'd
> > like to use each in turn within the for loop to populate the unit test
> > array structure. I thought the macro could be used to change the name
> > from UT1 to UT2 and so on.

> (i + 1) is a run-time expression.  UT is a compile-time macro.  You
> really cannot expect a run-time expression to have any affect on
> a compile-time construct.

> V
> --
> Please remove capital 'A's when replying by e-mail
> I do not respond to top-posted replies, please don't ask

No, you're right. It sounds really dumb me even trying. Sorry I'm a
noob. But maybe if I describe what I'm trying to do you could suggest
how to do it properly.

I'm creating an array of unit test structures to input into a search
function.

It searches for 'key' amongst the strings contained in 'arr'. Now the
number of strings contained in arr needs to vary from test to test.

So I might have 5 strings in my first ut struct but 26 in the next.

So I thought I'd create 20 tests with a huge upper limit, say 100, as
in

Code:

typedef struct
{
char * key;
char * arr[100];

}unit_test[20];

But any initialisation arrays of less than a 100 strings will leave
uninitialised ptrs, e.g.

Code:

typedef struct
{
char * key;
char * arr[100];

}unit_test[20] = {

  { "three", { "five", "four", "one", "three", "two" } }, //test1
leaves 95 bad ptrs
   .....,
   ....,
  { "two", { "five", "four", "one"} } //test20 leaves 97 bad ptrs

};

So I thought I'd declare

Code:

typedef struct
{
char * key;
char * arr[100];

}unit_test[20];

globally to get all the ptrs nulled for free and then initialise
within a for loop.
Using the structures

Code:

unit_test UT1 = { "three", { "five", "four", "one", "three",
"two" } };
...
unit_test UT20 = { "two", { "five", "four", "one" } };
Then, the question became how do you reference names UT1, UT2,...,UT20
within a for loop. Answer, macro! Or apparently not because it's
compile-time and I need things init'd at run-time.

How would you achieve the desired result?

Anonymous structs are really to be avoided in C++.  Give it a name,
you'll find that it's better that way...

    struct UnitTest {
        char const* key;
        char const* arr[100];
    };

    UnitTest unit_test[20];

> But any initialisation arrays of less than a 100 strings will leave
> uninitialised ptrs, e.g.

> Code:

> typedef struct
> {
> char * key;
> char * arr[100];
> }unit_test[20] = {
>  { "three", { "five", "four", "one", "three", "two" } }, //test1
> leaves 95 bad ptrs

Actually, not "bad ptrs".  _Null_ ptrs.

>   .....,
>   ....,
>  { "two", { "five", "four", "one"} } //test20 leaves 97 bad ptrs

Again, not "bad ptrs".

> };

> So I thought I'd declare

> Code:

> typedef struct
> {
> char * key;
> char * arr[100];
> }unit_test[20];

> globally to get all the ptrs nulled for free and then initialise
> within a for loop.

You should get them "for free" if you have fewer initialisers than
elements of the array.

> Using the structures

> Code:

> unit_test UT1 = { "three", { "five", "four", "one", "three",
> "two" } };
> ...
> unit_test UT20 = { "two", { "five", "four", "one" } };
> Then, the question became how do you reference names UT1, UT2,...,UT20
> within a for loop. Answer, macro! Or apparently not because it's
> compile-time and I need things init'd at run-time.

> How would you achieve the desired result?

Don't do anything special.  If your compiler doesn't create null
pointers for the omitted elements of the array, complain to the
compiler vendor/manufacturer.

    struct UnitTest {
        char const* key;
        char const* arr[100];
    };
    #include <cassert>
    int main() {
        UnitTest unit_test[20] = { { "one", { "one", "two", "three" } },
                         { "zwei", { "eins", "zwei", "drei", "vier" } },
                   { "pet", { "jedna", "dve", "tri", "ctyri", "pet" } } };
        assert(unit_test[0].arr[3] == 0);
        assert(unit_test[0].arr[99] == 0);
        assert(unit_test[3].key == 0);
    }

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask

On May 30, 9:32 am, Peithon <Peit@googlemail.com> wrote:

I dunno if I fully understand you requirements, but it looks like you
are trying to create a map of key and list of values.  So why not use
just that.

Here is how I would try to do it
1. Create a text file which maintians this mapping
   three,  five,  four, one, three //the first is the key and the
remaining are the list of values
2. Use a map<string, vector<string> > instead of the struct
3. Have a for loop and for each iteration read a line from the file,
split it in to individual values.  The first value becomes the key and
rest can be pushed in to the vector.
4. Once you have the map populated you can use it the way you want.

Hope I am not totally tangent to your requirements.

On 30 May, 20:30, "Victor Bazarov" <v.Abaza@comAcast.net> wrote:

Thanks, this looks excellent. Much appreciated.
I can't say thankyou in Russian, so in Welsh
Diolch yn fawr
On 30 May, 20:42, Naresh Rautela <nraut@gmail.com> wrote:

Thanks, but I'm still too noob to use STL and no you're not tangent at
all.
Add to del.icio.us | Digg this | Stumble it | Powered by Megasolutions Inc