|
|||
Writing a Function with variable number of arguments[BACK]Some times it becomes necessary to write a function with variable number of arguments. That is we do not have an idea of how many arguments a function can have before hand. The best emaple for this is the venerated printf(...) function which takes any number of arguments form user and prints a character string in the console window. Have you noticed one thing with printf(...), what ever might be the number of arguments that we pass to this function the first argument is always same, the (char *) type. So, if you would like to write a function with variable number of arguments, it is necessary to fix the first operand of the function signature (formal arguments of a function are called as signature of that function). I will try to explain you to write a function with variable number of arguments by taking two examples.
For finding an average of some numbers you might not know how many arguments will be passed in to the function. One way you could make the function would be to accept a pointer to an array like Avg(float vars[]). Another way would be to write a function that can take any number of arguments. So you would write Avg(4, 12.2, 23.3, 33.3, 12.1); or you might write Avg(2, 2.3, 34.4);
To use a function with variable number of arguments, or more precisely, a function without a set number of arguments, you would use the stdarg.h header file. Just add this line #include <stdarg.h> on the top of your cpp file or in the stdafx.h file if you are programming in windows environment. There are four parts needed in writing a function with variable number of arguments. va_list, which stores the list of arguments passed to the function, va_start, which initializes the starting argument of the list of arguments, va_arg, which returns the next argument from the list and va_end, which cleans up the memory allocated to the arguments in the list that is passed to the function. Function Declaration: In the normal way write the function name as you wish and give it a return type that you want. Here there will be a small change in the function signature about the way we need to write it. Write the first argument of the function as usually and as a second argument you should place an ellipsis (which looks like '...'). So, int Avg(int x, ...) would tell the compiler that the function should accept however many arguments that the programmer uses, as long as it is equal to at least one and that too the defined one. In this case the first argument should be int. va_list is like any type name that can be used to declare a variable. For example, va_list list; Here list stores the list of arguments that we pass to the function. va_start is a macro which accepts two arguments. The first argument should be a va_list variable that we declare and the second should be the name of the variable that directly precedes the ellipsis (...) in our function declaration. In our case, in he function Ang, to initialize a list with va_start, you would write va_start(list, x); va_arg takes a va_list and a variable type, and returns the next argument in the list in the form of whatever variable type it is told. It then moves down the list to the next argument. For example, va_arg(list, double) will return the next argument, assuming it exists, in the form of a double. The next time it is called, it will return the argument following the last returned number, if one exists. To show how each of the parts works, take an example Average function. #include <stdarg.h> #include <iostream.h> double Avg(int num, ...) { va_list arguments; //A variable to store the list of arguments passed to the function va_start(arguments, num); //Initializing arguments to store all values passed into the function after num int sum=0; for(int x=0; x<num; x++) sum+=va_arg(arguments, double); //Adds the next value in argument list to sum. You can replace the type name double with int or float. va_end(arguments); //Cleans up the list return sum/(double)num; //Returns the average computed(typecast prevents trunctation) } int main() { cout<<average(3, 12.2, 22.3, 4.5)endl; cout<<average(5, 3.3, 2.2, 1.1, 5.5, 3.3)<<endl; return 0; }[BACK][TOP] Example 2: Writing your own printf Function: After trying some crazy things on how to write a printf, efficiently with fewer lines of code, I got this and I use it in all my OpenGL programs to display Rasterised Bitmap Fonts in the OpenGL context. The function uses the same things that are explained above. So, direct code for function would be sufficient I guess. int Printf(char *formatString, ...) { char *buf=new char[255]; //declare array on heap or on stack like char buf[255] /* limilation: Here the final string you are going to print should be less than 255 characters wide or whatever the length you declare there. It's not a wise thing to have unlimited size or variable size, but you can have it by changing the above.*/ /* declaration to char *buf="\0"; initializing to NULL character is important as it indicates the End of String or terminating character.*/ va_list arguments; va_start(arguments, formatString); int strLength=_vsnprintf(buf, strlen(buf), formatString, arguments); PrintString(buf); /* This function parses the string character by character and displays equivalent Bitmap Font on the Screen. Each character is a display list. This function is particularly useful for OpenGL programmers.*/ va_end arguments; delete [ ] buf; return strLength; } It isn't necessarily a good idea to use a variable argument list at all times, because, potential exists for assuming a value of one type, while it is in fact another, such as a NULL pointer being assumed to be an integer. Functions with variable arguments should be used very rarely and they are also necessary only on some situations. Like venerous printf(). Till now I just wrote only one function in this way and that is the one above which is a replacement of original printf() to print characters not on the console window but the OpenGL context. Actually you can do what ever you want at the point where I wrote PrintString(...) function. Tried so many alternatives and thought a good example will be helpful for some one else. V Rama Aravind. 13-07-04. |
|||
|