Передача массивов в качестве параметров



При использовании массивов в качестве параметра в функцию передается указатель (адрес) на его первый элемент. Таким образом, массив всегда передается по адресу. Помимо собственно массива в функцию надо передавать и фактическое количество элементов массива. Формальный параметр функции, являющийся массивом, можно объявлять как тип элементов *a или как тип элементов  a[]. Первая форма в явном виде выражает тот факт, что параметр является указателем, а вторая форма более наглядно показывает, что параметр является массивом. Во втором случае нет необходимости указывать количество элементов, т.к. в соответствии с указанным типом элементов транслятор сам вычисляет адрес каждого элемента массива, а на программисте лежит ответственность обрабатывать столько элементов, сколько их фактически хранится в массиве.

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

// запоминание отрицательных элементов

 

#include "stdafx.h"

#include "stdio.h"

#include "conio.h"

 

void soxran(float *a,int n,float b[],int *k);

int _tmain(int argc, _TCHAR* argv[])

{ const int nn=25;

float a[nn],b[nn];

int m,l;

printf("wwedite kol-wo elementow\n");

scanf("%d",&m);

printf("\n wwedite elementi massiwa\n");

for (int i=0;i<m;i++)

scanf("%f",&a[i]);

soxran(a,m,b,&l);

if (l==0) printf("\notrizatelnix elementow net");

else

{printf("\n massiw otrizatelnix:\n");

for (int i=0;i<l;i++)

printf("%6.2f ",b[i]);

}

getch();

return 0;

}

void soxran(float *a,int n,float b[],int *k)

{*k=0;

 for(int i=0;i<n;i++)

 if (a[i]<0)

 {b[*k]=a[i];

(*k)++;

 }

}

При передаче многомерных массивов в функцию можно использовать вторую форму объявления формального параметра массива, но при этом необходимо указывать количество элементов по каждому измерению, начиная со второго (для первого измерения это делать не обязательно). Количество элементов при этом лучше задавать с помощью глобальной константы, так как в этом случае при изменении максимального количества элементов достаточно будет изменить значение этой константы, располагаемой в начале программы, и не надо вносить изменения в другие места программы. Это улучшает стиль программирования. Например,

const int mm=10,nn=20;

void f1(float a[][mm][nn],int k,int l, int m, float *s);

В качестве примера приведем функцию вычисления суммы элементов трехмерного массива.

// передача в функцию трехмерного массива

#include "stdafx.h"

#include "stdio.h"

#include "conio.h"

const int nn=5,ll=12;

void sum(float a[][ll][nn],int m,int l,int n,float *s);

int _tmain(int argc, _TCHAR* argv[])

{ const int mm=15;

float a[mm][ll][nn],s;

int m,l,n;

printf("wwedite kol-wo elementow po trem ismerenijam\n");

scanf("%d%d%d",&m,&l,&n);

printf("\n wwedite elementi massiwa\n");

for (int i=0;i<m;i++)

 for (int j=0;j<l;j++)

  for (int k=0;k<n;k++)

scanf("%f",&a[i][j][k]);

sum(a,m,l,n,&s);

printf("\n summa=%6.2f",s);

getch();

return 0;

}

void sum(float a[][ll][nn],int m,int l,int n,float *s)

{*s=0;

 for(int i=0;i<m;i++)

for(int j=0;j<l;j++)

for(int k=0;k<n;k++)

   (*s)+=a[i][j][k]; 

}

 

Объявить формальный параметр - двумерный массив можно и так:

void f2(float (*a)[nn],…);

В приведенном объявлении функции f2 сообщается, что первый параметр является указателем на массив из nn элементов (nn – заранее объявленная глобальная константа). Скобки в этой записи обязательны, так как без скобок запись float *a[nn] означает массив из nn указателей. В этом случае фактически работа ведется с указателем на строку матрицы с известным заранее количеством элементов в строке, что также позволяет транслятору правильно вычислять адреса элементов матрицы. Приводимая программа вычисляет среднее арифметическое всех элементов матрицы и среднее геометрическое модулей ее элементов.

// формальный параметр - указатель на массив

#include "stdafx.h"

#include "stdio.h"

#include "conio.h"

#include "math.h"

 

const int nn=12;

void sum(float (*a)[nn],int m,int n,float *sr,float *sg);

int _tmain(int argc, _TCHAR* argv[])

{ const int mm=15;

float a[mm][nn],sa,sg;

int m,n;

printf("wwedite kol-wo elementow po dwum ismerenijam\n");

scanf("%d%d",&m,&n);

printf("\n wwedite elementi matrizi\n");

for (int i=0;i<m;i++)

for (int j=0;j<n;j++)

scanf("%f",&a[i][j]);

sum(a,m,n,&sa,&sg);

printf("\n srednee arifm=%6.2f srednee geom=%6.2f",sa,sg);

getch();

return 0;

}

void sum(float (*a)[nn],int m,int n,float *sr,float *sg)

{*sr=0;

 *sg=1;

 for(int i=0;i<m;i++)

for(int j=0;j<n;j++)

{(*sr)+=a[i][j]; 

  (*sg)*=a[i][j];

}

(*sr)/=(m*n);

*sg=pow(fabs(*sg),(float)1/(m*n));

}

 

Третий вариант объявления формального параметра – многомерного массива состоит в том, что используется фактический способ размещения элементов массива в памяти ЭВМ. Поскольку память ЭВМ – линейная структура, то все элементы многомерных массивов хранятся подряд друг за другом. (Массив с любым количеством измерений представляется как одномерный.) Программист в этом случае должен сам в программе организовать вычисление адреса элемента массива. При этом необходимо знать способ хранения массивов при использовании конкретного языка программирования. Язык C предусматривает, что элементы массивов хранятся таким образом, что быстрее всего изменяется последний индекс элементов (в частности, матрицы хранятся по строкам).

