|
|
 |
 |
 |
 |
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.
Peithon wrote: > 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?
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:
> Peithon wrote: > > 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? > 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.- Hide 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.
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?
Peithon wrote: > [..] > 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 -- 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:
> 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.
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:
> Peithon wrote: > > [..] > > 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 > -- > 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 - >
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:
> On May 30, 9:32 am, Peithon <Peit @googlemail.com> wrote: > > 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. > 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 - >
Thanks, but I'm still too noob to use STL and no you're not tangent at all.
|
 |
 |
 |
 |
|