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 : ')'
7
  • 1
    Read about variadic functions. You might like to start doing so here: en.wikipedia.org/wiki/Variadic_function Commented Dec 28, 2014 at 15:36
  • 4
    Checkout stackoverflow.com/questions/479207/function-overloading-in-c for more information on function overloading Commented Dec 28, 2014 at 15:37
  • 2
    As for main, it is defined that there are two forms. Commented Dec 28, 2014 at 15:42
  • 2
    main is a special case; C does not support function overloading in any other case. Commented Dec 28, 2014 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. Commented Dec 28, 2014 at 15:45

2 Answers 2

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).

Sign up to request clarification or add additional context in comments.

6 Comments

As I said I am a beginner and I am not familiar with using macros in great detail.
@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.
This is not standard C, probably a gcc extension? Variadic macros there work differently, the ... doesn't follow a name.
@JensGustedt Indeed, it's a gcc extension. I rewrote the code to follow the C standard for variadic macros.
@Frxstrem, great, thanks. Another nitpick: names starting with an underscore are reserved in file scope. So your _myprint should better be myprint_.
|
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.

1 Comment

However this answer is correct,but I think it is not answer of my question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.