Для вычисления адреса элемента матрицы надо знать индексы элемента, а также максимальное количество элементов в строке (количество столбцов, заданное при объявлении массива.

Индекс элемента матрицы с индексами i и j в одномерном массиве, например,
int a[1000], вычисляется по формуле i*nmax+j, где nmax -максимальное количество столбцов матрицы, а его адрес будет равен a+i*nmax+j.

В примере находится сумма двух матриц.

//нахождение суммы двух матриц

//матрица рассматривается как одномерный массив

#include "stdafx.h"

#include "stdio.h"

#include "conio.h"

#include "math.h"

 

void summatr(float *a,float *b,float *c,int m,int n,int nn);

void pech(float *a,int m,int n,int nn);

int _tmain(int argc, _TCHAR* argv[])

{ const int mm=15,nn=12;

float a[mm][nn],b[mm][nn],c[mm][nn];

int m,n;

printf("wwedite kol-wo elementow po dwum ismerenijam\n");

scanf("%d%d",&m,&n);

printf("\n wwedite elementi matrizi A \n");

for (int i=0;i<m;i++)

for (int j=0;j<n;j++)

scanf("%f",&a[i][j]);

printf("\n wwedite elementi matrizi B \n");

for (int i=0;i<m;i++)

for (int j=0;j<n;j++)

scanf("%f",&b[i][j]);

summatr(&a[0][0],&b[0][0],&c[0][0],m,n,nn);

printf("\n matriza A\n");

pech(&a[0][0],m,n,nn);

printf("\n matriza B\n");

pech(&b[0][0],m,n,nn);

printf("\n matriza C\n");

pech(&c[0][0],m,n,nn);

getch();

return 0;

}

void summatr(float *a,float *b,float *c,int m,int n,int nn)

{

 for(int i=0;i<m;i++)

for(int j=0;j<n;j++)

c[i*nn+j]=a[i*nn+j]+b[i*nn+j]; 

}

void pech(float *a,int m,int n,int nn)

{ for(int i=0;i<m;i++)

{for(int j=0;j<n;j++)

   printf("%6.2f ",a[i*nn+j]); 

printf("\n");

}

}

В последнем случае, когда внутри функции работа с матрицей производится как с одномерным массивом, отпадает необходимость объявления глобальной константы, задающей максимальное количество столбцов матрицы. Фактическое количество строк, столбцов матрицы и максимальное количество столбцов матрицы передаются в функцию через список параметров, что повышает независимость функции и улучшает стиль программирования.

Можно предложить еще один способ объявления формальных параметров - массивов, предусматривающий использование оператора typedef (см. [2] раздел 5.5).. С его помощью вводится в рассмотрение новый тип данных – двумерный массив. Причем можно объявить матрицу сразу как двумерный массив, а можно объявить как одномерный массив, состоящий из одномерных массивов. Следующая программа демонстрирует способ объявления типа двумерного массива с использованием оператора typedef. Здесь требуется объявить две глобальные константы, задающие максимальное количество строк и столбцов. Программа с помощью функции умножает каждый элемент матрицы на дробную часть элемента.

//умножение элементов матрицы на дробную часть

#include "stdafx.h"

#include "stdio.h"

#include "conio.h"

const int mmax=12, nmax=14;

typedef float tmatr[mmax][nmax];

void fun(tmatr a,int m,int n);

 

int _tmain(int argc, _TCHAR* argv[])

{

tmatr b;

int m,n;

printf("wwedite rasmeri m i n");

scanf("%d%d",&m,&n);

printf("\n wwedite matrizu \n");

for (int i=0;i<m;i++)

for (int j=0;j<n;j++)

  scanf("%f",&b[i][j]);

printf("\n matriza\n");

for (int i=0;i<m;i++)

{

for (int j=0;j<n;j++)

  printf("%6.2f ",b[i][j]);

printf("\n");

}

fun(b,m,n);

printf("\n matriza\n");

for (int i=0;i<m;i++)

{

for (int j=0;j<n;j++)

  printf("%6.2f ",b[i][j]);

printf("\n");

}

getch();

return 0;

}

void fun(tmatr a,int m,int n)

{for (int i=0;i<m;i++)

for (int j=0;j<n;j++)

a[i][j]*=(a[i][j]-(int)a[i][j]);

}

 

Объявление типа двумерного массива tmatr как одномерного, состоящего из одномерных массивов типа tv, можно выполнить так:

typedef float tv[nmax];

typedef tv tmatr[mmax];

Примеры выполнения заданий

Пример 1.Составить функцию, копирующую из матрицы A(m,n), m≤10, n≤14 положительные элементы в массив Pol и подсчитывающую их количество kPol, а отрицательные элементы – в массив Otr и подсчитывающую их количество kOtr. Использовать эту функцию для матрицы В в основной программе. Если окажется, что положительных и/или отрицательных элементов в матрице нет, то вывести соответствующие сообщения, иначе – скопированные в массивы данные.

// формирование массива положительных и массива отрицательных

// элементов матрицы

#include "stdafx.h"

#include "stdio.h"

#include "conio.h"

 

const int nmax=14;

 void polotr(float a[][nmax],int m,int n,float pol[],float otr[],int *kpol,int *kotr);

int _tmain(int argc, _TCHAR* argv[])

{

 const int mmax=10;

 float b[mmax][nmax],pol[mmax*nmax],otr[mmax*nmax];

 int i,j,m,n,kpol,kotr;

printf("wwedite kol-wo strok i stolbzow\n");

scanf("%d%d",&m,&n);

printf("\nwweditr matrizu\n");

for (i=0;i<m;i++)

for (j=0;j<n; j++)

        scanf("%f",&b[i][j]);

printf("\nIsxodnaja matriza\n");

for (i=0;i<m;i++)

{

for (j=0;j<n; j++)

        printf("%5.1f ",b[i][j]);

 printf("\n");

}

polotr(b,m,n,pol,otr,&kpol,&kotr);

if (kpol>0)

{

printf("\nMassiw poloshitelnix\n");

for (i=0; i<kpol;i++)

  printf("%5.1f ",pol[i]);

printf("\n");

}

else printf("\nPoloshitelnix elementow net\n");

if (kotr>0)

{printf("\nMassiw otrizatelnix\n");

for (i=0; i<kotr;i++)

  printf("%5.1f ",otr[i]);

printf("\n");

}

else printf("\nOtrizatelnix elementow net\n");

getch(); 

 return 0;

}

void polotr(float a[][nmax],int m,int n,float pol[],float otr[],int *kpol,int *kotr)

{int i,j;

*kpol=0;

*kotr=0;

for (i=0;i<m;i++)

for (j=0; j<n; j++)

  if (a[i][j]>0) 

{

    pol[*kpol]=a[i][j];

    (*kpol)++;

}

   else if (a[i][j]<0) 

{

    otr[*kotr]=a[i][j];

    (*kotr)++;

}

 }

Пример 2. Составить и использовать функцию, возвращающую максимальный из первых N элементов массива X(N), N≤100.

// функция определения иаксимального элемента массива

#include "stdafx.h"

#include "stdio.h"

#include "conio.h"

 

float maxmas(int n, const float x[]);

int _tmain(int argc, _TCHAR* argv[])

{ const int mm=100;

float y[mm];

int n,i;

printf("\n wwedite kol-wo elementow\n");

scanf("%d",&n);

printf("wwedite elementi massiwa\n");

for (i=0;i<n;i++)

scanf("%f",&y[i]);

 //Вызов функции в функции вывода

printf("\nMaksimalnij is n=%3d elementow rawen %5.1f",n,maxmas(n,y));

getch();

return 0;

}

float maxmas(int n, const float x[])

{int i;

 float max;

max=x[0];

for (i=1; i<n;i++)

if (x[i]>max)

  max=x[i];

return max;

}

Пример 3. Составить программу поиска приближенных значений корней уравнения

и их уточнённых значений методом половинного деления.

В данном примере использование функций позволяет не только сделать текст программы более удобным для понимания её алгоритма, но и уменьшить его при необходимости повторных вычислений в разных частях программы.

//уточнение корней уравнения

#include "stdafx.h"

#include "stdio.h"

#include "conio.h"

#include "math.h"

 

double f_px(double p,double x);

double koren_f(double p,double x0,double x1,double eps);

 

int _tmain(int argc, _TCHAR* argv[])

{ double p,x, a, b, dx, f0, f1,eps,koren;

printf("Wwedite granizi interwala i schag argumenta\n");

scanf("%lf%lf%lf",&a,&b,&dx);

printf("\nWwedite parametr p\n");

scanf("%lf",&p);

printf("\nWwedite tochnost\n");

scanf("%lf",&eps);

f0=f_px(p,a);

dx=0.01;

x=a+dx;

while (x<b+dx/2)

{

f1=f_px(p,x);

if (f0*f1<0) 

 {

  //Найдены приближенные значения корня

  //X-dX - приближение, меньшее корня

  //X - приближение, большее корня

  printf("\nx-dX = %8.4f - lewoe priblishenie kornja\n",x-dx);

  //Поиск приближения с точностью Eps

  koren = koren_f(p,x-dx,x,eps);

  //Вывод результатов

  printf("Koren=%8.4f s tochtostju=%8.4f\n",koren,eps);

  printf("Snachenie funkcii w korne=%8.4f\n",f_px(p,koren));

 }

f0=f1;

x+=dx;

}

getch();

return 0;

}

 //Функция, вычисляющая выражение,

 //входящее в уравнение

 double f_px(double p,double x)

 {double px,f;

px=p*x;

f=x*cos(3*px)/p/12-sin(3*px)/p/p/36

   -3*x*cos(px)/p/4 +3*sin(px)/p/p/4;

return f;

 }

 

 //функция, уточняющая значение корня

double koren_f(double p,double x0,double x1,double eps)

{double f0,f,f1,x;

f0=f_px(p,x0);

do

{x=(x0+x1)/2;

f=f_px(p,x);

if (f0*f>0)

  x0=x;

else

  x1=x;

 }

while(fabs(x1-x0)>eps);

return x;

 }

Пример 4. Составить функцию для вычисления среднего арифметического элементов одномерного массива. Использовать эту функцию для формирования массива средних арифметических значений элементов каждой строки матрицы A(m,n), m≤12, n≤11.

В данном примере рассматривается два способа передачи строки матрицы в функцию. Можно переписать элементы очередной строки матрицы в одномерный массив и уже его передать в качестве фактического параметра в функцию. Можно решить эту задачу более изящно. Поскольку при работе с матрицей элемент a[i] представляет собой указатель (адрес) на i-ую строку матрицы, то в качестве фактического параметра в функцию удобнее передавать как раз этот адрес.

// функция вычисления среднего арифметического одномерного массива

// передача в функцию строки матрицы

#include "stdafx.h"

#include "stdio.h"

#include "conio.h"

#include "math.h"

 

float sred(const float b[],int n);

int _tmain(int argc, _TCHAR* argv[])

{

 const int mmax=12, nmax=11;

 float a[mmax][nmax], //Массив исходной матрицы

     sredstrka[mmax], //Массив средних значений

                        //строк матрицы

     b[nmax]; //массив элементов строки матрицы (первый вариант)

 int m,n,i,j;

printf("wwedite kol-wo strok i stolbzow\n");

scanf("%d%d",&m,&n);

printf("\nwwedite matrizu\n");

for (i=0;i<m;i++)

for (j=0; j<n;j++)

scanf("%f",&a[i][j]);

//Вычисление средних арифметических

//значений в строках матрицы

for (i=0;i<mmax;i++)

//Обращение к функции

sredstrka[i]=sred(a[i],n);

/* первый вариант – перепись элементов строки в массив

for (i=0;i<m;i++)

{for (j=0;j<n;j++)

   b[j]=a[i][j];

sredstrka[i]=sred(b,n);

 

*/

//Вывод матрицы по строкам и правее

//каждой строки - её среднего арифметического

printf("\nisxodnaja matriza i srednie arifmeticheskie\n");

for (i=0; i<m;i++)

{

for (j=0; j<n;j++)

printf("%6.1f ",a[i][j]);

printf(" %6.1f\n",sredstrka[i]);

getch();

return 0;

}

 //Функция вычисления среднего арифметического

 //элементов одномерного массива

 float sred(const float b[],int n)

 {

int i;                 

float s=0;                    

for (i=0;i<n;i++)             

s+=b[i];   

return s/n;      

 }

Можно поставленную задачу решить и по-другому, если функция должна работать непосредственно с матрицей. Функция в этом случае возвращает сразу сформированный массив средних арифметических.

// функция вычисления среднего арифметического одномерного массива

// передача в функцию всей матрицы и формирование массива средних

 

#include "stdafx.h"

#include "stdio.h"

#include "conio.h"

#include "math.h"

const int nmax=11;

void sred(const float b[][nmax], float sred[],int m,int n);

 

int _tmain(int argc, _TCHAR* argv[])

{

 const int mmax=12;

 float a[mmax][nmax], //Массив исходной матрицы

     sredstrka[mmax]; //Массив средних значений

                      //строк матрицы

 int m,n,i,j;

printf("wwedite kol-wo strok i stolbzow\n");

scanf("%d%d",&m,&n);

printf("\nwwedite matrizu\n");

for (i=0;i<m;i++)

for (j=0; j<n;j++)

scanf("%f",&a[i][j]);

//Вычисление средних арифметических

//значений в строках матрицы

//Обращение к функции

sred(a,sredstrka,m,n);

//Вывод матрицы по строкам и правее

//каждой строки - её среднего арифметического

 

printf("\nisxodnaja matriza i srednie arifmeticheskie\n");

for (i=0; i<m;i++)

{

 for (j=0; j<n;j++)

printf("%6.1f ",a[i][j]);

printf(" %6.1f\n",sredstrka[i]);

getch();

return 0;

}

 //Функция вычисления среднего арифметического

 //элементов одномерного массива

 void sred(const float b[][nmax], float sred[],int m,int n)

 {

int i,j;               

float s;                      

for (i=0;i<m;i++)

{ s=0;

for (j=0;j<n;j++)

   s+=b[i][j];    

sred[i]= s/n;   

}

 }

 


Дата добавления: 2018-10-27; просмотров: 640; Мы поможем в написании вашей работы!

Поделиться с друзьями:






Мы поможем в написании ваших работ!