Альтернативный метод вызова этой функции Variadic

Я написал функцию с переменным числом аргументов, которая принимает в качестве первого аргумента число N, а в качестве следующих N аргументов принимает N переменных типа double. Кроме того, эта функция возвращает сумму этих N переменных.

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

double foo(int arg_count, ...)
{
      va_list ap;

      int i;
      double sum = 0;

      va_start(ap, arg_count);

      for (i = 0; i < arg_count; i++) {
          sum += va_arg(ap, double);
      }

      va_end(ap);

      return sum;
}

int main(void)
{
    int n, i;
    double *p, rez;

    printf("N= ");
    scanf("%d", &n);

    p = (double *) calloc(n, sizeof(double));
    if (p == NULL) {
       exit(EXIT_FAILURE);
    }

    for (i = 0; i < n; i++) {
        printf("p[%d]= ", i);
        scanf("%lf", &p[i]);
    }

    printf("\n%lf\n", (rez = foo(n, p[0], p[1], p[2])));

    free(p);

    return 0;
}

Однако эта программа, например, возвращает только сумму первых трех элементов double *p, независимо от значения N (которое содержится в int n).

Если я хочу, чтобы он возвращал сумму, скажем, первых 10 элементов, мне пришлось бы переписать приведенный выше код...

printf("\n%lf\n", (rez = foo(n, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7], p[8], p[9])));

Есть ли более разумный способ сделать это?


person Patrick Seres    schedule 15.05.2014    source источник
comment
Используйте связанный список или массив.   -  person Chnossos    schedule 15.05.2014
comment
Распространенные способы сделать это — также добавить магический терминатор (если передаются указатели, это NULL (может быть, попробовать DBL_MAX?). См. семейство функций execv для примеров различных способов, которыми это делается.   -  person Mark Nunberg    schedule 15.05.2014


Ответы (2)


Разрешить как вариационную версию, так и версию массива.

Посмотрите реализацию execl и execv.

execl принимает аргументы с переменным числом аргументов, оканчивающиеся на NULL, а execv принимает массив аргументов (оканчивающихся указателем NULL).

Это можно распространить на ваш пример.

fool(n, p[0], p[1], p[2]);

а также

foov(n, p);

но вместо окончания NULL вы используете n для указания количества аргументов.

person Jeffery Thomas    schedule 15.05.2014

Используйте обычную функцию и передайте массив в качестве аргумента.

double foo(int arg_count, double p[])
{
      int i;
      double sum = 0;

      for (i = 0; i < arg_count; i++) {
          sum += p[i];
      }

      return sum;
}


double sum1 = foo(3, p);
// Sum of the first 3 elements.

double sum2 = foo(10, p);
// Sum of the first 10 elements.
person R Sahu    schedule 15.05.2014