Reputation: 1545
I have some char array in my program. the number of those arrays is fixed and the name of each array started by a 'S' character and a number as follows:
char *s0="aaasa";
char *s1="bssbaabb";
char *s2="bbbssbaaaa";
.
.
char *sX="bcccbaabaab";
int num_arrays=X;
I decided to use macros to print content of arrays but no success is achieved( i am new to macros).
So i have no idea how should i use Macros to print contents of the arrays in a for
loop as follows:
#X(s,i) //what should be here?
for(int i=0;i<X;i++){
printf("s%d: %s \n",i, X(s,i) );
}
Thanks.
Upvotes: 0
Views: 258
Reputation: 214300
Sounds like what you are fishing for is so-called "X macros". Please note that these should be avoided as far as possible, since they make the code very hard to read.
The most correct solution here is to simply use an array. If you find yourself needing something else, the root cause is likely bad program design. Other posted answers show proper solutions with plain arrays. X macros should be the last resort for very special cases.
That being said, this is how you achieve this with X macros:
#include<stdio.h>
#define STRING_LIST \
X(0, "aaasa") \
X(1, "bssbaabb") \
X(2, "bbbssbaaaa") \
X(3, "bcccbaabaab")
int main(void)
{
// declare pointers s0 to s3:
#define X(i, str) const char* s##i = str;
STRING_LIST
#undef X
// print data by using pointers s0 to s3:
#define X(i, str) printf("s%d: %s \n", i, s##i);
STRING_LIST;
#undef X
}
If you want to combine this with a loop/array, it is also possible, if we go "full C retard" and do something like this...
// Definitely NOT recommended practice but can be studied for learning purposes
#include<stdio.h>
#define STRING_LIST \
X(0, "aaasa") \
X(1, "bssbaabb") \
X(2, "bbbssbaaaa") \
X(3, "bcccbaabaab")
// determine the size of the X macro list by using an enum:
typedef enum
{
#define X(i, str) DUMMY_##i,
STRING_LIST
#undef X
STRINGS_N
} strlist_size_t;
// declare union with both pointers s0 to s3 and an array:
typedef union
{
struct // C11 anonymous struct
{
#define X(i, str) const char* s##i;
STRING_LIST
#undef X
};
const char* array [STRINGS_N];
} strlist_t;
int main(void)
{
// ensure that the type punning is safe on the given system:
_Static_assert(sizeof(strlist_t) == sizeof(const char* [STRINGS_N]),
"Struct padding detected! Type punning failed.");
// initialize list:
strlist_t strlist =
{
#define X(i, str) .s##i = (str),
STRING_LIST
#undef X
};
// print data by using pointers s0 to s3:
#define X(i, str) printf("s%d: %s \n", i, strlist.s##i);
STRING_LIST;
#undef X
printf("\n");
// print data using a loop:
for(int i=0; i<STRINGS_N; i++)
{
printf("s%d: %s \n", i, strlist.array[i]);
}
}
Upvotes: 1
Reputation: 3275
Something like this should work (at least in gcc it would - it uses the block expression compiler extension):
#define X(s, i) ({ \
char *ss[num_arrays]; \
ss[0] = s##0; \
ss[1] = s##1; \
ss[2] = s##2; \
ss[3] = s##3; \
...
ss[X] = s##X; \
ss[i]; })
But it's really creepy and inefficient, as it creates a new array of char pointers and initializes it every time it is used ...
Upvotes: 1
Reputation: 60017
Assuming all your strings are constants you can do the following without macros (They tend to be a bad idea IMHO):
const char *S[] = {
"string1",
"string2",
"strin3",
NULL
};
for(int i=0; s[i];i++){
printf("s%d: %s \n",i, s[i] );
}
PS: Using NULL as a marker for the end of the list - Could use sizeof s/sizeof (s[0])
instead
Upvotes: 1
Reputation: 7441
Answer is you can't do that.
Simply, because macros are compiled and can't be used with for loops in your way.
Use array of pointers to your strings, something like:
char* pointers[] = {
"String1",
"String2",
"...."
};
Usage for printf (using sizeof in for loop to identify number of elements in array to print):
for (int i = 0; i < sizeof(pointers) / sizeof(pointers[0]); i++) {
printf("s%d: %s \n", i, pointers[i]);
}
Upvotes: 2