Reputation: 11
I have a printf statement as follows:
printf("[%d] %d", i, n->data);
I'm trying to make the related code flexible so you can change the variable type of "n->data" depending on your need. Is there a way to make the format specifier update depending on the variable type used?
I've tried including:
const char FS[2] = "%f";
when the variable is a float, then amending the printf statement to:
printf("[%d] "FS, i, n->data);
but this gets the following error, which I don't know how to resolve:
dLList.c:125:23: error: expected ')'
printf("[%d] "FS, i, n->data);
^
dLList.c:125:15: note: to match this '('
printf("[%d] "FS, i, n->data);
^
1 error generated.
Any ideas? Thanks
Upvotes: 1
Views: 2971
Reputation: 941
You could use an enum and a lookup table for format strings. Just make sure your struct that contains the data also contains a matching enum describing the type of data currently contained in the struct.
That way you can write a print function that accepts such a struct as an argument and prints its value using a correct format string for that type of data.
#include <stdio.h>
typedef enum Format_
{
/* Add/remove formats as needed. */
SIGNED_DECIMAL_INT,
UNSIGNED_DECIMAL_INT,
DECIMAL_FLOATING_POINT,
STRING,
POINTER_ADDRESS,
NUM_SUPPORTED_FORMATS
} Format;
static const char* formatStrings[NUM_SUPPORTED_FORMATS] =
{
"%d\n", /* Add more complex format strings if needed. */
"%u\n",
"%f\n",
"%s\n",
"%p\n"
};
typedef struct Wrapper_
{
Format format;
float data;
} Wrapper;
void printData(const Wrapper *const wrapper)
{
printf(formatStrings[wrapper->format], wrapper->data);
}
int main(void)
{
Wrapper wrapper;
wrapper.format = DECIMAL_FLOATING_POINT;
wrapper.data = 12.345f;
/* Prints 12.345000 */
printData(&wrapper);
return 0;
}
Upvotes: 0
Reputation: 153557
Is there a way to make the format specifier update depending on the variable type used?
Yes, C11 has _Generic
. This allows code selection based on the type of the expression. The selection is not evaluated at run-time, but at compile time, the type is determined.
#include <stdio.h>
#include <stdlib.h>
#define print(X) printf(_Generic((X), \
double: "%e\n", \
int: "%i\n", \
char *: "%s\n", \
default: "TBD" \
) , X)
int main(void) {
print(5.0);
print(5);
print("Five");
print(1.0f);
return 0;
}
Output
5.000000e+00
5
Five
TBD
Upvotes: 3
Reputation: 17668
Instead of const char FS[2] = "%f";
, you may try to use macro like this:
#define FS "%f"
that would aggregate the control string format as you apparently want.
Upvotes: 3