Студопедия
Случайная страница | ТОМ-1 | ТОМ-2 | ТОМ-3
АрхитектураБиологияГеографияДругоеИностранные языки
ИнформатикаИсторияКультураЛитератураМатематика
МедицинаМеханикаОбразованиеОхрана трудаПедагогика
ПолитикаПравоПрограммированиеПсихологияРелигия
СоциологияСпортСтроительствоФизикаФилософия
ФинансыХимияЭкологияЭкономикаЭлектроника

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

График выполнения и сдачи заданий по дисциплине | Типы данных в языке Си. | Использование функции printf( ) и scanf( ). | Операторы языка Си | Тема 3. Управляющие структуры. Структуры повторения While, do – While, For. Управляющие операторы break и continue. | Тема 4. Массивы. Разработка программ с использованием одномерных и двумерных массивов. | Тема 6. Классы памяти и разработка программ. | Тема 11. Структуры данных в Си. | Тема 12. Динамические структуры данных. | Тема 13. Работа с файлами в Си. |


Читайте также:
  1. VIII. Требования к обработке сырья и производству продукции
  2. VIII. Требования к обработке сырья и производству продукции
  3. Базовые пресуппозиции НЛП и использование ресурсных состояний
  4. в части, реализуемой с использованием ДОТ
  5. Валидность и использование мысленных образцов эксперимента
  6. Глава 3. Использование родителями методов поощрение и наказание в воспитании ребенка
  7. ГОРОДА МОСКВЫ С ИСПОЛЬЗОВАНИЕМ МЕТОДА CASE STUDY

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

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],

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

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

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

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

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

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

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


Дата добавления: 2015-11-04; просмотров: 99 | Нарушение авторских прав


<== предыдущая страница | следующая страница ==>
Тема 7. Указатели в Си.| Тема 9. Символы и строки в Си.

mybiblioteka.su - 2015-2024 год. (0.011 сек.)