Как передать количество элементов массива в функцию - PullRequest
0 голосов
/ 06 апреля 2019

Я бы хотел передать n количество элементов массива в функцию, чтобы вычислить среднее значение. По сути, я бы хотел, чтобы количество элементов в коде было динамическим, чтобы можно было ввести произвольное число.

float average(float num[]); 

int main() 
{ 
  int n,i,k; 
  float num[n]; 
  printf("Enter the numbers of elements: "); 
  scanf("%d",&k);
  for(i = 0; i < k; ++i)
  {
    printf("%d. value: ", i+1);
    scanf("%f", &num[i]);
  }
  printf("Average = %.2lf",average(num)); 
  return 0;
}

float average(float num[])
{
  int i,n;
  float sum = 0.0, avg;
  n = sizeof(num)/sizeof(int);

  for(i = 0; i < n; ++i)
  {
    sum += num[i];
  }
  avg = sum / n;
  return avg;
}

n = sizeof(num)/sizeof(int); почему-то не передает правильное количество элементов. Я пытался копаться в Интернете и пробовал разные варианты, но, похоже, ничего не работает правильно. Я предполагаю, что это потому, что я не передаю массив функции правильно ... но не знаю, как, пожалуйста, посоветуйте большое спасибо

Ответы [ 2 ]

2 голосов
/ 06 апреля 2019

Когда вы передаете массив как параметр функции в C, он «настраивается» на указатель. В C11 это § 6.7.6.3 ¶ 7:

Объявление параметра как «массива тип » должно быть скорректировано на «квалифицированный указатель на тип », где квалификаторы типа (если таковые имеются) - те, которые указаны в [ и ] деривации типа массива. Если ключевое слово static также присутствует в пределах [ и ] при выводе типа массива, то для каждого вызова функции указывается значение соответствующего фактического аргумента. должен обеспечить доступ к первому элементу массива, по крайней мере, с таким количеством элементов, как указано в выражении размера.

Тем не менее, вы можете сообщить компилятору и / или дополнительным инструментам (например, инструментам статического анализа), что другой параметр несет длину, но этот параметр должен прийти перед параметром массива. Это хорошая практика, чтобы войти в; см. API05-C в стандарте кодирования SEI CERT C для получения дополнительной информации.

Проблема в том, что компиляторы вроде как отстой. Во-первых, параметры согласованного массива разрешены только в C ≥ C99, поэтому, если предполагается, что ваш код строго C89 или что-то еще, они не будут работать.

Несмотря на то, что параметры согласованного массива (по сомнению) не являются массивами переменной длины , большинство компиляторов в основном воспринимают их как таковые, а поддержка компиляторов для VLA довольно нечеткая; C11 даже делает поддержку VLA необязательной. MSVC не реализует их вообще. GCC и Clang (по крайней мере) будут предупреждать, если вы используете их с включенным -Wvla. В PGI есть ошибка, которая приводит к сбою компиляции. IAR также обрабатывает их как VLA и выдает предупреждение, если вы не включаете массивы переменной длины (поддержка отключена по умолчанию, но есть переключатель командной строки для их включения). Tiny C Compiler также выдает ошибку; IIRC, потому что он также считает их VLA.

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

Независимо от того, хотите ли вы использовать соответствующие параметры массива, вам нужно изменить свой код. Вы можете передать массивы как два аргумента или создать тип, который инкапсулирует как длину, так и массив ... два аргумента - определенно идиоматическое решение. Так что для вашего прототипа вы получите что-то вроде

// No conformant array parameters, just another parameter
float average(size_t n, float num[]);
// CAP
float average(size_t n, float num[n]);
// CAP with a macro
float average(size_t n, float num[ARRAY_PARAM(n)]);

sizeof(num) все равно будет равно sizeof(float*) (поскольку это то, что есть), но, по крайней мере, вы знаете, сколько элементов в массиве.

1 голос
/ 06 апреля 2019

In main

  float num[n]; 

необходимо переместить, поскольку n не инициализировано, поэтому:

 int n,i,k; 
 float num[n]; 
 printf("Enter the numbers of elements: "); 
 scanf("%d",&k);

должно быть похоже на

 int i,k; 

 printf("Enter the numbers of elements: "); 
 if (scanf("%d",&k) != 1) {
   puts("invalid size");
   return -1;
 }
 float num[k]; 

В в среднем :

n = sizeof(num)/sizeof(int);

неверно, потому что число элементов в num неизвестно, поэтому sizeof(num) определяет размер указателя, вам нужно указать номер элемента в параметре

 float average(float num[], int n); 

и основной

printf("Average = %.2lf",average(num, k)); 

и

float average(float num[], int n)
{
  int i;
  float sum = 0.0;

  for(i = 0; i < n; ++i)
  {
    sum += num[i];
  }

  return sum / n;
}
...