【问题标题】:how to pass n number of arguments to a function where n is not known [duplicate]如何将 n 个参数传递给 n 未知的函数 [重复]
【发布时间】:2014-10-09 22:37:34
【问题描述】:

我需要将 n 个参数传递给一个函数。用户可以输入任意数量的参数,但我们不知道他将传递的参数数量。但是我看到的所有使用 va_list 的实现都包含一个 count ,但在这里我们不知道这个数字。它看起来像

        void xyz(int x[],...);

我们只有数组

函数的使用方式是一样的。

        xyz({1,2,3},{1,1},{2},{3,3,3})

然后如果可能的话,我希望我的函数中有 3 个数组在单独的变量中。我需要在这些数组中进行一些计算。这在 C++ 中可能吗??

【问题讨论】:

  • 如何将参数收集到字符串向量中,然后将其传递给函数?
  • 我需要坚持函数声明。但我找不到任何文档或任何实现,其中某处做了类似的事情
  • 实际的函数声明是什么?真的是void xyz(int x[], ...)吗?
  • 你如何用 - 大概 - 运行时定义的参数计数来调用它?
  • 函数名与xyz不同但需要n个数组

标签: c++ function variadic-functions


【解决方案1】:

您可以使用可变参数函数(如printf),但您通常不希望这样做。

您可以将initializer_list 作为参数。这将允许您获取可以全部转换为单一类型的项目的大括号列表:

void f(std::initializer_list<int> l);

...你可以称之为:

f({1, 2, 3, 4});

还有一个 std::vector 的 ctor 采用 std::initializer_list,因此您可以采用(参考)vector&lt;T&gt; 并完成大致相同的操作。但是请注意,(与 C++ 的大多数部分不同)它不支持缩小转换,因此对于上面需要 ints 的 f,如果您尝试传递(例如)@改为 987654330@。

如果你不喜欢大括号,或者想支持不同类型的参数,你可以使用可变参数模板。例如,这是我前段时间发布的一个函数,用于获取任意数量的(几乎)任意类型的参数,将它们组合成一个字符串,并将生成的字符串写入套接字:

#include <sstream>
#include <string>
#include <iostream>

template <class T>
std::string stringify(T const &t) { 
    std::stringstream b;
    b << t;
    return b.str();
}

template<typename T, typename... Args>
std::string stringify(T arg, const Args&... args) {
    return stringify(arg) + stringify(args...);
}

template<typename... Args>
void send_cmd(const Args&... args) { 
    std::string buffer = stringify(args...);
    send(sock, buffer.c_str(), buffer.length(), 0);
}

int main() {
    std::string three{" three"};

    send_cmd("one: ", 1, " two: ", 2, three, "\n");

    return 0;
}

【讨论】:

    【解决方案2】:
    #include <iostream>
    #include <initializer_list>
    #include <list>
    #include <vector>
    #include <algorithm>
    #include <iterator>
    
    // Base case: do nothing once all inputs have been processed
    void implementation(const std::list<int>& acc) {}
    
    // Recursively pick off one sequence at a time, copying the data into
    // the accumulator
    template<class ONE, class ... REST>
    void implementation(std::list<int>& accumulator,
                        const ONE& first,
                        const REST& ... rest) {
      std::copy(begin(first), end(first), std::back_inserter(accumulator));
      implementation(accumulator, rest...);
    }
    
    // Interface, hiding the creation of the accumulator being fed to the
    // template-recursive implementation.
    template<class ... REST>
    std::vector<int> concatenate(const std::initializer_list<REST>& ... rest) {
      std::list<int> accumulator;
      implementation(accumulator, rest...);
      return std::vector<int>(begin(accumulator), end(accumulator));
    }
    
    template<class SEQ>
    void show_contents(const SEQ& s) {
      std::copy(begin(s), end(s), std::ostream_iterator<int>(std::cout, " "));
      std::cout << std::endl;
    }
    
    int main() {
    
      show_contents(concatenate({1,2}, {3,4,5}, {6,7}));
      show_contents(concatenate({8,9}));
      show_contents(concatenate({9,8,7}, {6,5}, {4,3}, {2,1}));
    
    }
    

    【讨论】:

    • 所以递归函数是一个好方法,但我想同时处理数组。就像将所有数组按递增顺序合并到一个数组中。
    【解决方案3】:

    如果所有参数的类型相同,您可以传递std::vector

    void xyz(std::vector<int>& parameters)
    {
      //...
    }
    

    在您的示例中,看起来每个参数可能有不同数量的数字。
    这可以通过使用std::vector&lt; std::vector&lt; int&gt; &gt; 来处理:

    void abc(std::vector< std::vector< int> >& parameters)
    {
      // Each slot of the outer vector is denoted by your {...} syntax.
      std::vector<int>& parameter2 = parameters[1];
    
      // Each number within {...} is represented by a vector of integers
      std::cout << "{"
                << parameter2[0] << ", "
                << parameter2[1] << ", "
                << parameter2[2]
                << "}\n";
    }
    

    编辑1:传递参数

    您可以将数字放入变量中并将变量传递给函数:

    int main(void)
    {
      // Load up the individual parameters.
      std::vector<int> p1 = {1};
      std::vector<int> p2 = {2, 3};
      std::vector<int> p3 = {5, 6, 7};
    
      // Place all parameters into one container
      std::vector< std::vector< int > > parameters = {p1, p2, p3};
    
      // Call the function with the parameters
      abc(parameters);
    
      return 0;
    }
    

    【讨论】:

    • 那么我将如何传递参数?我可以写 abc({1},{2,3},{5,6,7});
    • 能否在调用函数之前将数字放入数据结构或向量中?
    • 见我的编辑1,加载参数和调用函数的例子。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-08-22
    • 1970-01-01
    • 2012-01-06
    • 2012-09-22
    • 1970-01-01
    • 1970-01-01
    • 2022-01-26
    相关资源
    最近更新 更多