АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомДругоеЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция

Тема 8. Использование указателей при обработке одномерных и двумерных массивов

Читайте также:
  1. А) ИСПОЛЬЗОВАНИЕ КАТЕГОРИИ ВИДА В РУССКОМ ЯЗЫКЕ
  2. Административная ответственность за нарушения прав на использование информацией
  3. Влияние легирования на превращения при термообработке
  4. Вопрос 5.4. Распределение и использование прибыли на предприятии.
  5. Выбор максимального из трёх чисел с использованием подпрограммы–функции выбора максимума из двух чисел.
  6. Г) ИСПОЛЬЗОВАНИЕ МОРФОЛОГИЧЕСКИХ СРЕДСТВ ЯЗЫКА
  7. Глава 10. Расстройства, вызванные использованием психоактивных веществ.
  8. Глава 13. ИСПОЛЬЗОВАНИЕ ЗАРУБЕЖНОГО ОПЫТА БАНКРОТСТВА И ЛИКВИДАЦИИ БАНКОВ
  9. Глава 2. Использование слов и мысленных образов
  10. Государственный земельный кадастр и его использование для решения экологических задач
  11. Графический метод с использованием характеристик для мгновенных значений
  12. Диверсификация, использование кредита и отношение задолженности к собственному капиталу

Массивы и указатели. При описании массивов указываются тип данных и требуемый класс памяти. К массивам, как и в случае простых переменных, применяется тот же принцип умолчания. Рассмотрим примеры описаний массивов:

int b[30]; /*внешний массив из 30 целых элементов*/

float a[30]; /*автоматический массив из 30 чисел типа float*/

static char c[20]; /*статический массив из 20 символов*/

extern b[ ]; /*внешний массив; размер указан выше*/

}

В зависимости от класса памяти различают внешние, статические, автоматические и регистровые массивы. Рассмотрим инициализацию массивов. В описании типа можно инициализировать только внешние и статические массивы. Описание внешних и статических массивов предполагает по умолчанию обнуление элементов этих массивов.(Итак, для обнуления статического и внешнего массива ничего предпринимать не нужно). Рассмотрим пример инициализации внешнего массива, значениями элементов массива будет количество студентов в каждой группе потока:

int stud[10]={10,12,14,16,12,10,17,10,15,13};

main()

{ int i;

extern int stud{ }; /*необязательное описание*/

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

printf(“Группа N %d %d студентов”, i+1, stud[i]); }

Массив stud[10] инициировали списком, заключенным в скобки, используя при этом запятые для разделения элементов списка. Количество элементов в списке должно соответствовать размеру массива. Если элементов в списке меньше размера массива, то оставшиеся элементы массива будут иметь нулевые значения. Если элементов в списке больше, будет сообщение об ошибке.

Инициализацию элементов массива можно осуществить и в следующем виде:

int stud[ ]={10,12,15,16,17,11,18,10};

main ()

{ int i;

extern int stud [ ];

for (i=0; i<sizeof stud/(sizeof(int)); i++)

printf (“Группа N %d %d студентов.\n”,i+1,stud[i]); }

Если для инициализации массива используются пустые кнопки, то компилятор сам определяет количество элементов в списке и выделит для него массив нужного размера. При определении размера массива используется оператор sizeof. Оператор sizeof определяет размер в байтах объекта или типа. Следующего за ним. Для получения количества элементов массива общее число байтов, занимаемое массивом, делится на 2 (в данной системе размер каждого элемента типа int равен 2 байтам). В общем случае делится на значение переменной sizeof соответствующего типа.

Указатели массивов. Ранее было отмечено, что указатели позволяют организовать работу с символическими адресами. (В этом случае обработка массива будет организована более эффективно). Обозначение массива представляет собой скрытую форму использования указателей.

Например, имя массива определяет также последний элемент, т.е. если a[ ] массив, то последний a[0].

Оба значения являются константами типа указатель, т.к. они не изменяются на протяжении всей программы. Их можно присваивать (как значения) переменной типа указатель и изменять значение переменной. Рассмотрим пример, в котором к значению указателя прибавляется число:

{ int a[4], *pti, i;

float b[4], *ptf;

pti=a; /*присваивает адрес указателю массива*/

ptf=b;

for (i=0, i<4,i++)

printf(“Указатели +%d: %8u %10u\n”, i, pti+i, ptf+i); }

Результат:

указатель +0: 56014 56026 (начальные адреса массивов)

указатель +1: 56016 56030 (результат прибавления единицы к адресу)

указатель +2: 56018 56034

указатель +3: 56020 56038

Единицей адресации является байт, но тип int использует 2 байта, а тип float – 4 байта.

«Прибавить единицу к указателю» - компилятор добавит единицу памяти. Для массива это означает, что происходит переход к адресу следующего элемента, а не следующего байта. Вот почему специально оговаривается тип объекта, на который ссылается указатель.

