Reputation: 37
I want to write a function which takes at least two integer and returns the sum of all integer passed to the function:
int sumOfAtLeastTwoIntegers(int a, int b, ...){
int sum = a+b;
va_list ptr;
va_start(ptr,b);
for(){
sum += va_arg(ptr, int)
}
va_end(ptr);
return sum;
}
I want to know how the expression in the for loop has to look like such that the loop continues until all optional arguments were added to the sum. How would I achieve this without knowing how many optional arguments were passed to the function? The function call would look like this:
sumOfAtLeastTwoIntegers(2,3,4,5,1,0,200);
Upvotes: 1
Views: 1042
Reputation: 881383
There are generally two ways to handle variable arguments, pre-knowledge and post-knowledge.
Pre-knowledge is like with printf("%d %c\n", anInt, aChar)
, there's an argument up front which you can use to figure out how many remain. An example of that would be:
int sumOfInts(size_t count, int a, ...); // Needs "count" integers.
int eleven = sumOfInts(2, 4, 7);
Post-knowledge requires you to have a sentinel value that tells you when to stop, such as with:
int sumOfNonZeroInts(int a, ...); // Needs non-zero integers, stops at 0.
int eleven = sumOfInts(4, 7, 0);
One other thing you may want to consider is steering clear of variable argument lists, there are much more expressive ways in C++ for doing what you want with, for example, vectors. The following provides one way of doing this:
#include <iostream>
#include <vector>
template<typename T> T sumOf(const std::vector<T> &vec) {
T acc = T();
for (const T &item: vec)
acc += item;
return acc;
}
int main() {
auto eleven = sumOf<int>({4, 7});
std::cout << "Four plus seven is equal to " << eleven << '\n';
}
This isn't necessarily as fast as variable arguments, but my default position nowadays is to generally optimise for readability first :-)
Upvotes: 9
Reputation: 4899
Use the first argument as an "input size" just how you'd do with regular arrays especially in C.
int sumOfAtLeastTwoIntegers(int howMany, ...) {
int sum = 0
va_list ptr;
va_start(ptr,b);
while(howMany--){
sum += va_arg(ptr, int)
}
va_end(ptr);
return sum;
}
Upvotes: 1
Reputation: 7100
I suggest to use a variadic template like the following. It works only if u give it two integers at least. And all of the args must be integers too.
#include<iostream>
#include <type_traits>
template< typename ... Args>
std::enable_if_t<std::is_same_v<std::common_type_t<Args...>, int>, int>
sum(int arg1, Args...args)
{
return (args+...+arg1);
}
int main(){
std::cout << sum(1,2);//working
std::cout << sum(1,.2);//compile error
std::cout << sum(1);//compile error
}
Upvotes: 5
Reputation: 409166
There are three ways to handle variable-argument functions:
Either have some kind of terminator, an argument whose sole meaning is to terminate the argument list.
Make the first argument be a count of the number of arguments passed.
Some kind of argument-matching format, like e.g. printf
or scanf
.
For your kind of function, the first two variants could both be good solutions (depending on the range of values allowed in the arguments).
Upvotes: 4