MemAllox
MemAllox

Reputation: 851

How to pad strings using preprocessor macros

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

Answers (2)

chqrlie
chqrlie

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

John Bollinger
John Bollinger

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

Related Questions