简体   繁体   English

如何在不知道 C++ 中有多少可选 arguments 的情况下在循环中使用 va_arg?

[英]How can I use va_arg in a loop without knowing how many optional arguments there are in C++?

I want to write a function which takes at least two integer and returns the sum of all integer passed to the function: 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.我想知道 for 循环中的表达式必须如何看起来才能使循环继续,直到所有可选的 arguments 都被添加到总和中。 How would I achieve this without knowing how many optional arguments were passed to the function?在不知道有多少可选 arguments 被传递给 function 的情况下,我将如何实现这一点? The function call would look like this: function 调用如下所示:

sumOfAtLeastTwoIntegers(2,3,4,5,1,0,200);

There are generally two ways to handle variable arguments, pre-knowledge and post-knowledge.处理变量arguments一般有两种方式,前置知识和后置知识。

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.预知识就像printf("%d %c\n", anInt, aChar) ,前面有一个参数,您可以使用它来确定剩余的数量。 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.可能要考虑的另一件事是避免使用变量参数列表,C++ 中有更多表达方式可以用来做您想做的事情,例如向量。 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:-)这不一定像变量 arguments 一样,但我现在的默认 position 通常是首先优化可读性:-)

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
 
}

There are three ways to handle variable-argument functions:处理可变参数函数的三种方法:

  1. Either have some kind of terminator , an argument whose sole meaning is to terminate the argument list.要么有某种终止符,一个参数,其唯一含义是终止参数列表。

  2. Make the first argument be a count of the number of arguments passed.使第一个参数成为 arguments 传递的数量的计数。

  3. Some kind of argument-matching format, like eg printf or scanf .某种参数匹配格式,例如printfscanf

For your kind of function, the first two variants could both be good solutions (depending on the range of values allowed in the arguments).对于您的 function,前两个变体都可能是很好的解决方案(取决于参数中允许的值范围)。

Use the first argument as an "input size" just how you'd do with regular arrays especially in C.使用第一个参数作为“输入大小”,就像使用常规 arrays 一样,尤其是在 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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM