0

I want to know how can I define a function that receives different type of arguments.

For example suppose I want to define a "myprint" function that receives a string to be printed and an integer that shows the background color of the first string.(I have no problems with changing the color in console.)

But if function receives only the first string,it should choose background color as my default,for example black.

I think this question could be answered because "main" function has this capability.It can receive no arguments,or argc and argv.

I am a beginner C programmer.

Edit:

After Frxstrem's answer,I wrote this code that has a void myPrintf(int backgroundColor,int textColor,char * string) function and I want the same result as Frxstrem's answer for two arg function:

//suppose I have defined colors
#define first(a,...) (a)
#define second(a,b,...) (b)
#define third(a,b,c,...) (c)
#define myprint(...) (myPrintf(first(__VA_ARGS__,BLACK),second(__VA_ARGS__,GRAY),third(__VA_ARGS__)))
void myPrintf(int backgroundColor,int textColor,char * string){
    int color=16*backgroundColor+textColor;
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),color);
        printf("%s",string);
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),0x07);
}
int main(){
    myprint(,,"hello");//error
}

But I get this error:

error C2059: syntax error : ')'
Mohammad
  • 362
  • 1
  • 7
  • 19
  • 1
    Read about variadic functions. You might like to start doing so here: http://en.wikipedia.org/wiki/Variadic_function – alk Dec 28 '14 at 15:36
  • 4
    Checkout http://stackoverflow.com/questions/479207/function-overloading-in-c for more information on function overloading – kwierman Dec 28 '14 at 15:37
  • 2
    As for `main`, it is [defined that there are two forms](http://stackoverflow.com/questions/4207134/what-is-the-proper-declaration-of-main). – Jongware Dec 28 '14 at 15:42
  • 2
    `main` is a special case; C does not support function overloading in any other case. – Oliver Charlesworth Dec 28 '14 at 15:42
  • @alk: I don't think variadic functions are needed here. The OP just want a default value for an argument if it is not given. – Richard-Degenne Dec 28 '14 at 15:45
  • you can't do it. yes, you can't do it in c. the function must have to know how to many argument it receives either in runtime or compile time. – Shakil Ahamed Dec 28 '14 at 15:48
  • I've rolled back the previous edit; a language-agnostic question about function overloading is pretty meaningless; there are loads of languages that offer it. But C isn't one of them. – Oliver Charlesworth Dec 28 '14 at 15:59

2 Answers2

4

Since your question is actually about providing default arguments, you can take advantage of variadic macros:

// always returns first and second argument, respectively
#define FIRST(a, ...) (a)
#define SECOND(a, b, ...) (b)

// define the color black as a constant
#define BLACK 0x000000

// our C function
void myprint_(const char *string, int bgcolor);

// our C macro
#define myprint(...) (myprint_(FIRST(__VA_ARGS__), SECOND(__VA_ARGS__, BLACK)))

Now myprint("hello world"); gets expanded to myprint_("hello world", BLACK) while myprint("hello world", 123456) gets expended to myprint_("hello world", 123456).

Frxstrem
  • 38,761
  • 9
  • 79
  • 119
  • As I said I am a beginner and I am not familiar with using macros in great detail. – Mohammad Dec 28 '14 at 16:00
  • @M.K Well, as far as I know that's really the only way to actually do what you asked in the question, at least in C. However, I would recommend as an alterantive solution to just make two differently named functions (say, `myprint` and `myprint_black`), and calling `myprint` from within `myprint_black`. – Frxstrem Dec 28 '14 at 16:03
  • This is not standard C, probably a gcc extension? Variadic macros there work differently, the `...` doesn't follow a name. – Jens Gustedt Dec 28 '14 at 16:56
  • @JensGustedt Indeed, it's a gcc extension. I rewrote the code to follow the C standard for variadic macros. – Frxstrem Dec 28 '14 at 17:02
  • @Frxstrem, great, thanks. Another nitpick: names starting with an underscore are reserved in file scope. So your `_myprint` should better be `myprint_`. – Jens Gustedt Dec 28 '14 at 17:04
  • I want to know if __VA_ARGS__ is/are (...) in myprint?And another question,if we have a text color in addition to bgcolor does this way work? – Mohammad Dec 29 '14 at 12:12
1

While Frxstrem's answer is correct (and he/she has my upvote on it), too liberal use of preprocessor macros is a code smell. So the purists approach is to just declare two functions, one of which is a simple call through to the other:

void myprint_color(char* string, int color) {
    ...
}

void myprint(char* string) {
    myprint_color(string, kBackgroundColor);
}

This approach has two advantages:

  1. It's very clear to a reader what's happening.

  2. You are not forced to provide all the functionality of the two functions within the body of a single one. I. e. you are free to implement it the other way round like this:

    void myprint(char* string) {
        ...
    }
    
    void myprint_color(char* string, int color) {
        int savedColor = /* get current text color */;
        /* set the text color */
    
        myprint(string);
    
        /* reset the text color to savedColor */
    }
    

    With this approach, the simpler function really avoids setting the color, while the other really adds the relevant code, instead of always setting a color that defaults to black.

    You are free to use whichever approach is more convenient to implementing the functionality. And you can decide later to change the implementation from one approach to the other without breaking code on the user side. Such a change cannot be done once you have preprocessor magic in place that provides the look and feel of a default argument.

cmaster - reinstate monica
  • 38,891
  • 9
  • 62
  • 106