Рассмотрим следующие равенства:

a+2==&a[2]; /*один и тот же адрес*/

*(a+2)==a[2]; /*одно и то же значение*/

Эти соотношения показывают связь между массивами и указателями, т.е. можно использовать указатель для определения отдельного элемента массива, а также для получения его значения.

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

Использование указателей при работе с массивами. Напишем функцию, использующую массивы, а затем перепишем ее, применяя указатели.

int func(a, l)

int a[ ], l;

{ int i, sum;

for (i=0, sum=0; i<l; i++)

if (a[i]%2!=0)

sum+=a[i];

return (sum); }

for (i=0,sum=0;i<l; i++)

sum+=a[i];

return ((int) (sum/l)); }

Оператор вызова в вызывающей программе может выглядеть следующим образом:

func(x, size);

Перепишем функцию с использованием указателей. Объявим pа указателем на тип int. Затем заменим элемент массива a[i] на соответствующее значение: *(pa+i).

int func(pa, l)

int *pa, l;

{ int i, sum;

for (i=0, sum=0; i<l; i++)

sum+=*(pa+i);

return ((int) (sum/l));

}

for (i=0, sum=0; i<l; i++)

if (*(pa+i)%2!=0)

sum+=*(pa+i);

return (sum); }

Вызов функции остается в том же виде:

func(x, size)/

Т.к. имя массива является указателем, отметим, что следующие операторы описания идентичны по действию: оба объявляют ра указателем:

int pa[ ]; и int *pa;

В программе можно применять любой из них, хотя до сих пор мы использовали второй в виде *(pa+i).

Использование указателей при работе с двумерными массивами. Рассмотрим массив a[3][2].

int a[3][2]; /* массив типа int из 3 строк и 2 столбцов */

int *pri; /* указатель на целый тип */

pri=a; /* указатель указывает на элемент a[0][0] */

a==&a[0][0]; /* pri+1 указывает на a[0][1] */

Т.обр. в нашем примере:

pri==&a[0][0]; /* 1-я строка, 1 столбец */

pri+1==&a[0][1]; /* 1-я строка, 2 столбец */

pri+2==&a[1][0]; /* 2-я строка, 1 столбец */

pri+3==&a[1][1]; /* 2-я строка, 2 столбец */

pri+4==&a[2][0]; /* 3-я строка, 1 столбец */

pri+5==&a[2][1]; /* 3-я строка, 2 столбец */

Двумерный массив представлен как массив массивов, т.е. можно рассмотреть 3 строки, каждая из которых является массивом из двух элементов. Имя первой строки a[0], второй – a[1], третьей – a[2]. Имя массива является указателем на этот массив, т.е. ссылается на первый его элемент. Значит

a[ 0]==&a[0][0]

a[ 1]==&a[1][0]

a[ 2]==&a[2][0].

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

main()

{ static int b[3][4]={{6,4,8,10},

{10,20,30,40},

{20,40,60,80}};

int i;

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

printf(“Среднее значение строки %d равно %d\n”, i, func(b[i], 4));

/*b[i] – одномерный массив из 4 элементов*/

}

/*нахождение среднего значения в одномерном массиве*/

int func(x, n)

int x[ ],n;

{ int l;

float s;

for (l=0, s=0; l<n; l++)

s+=x[l];

return ((int) (s/n)); }

Для того, чтобы описать функцию, работающую с двумерным массивом, причем со всем целиком, а не с частями, необходимо правильно записать определение функции и ее описание. Пусть функция main() выглядит так:

main()

{ static int b[3][4]={{6,4,8,10},

{10,20,30,40},

{20,40,60,80}};

sr(b); }

Приведем заголовок функции sr(b):

sr(b)

int b[ ][4];

int mult (int b[ ][4], int m)

{ int i, j; p=1;

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

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

if (b[i][j]!=0) p=p*b[i][j]; }

Рассмотрим еще один способ:

Дан массив b[5,4]. Можно привести такое описание:

mult (int a[ ], int size)

Обращение к функции будет иметь вид:

mult (b, 5*4); (b будет рассматриваться как одномерный массив, содержащий 20 элементов).

 

Основная литература: 1осн[295-304], 2осн[346-370], 3осн[84-108],

Дополнительная литература: 6доп[135-190], 8доп[4-13]

Контрольные вопросы:

1. Приведите примеры инициализации различных видов массивов?

2. Что содержать указатели в качестве значения?

3. Какие три значения могут использоваться для инициализации указателя?

4. К переменным какого класса памяти не может быть применена операция взятия адреса?

5. Указателем на какой элемент массива является имя массива?


1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 |

Поиск по сайту:



Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Студалл.Орг (0.008 сек.)