C ++中的求和函数,参数和类型数量未知

Posted

技术标签:

【中文标题】C ++中的求和函数,参数和类型数量未知【英文标题】:Sum function in C++ with unknown number of arguments and types 【发布时间】:2022-01-16 00:31:53 【问题描述】:

问题的第一部分是创建一个参数数量未知的函数(Sum),我已经完成了。它工作得很好。但是我在第二部分中遇到了困难,不同类型的参数,例如:int,float,double ...在一个函数调用中。任何我可以修复我的程序的理想???

感谢您的关注。

我想很多人不明白我的问题。 我希望我的程序也可以使用不同类型的 od 参数。 例如: sum(3, int x, int y, double z)sum(4, double x, int y, float z, double t)

cout << func(sum, 5, 1.0, 2.0, 3.0, 4.0, 5.0) << endl; 正如我所料,它与 double 配合得很好。

但是

cout << func(sum, 5, 1.0, 2.0, 3, 4, 5) << endl; 不行

甚至所有数字都是整数,它仍然不能像我预期的那样工作,它返回 0

cout << func(sum, 5, 1, 2, 3, 4, 5) << endl;

double func(double (*f) (const double*, int) , int num, ...) 


  va_list arguments;

  /* Initializing arguments to store all values after num */
  va_start(arguments, num);
  /* Sum all the inputs; we still rely on the function caller to tell us how
  * many there are */

  auto *array = new double[num];

  for (int x = 0; x < num; x++) 
    double el = va_arg( arguments, double );
    array[x] = el;
  
  va_end(arguments);                  // Cleans up the list

  return f(array, num);


double sum(const double *array, int n) 
  double result = 0;

  for (int i = 0; i < n; ++i) 
      result += array[i];
  
  return result;

【问题讨论】:

如果您的目标是编写 C++ 代码,那么您将需要使用模板,顺便说一下,模板可以完成同样的事情,而不是像 va_arg 这样的 C 级黑客。你知道如何在 C++ 中使用模板吗?如果没有,那么你从哪里得到这个编程任务?这种编程任务只有在介绍了 C++ 模板的基础知识之后才会给出。 这个编程作业的教材主题是什么?通常,在课堂上介绍特定主题或主题后给出编程作业,即在解释虚拟功能如何工作后给出涉及虚拟功能的编程作业。也许对于这个编程任务,您应该学习如何使用std::common_type 主题是使用 cstdarg 库编写函数,如 sum,mean... 具有不同数量的参数,然后更改函数以使用不同类型,如 int、float、double 也(不是模板 ) 比如 sum(int a, double b), sum(int a, float b, double c)... 不,这不是编程主题。没有像这样标题的章节的 C++ 教科书。一个主题可能是虚函数、多重继承、容器、算法等……您最近在课堂上从您提到的与此编程作业相关的讲师那里学到了什么?有一个特定的模板,给定其中一种类型,生成所谓的通用类型,即 int、float -> float。这可能是预期的解决方案。也许你忘记了,如果是的话,你可以查阅你的课堂笔记。 【参考方案1】:

问题是你假设 double 作为参数,见这一行:

double el = va_arg( arguments, double );

通常的解决方案是提供传递给函数的参数格式,就像在 printf 中一样 - 但我想你不想这样做。

我可以建议你使用像这个例子中的可变参数模板:

template<typename T>
T func(T first) 
  return first;


template<typename T, typename... Args>
T func(T first, Args... args) 
  return first + func(args...);


int main() 
  std::cout << func(5, 1.0, 2.0, 3, 4, 5) << std::endl;
  std::cout << func(5, 1, 2, 3, 4, 5) << std::endl;
  return 0;

您可以将返回类型从 T 更改为 double。

【讨论】:

你能告诉我 printf 在这种情况下可以做的理想功能吗? func 会像我传入的第一个参数一样返回值吗?我想要更通用的,第一个参数是我将传递给函数以计算总和的元素数 C 风格的 printf 采用格式字符串来指定每个参数的类型。所以你的解决方案是: func(sum, "%d%f%f%d", 1, 2.0f, 3.0f, 4);因此,您必须迭代格式以了解每个参数是什么类型 - 对于 %d,您可以将 va_arg 与 int 一起使用,对于 %f va_arg 与 float 等。丑陋且容易出错。 您可以将返回类型更改为auto - 但我不确定是否保证返回参数的常见类型 - 也许有人会发布答案?至于元素的数量,你不需要这样的 sum 函数或元素的数量,求和发生在 func - + 所在的位置。 我认为这是我正在寻找的东西,非常感谢你,Marcin【参考方案2】:

作为marcinj's answer 的延续,variadic template 绝对是最简单的方法。但是,就像您提到的那样,您希望确保函数尽可能通用,所以我会这样做:

template<typename ... Args>
auto sum(Args ... args) -> std::common_type_t<int, Args...>

    return (0 + ... + args);

这里sum(Args ... args) 表示它将接受任意数量的参数,包括0个参数。

然后您可以使用尾随返回类型设置返回类型。您可以尝试这样做:

-> std::common_type_t<Args...>

但是,如果您将 0 个参数传递给 sum(),这将导致编译器错误,这就是我向其添加 int 的原因。

然后我用fold expression解包参数包,所以(0 + ... + args)就相当于:

((((0 + arg1) + arg2) + ...) + argN)

注意:尾随返回类型不是必需的,您也可以这样做:

template<typename ... Args>
std::common_type_t<int, Args...> sum(Args ... args);

对我来说它看起来更干净。

【讨论】:

【参考方案3】:

在 C++ 中,您可以使用称为模板函数的东西,它允许不同类型的变量。您可以在这里查看:C++ Function Template

这是一个例子:

template <typename T>
T add(T num1, T num2) 
   return (num1 + num2);

我建议将std::vector&lt;&gt; 传递给函数,然后使用带有vector_name.size() 的for 循环遍历每个元素并添加它们。

【讨论】:

我知道模板,但我认为它无济于事。我想添加不同数量的不同类型。像 double sum(5, int x1, double x2, int x3, float x4, double x5) 或 double sum(2, double x1, int x2) @TheHo 使用 C++ 风格的可变参数模板函数,而不是 C 风格的可变参数函数

以上是关于C ++中的求和函数,参数和类型数量未知的主要内容,如果未能解决你的问题,请参考以下文章

c语言中的类型名和形式参数名的意义是啥

在C语言中,调用函数除函数名外,还必须有()。

C语言函数定义和说明的格式

如何使 TypeScript 从数组中推断参数的数量和类型

C语言中可否定义一个函数,这个函数的形参数量可以改变?

python-函数可变参数类型