todd42
todd42

Reputation: 11

Variable format specifier in C

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

Answers (3)

JonatanE
JonatanE

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

chux
chux

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

tdao
tdao

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

Related Questions