Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to make an output function similar to Python's in C?

Tags:

python

c

output

I am working on a custom programming language called BPML and I want to try and update the output function called say().

Recent version in C:

void say(char *text) {
    printf("%s", text);
}

Recent version in Python:

def say(text):
    print(text, end = '')

In C, I want it to act like Python's print() function by just typing in the variable to the function, but it's not the case in C, because you still have to use the appropriate kind of variable.

Which is why I got an error in a program I made:

#include <stdio.h>

void say(char *text);

int main() {
    int number = 21;
    say(number);
}

void say(char *text) {
    // Output function
}

Error:

P1.c:7:9: error: incompatible integer to pointer conversion passing 'int' to parameter of type 'char *' [-Werror,-Wint-conversion]
    say(number);
        ^~~~~~

I still have to use the itoa() function in <stdlib.h>, which I didn't have in mind, since it wasn't available in the version of C I use.

So is it possible to make some kind of output function that is similar to the way Python's function acts?

like image 408
BMPL Avatar asked Mar 03 '23 01:03

BMPL


1 Answers

C does not have overloads, nor does it have function templates. But you can a macro and generic selection in C11 and above to choose an appropriate format:

#include <stdio.h>

#define say(X) printf(_Generic((X),    \
                        double: "%f ", \
                        float:  "%f ", \
                        char *: "%s ", \
                        int:    "%d "  \
                ), (X));

int main(void) {
    say(21);
    say(21.5);
    say(21.5f);
    say("Hello world");
}

This can be coupled with X-macros to have really powerful constructs easily:

#include <stdio.h>

// you can easily add new supported types here
#define SAY_FORMATS(X) \
    X(double, "%f")    \
    X(float,  "%f")    \
    X(char *, "%s")    \
    X(int,    "%d")
    
// add space after each item. Leading comma so that we do not
// need to have a dummy entry in the end. Unfortunately C 
// does not like trailing commas in _Generic. Thanks to 
// user694733 for the idea
#define GENERIC_ENTRY(Type, Format) \
    , Type: Format " "

#define say(X)                      \
     printf(_Generic((X)            \
         SAY_FORMATS(GENERIC_ENTRY) \
     ), (X))

int main(void) {
    say(21);
    say(21.5);
    say(21.5f);
    say("Hello world");
}
like image 171