Home > Software engineering >  How do I implement arbitrary number of arguments in my Max(int num, ...) with ONLY arguments that ne
How do I implement arbitrary number of arguments in my Max(int num, ...) with ONLY arguments that ne

Time:10-30

How do I implement arbitrary number of arguments in my Max(int num, ...) with ONLY arguments that needs to be compared in C? I'm using va_list from the C library stdarg.h

I've read Variable number of arguments in C programmng, but sadly it seems that there aren't any answers that can help me. Since it is a post in 2018, I wonder if there is a solution to my problem after 4 years from then.

I'm using va_list from the C library stdarg.h to implement Max() . While looking for the maximal value, I have to use for loop to retrieve the arguments from the very first to the last. And that is where I get stuck.

My goal is to implement Max() with only arguments that needs to be compared their value. But I can't find a way to stop my for loop from executing after it reach to the last argument. The mostly seem solutions on the net for breaking the for loop are:

  1. Adding an additional argument that represent the amount of arguments that you are passing in, which tells the for loop to loop for that amount of times
  2. Passing in a number that the for loop's condition part becomes false -> break out of the loop (In my code below, I pass the argument -1 in as the last argument to my function. When the for loop sees that value, it knows it has arrived to the end of the argument)

But the above solutions both require an additional arguments, which I can't achieve my goal. So are there any solutions that can help me with my problem? Any response is appreciated :)

#include <stdio.h>
#include <stdarg.h> // this library is required for infinite number of arguments

int Max(int num, ...){
    va_list ap;
    int temp;
    va_start(ap,num);
    int maximum = num;
    for(temp = va_arg(ap,int); temp!= -1/*put condition here */; temp = va_arg(ap, int)){
        if(temp > maximum){
            maximum = temp;
        }
    }
    va_end(ap);
    return maximum;
}

int main(){
    int maximum;
    printf("the input vals are: 1 3 4 6 3 78 100\n");
    maximum = Max(1,3,4,6,3,78,100, -1);
    printf("maximum val: %d\n",maximum);
}

CodePudding user response:

The C standard does not provide any way for a function to know how many arguments were passed or which is the last one. Such information must be provided by the programmer.

You can use preprocessing features to do this. We can define a macro that counts its arguments:

#define Max(...)    \
    Max(sizeof (int []) {__VA_ARGS__} / sizeof (int), __VA_ARGS__)

This creates a compound literal of type array of int initialized with the macro arguments. Then it calculates the number of arguments by dividing the size of the array by the size of one element. Then it passes this size and the arguments to the Max function. (Note that a macro is not replaced in its own replacement list, so the replacement of the Max macro can call the Max function without causing repeated replacement.)

Then the function must take the number of following arguments as its first argument:

int Max(size_t N, ...)
{
    //  Initialize "maximum seen so far" to identity element of max operation.
    int maximum = INT_MIN;

    va_list ap;
    va_start(ap, N);
    for (size_t i = 0; i < N;   i)
    {
        int t = va_arg(ap, int);
        if (maximum < t)
            maximum = t;
    }
    va_end(ap);
    return maximum;
}

Note that the function definition must appear before the macro definition in the source code, so that replacement of the Max macro does not occur in the function definition.

At least one value must be given. The macro could be made to support zero arguments with some changes to it and the function.

CodePudding user response:

Add this line somewhere after the definition of Max:

#define Max(...) Max(__VA_ARGS__, -1)

It will add -1 at the end of the argument list, so you don't have to.

As a side note, -1 is not a good sentinel for a function like Max because -1 is just an integer, no better or worse than any other integer. What if I want to find Max(-5,32,8,-1,77,-11,141)? I will let you ponder possible solutions for this problem.

  • Related