Reputation: 851
Is it possible to pad a string with spaces (or any character) using only preprocessor macros? If so, how?
Example:
#define SOME_STR "v1.1"
#define STR_PAD(str, len) // <-- padding defined string
#define SOME_STR_PADDED STR_PAD(SOME_STR, 10) // evaluates to "v1.1 "
I know that there are simple solutions during runtime, but my question is how to pad a string during compile time.
Upvotes: 4
Views: 1125
Reputation: 144740
Very interesting question! It does not seem possible in the general case where both str
and len
are unknown, and also when str
alone is unknown. If both the length of str
is known and len
is bounded by some reasonable fixed value, one could generate a compound ternary expression that compiles to a single string constant.
Here is an illustration:
// compile time padding: str must be a string constant and len <= 4 + strlen(str)
#define STR_PAD(str, len) (((len) + 1 <= sizeof str) ? str : \
((len) == sizeof str) ? str " " : \
((len) == sizeof str + 1) ? str " " : \
((len) == sizeof str + 2) ? str " " : \
str " ")
Upvotes: 6
Reputation: 180201
In the first place, the preprocessor can convert tokens to strings, but it cannot modify existing strings at all. What it can do is place string literals next to each other ("foo" "bar"
), which is translated at compile time -- albeit not formally by the preprocessor -- equivalently to the concatenated string ("foobar"
).
You could, therefore do something like this:
#define VERSION "v1.1"
#define APPEND_10_SPACES(s) s " "
printf("%s", APPEND_10_SPACES(VERSION));
With considerably more difficulty, you could arrange to append a number of spaces specified by a macro argument, too. Your web searches should turn up several results pertaining to making the preprocessor mimic iteration.
What the preprocessor absolutely cannot do, however, is determine or use the length of a string literal, so as to allow you to do something equivalent to padding a literal to a specific length. If you need that, then you could potentially rely on a workaround along these lines:
char padded[] = APPEND_10_SPACES(VERSION);
padded[10] = '\0';
You do not that way get your desired string as a literal, but you do get it, at the cost of allocating up to 10 more bytes than you need, and truncating the original string if it was in fact longer than 10 characters.
Upvotes: 1