Macro question

P

Peithon

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 = 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.
 
R

Rolf Magnus

Peithon said:
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 = UTMACRO(i + 1);
}


}


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

Why?


A macro does code subtitutions and nothing else.

unitTest = UTMACRO(i + 1);

is turned into

unitTest = 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.
 
P

Peithon

Peithon said:
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 = UTMACRO(i + 1);
}

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


A macro does code subtitutions and nothing else.

unitTest = UTMACRO(i + 1);

is turned into

unitTest = 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.- Hide quoted text -

- Show quoted text -


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.
 
V

Victor Bazarov

Peithon said:
[...]
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
 
P

Peithon

Peithon said:
[...]
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

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?
 
V

Victor Bazarov

Peithon said:
[..]
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];

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
 
N

Naresh Rautela

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 = 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.


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.
 
P

Peithon

Peithon said:
[..]
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

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

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.

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

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

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- Hide quoted text -

- Show quoted text -

Thanks, this looks excellent. Much appreciated.
I can't say thankyou in Russian, so in Welsh
Diolch yn fawr
 
P

Peithon

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 = 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.

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.- Hide quoted text -

- Show quoted text -


Thanks, but I'm still too noob to use STL and no you're not tangent at
all.
 

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

Similar Threads

Help in this program. 2
A silly macro technique 5
variadic macro 2
offsetof() Macro Attempt 45
Alternative approach to bitfields 9
multi block macro 8
Macro to stringify an enum 4
question about macro? 23

Members online

No members online now.

Forum statistics

Threads
473,774
Messages
2,569,598
Members
45,160
Latest member
CollinStri
Top