Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лаба Алг 5 Указатели и одномерные многомерные массивы.docx
Скачиваний:
21
Добавлен:
14.03.2016
Размер:
51.07 Кб
Скачать

Лабораторная работа №5. Указатели и массивы.

Цель работы - изучение способов описания, ввода – вывода и обработки массивов, использование указателей при работе с массивами.

Методические указания для С

При выполнении задания к данной лабораторной работе необходимо в программе использовать два способа обращения к элементам массива:

  • с помощью индексов – порядковых номеров элементов в массиве (при выполнении ввода – вывода);

  • с помощью указателей (при обработке элементов массива).

Указатели

Для большинства типов T указатель на T имеет тип T*. Это значит, что переменная типа T* может хранить адрес объекта типа T. Указатели на массивы и функции, к сожалению, требуют более сложной записи:

int* pi;

char** cpp; // указатель на указатель на char

int (*vp)[10]; // указатель на массив из 10 целых

int (*fp)(char, char*); // указатель на функцию с параметрами

// char и char*, возвращающую int

Главная операция над указателями - это косвенное обращение (разыменование), т.е. обращение к объекту, на который настроен указатель. Эту операцию обычно называют просто косвенностью. Операция косвенности * является префиксной унарной операцией.

Например:

char c1 = 'a';

char* p = &c1; // p содержит адрес c1

сhar c2 = *p; // c2 = 'a'

Переменная, на которую указывает p,- это c1, а значение, которое хранится в c1, равно 'a'. Поэтому присваиваемое c2 значение *p есть 'a'. Над указателями можно выполнять и некоторые арифметические операции. Ниже в

качестве примера представлена функция, подсчитывающая число символов в строке, заканчивающейся нулевым символом (который не учитывается):

int strlen(char* p)

{

int i = 0;

while (*p++) i++;

return i;

}

Массивы

Для типа T T[size] является типом "массива из size элементов типа T". Элементы индексируются от 0 до size-1. Например:

float v[3]; // одномерный массив из трех чисел с плавающей точкой: v[0], v[1], v[2]

int a[2][5]; // двумерный массив, размером 2*5, состоящий из целых чисел

char* vpc; // массив из 32 символьных указателей

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

int mas[5,2]; // ошибка

или такое

int mas[5][2]; //правильно

int mas = v[4,1]; // ошибка

int mas = v[4][1]; // правильно

Ниже описывается массив из двух элементов, каждый из которых является, в свою очередь, массивом из 5 элементов типа char:

char v[2][5];

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

char v[2][5] = {

{ 'a', 'b', 'c', 'd', 'e' },

{ '0', '1', '2', '3', '4' }

};

В результате получим:

v[0][0]=a v[0][1]=b v[0][2]=c v[0][3]=d v[0][4]=e

v[1][0]=0 v[1][1]=1 v[1][2]=2 v[1][3]=3 v[1][4]=4

Указатели и массивы в языке Си++ тесно связаны. Имя массива можно использовать как указатель на его первый элемент.

Эта эквивалентность широко используется при вызовах функций с параметром-массивом, который всегда передается как указатель на его первый элемент.

Результат применения к указателям арифметических операций +, -, ++ или -- зависит от типа указуемых объектов. Если такая операция применяется к указателю p типа T*, то считается, что p указывает на массив объектов типа T. Тогда p+1 обозначает следующий элемент этого массива, а p-1 – предыдущий элемент. Отсюда следует, что значение (адрес) p+1 будет на sizeof(T) байтов больше, чем значение p.

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

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

void f()

{

int v1[10];

int v2[10];

int i = &v1[5]-&v1[3]; // 2

i = &v1[5]-&v2[3]; // неопределенный результат

int* p = v2+2; // p == &v2[2]

p = v2-2; // *p неопределено

}

Как правило, сложных арифметических операций с указателями не требуется и лучше всего их избегать. Следует сказать, что в большинстве реализаций языка С нет контроля над границами массивов. Описание массива не является самодостаточным, поскольку необязательно в нем будет храниться число элементов массива. Понятие массива в С является, по сути, понятием языка низкого уровня.

Пример 1. В массиве из двадцати элементов найти максимальный элемент.

Текст программы:

С помощью индексов – порядковых номеров элементов в массиве (при выполнении ввода – вывода).

// Диpективы пpепpоцессоpа

#include <math.h> //Деклаpации функции abs

#include <stdio.h> //Деклаpации функций ввода-вывода (printf)

#include <stdlib.h> //Деклаpации функций random

#include <conio.h> //Деклаpация функций clrscr, getch

//***************** Функция main() *************************

void main()

{

int a[20],maximum;

char v,i;

clrscr(); // Очистка экрана

printf("Лабоpатоpная pабота 4.\n"); // Сообщение для

printf("Указатели и массивы. Ваpиант 0.\n"); // пользователя

printf("Выполнил студент гр.1ВМ-00 Иванов И.И.\n");

printf("\n\nРезультаты pаботы пpогpаммы:\n\n");

vvod: printf("Выберите способ задания массива:\n");

printf("1. С клавиатуры.\n2.Случайными числами.\n");

scanf("%d",&v);

if(v!=1 && v!=2){printf("Введите 1 или 2\n"); goto vvod;}

if(v==1){

for(i=0;i<=19;i++){

printf("Введите %d элемент массива",i);

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

}

else {for(i=0;i<=19;i++);a[i]=random(100);}

for(i=0;i<=19;i++){

printf("%d элемент=%d\n",i,a[i]);

if(a[i]>maximum) maximum=*(a+i);

printf("Максимальный эллемент в массиве---%d",maximum);

printf("\n\nНажмите любую клавишу");

getch();

}

//Конец программы

Результаты работы программы:

Лабоpатоpная pабота 4.

Указатели и массивы. Ваpиант 0.

Выполнил студент гр.1ВМ-00 Иванов И.И.

Результаты pаботы пpогpаммы:

1.С клавиатуры.

2.Случайными числами.

2

0 элемент=-4096

1 элемент=0

2 элемент=1584

3 элемент=0

4 элемент=1572

5 элемент=0

6 элемент=-22

7 элемент=0

8 элемент=20483

9 элемент=0

10 элемент=3

11 элемент=0

12 элемент=1824

13 элемент=0

14 элемент=12291

15 элемент=1824

16 элемент=64

17 элемент=5492

18 элемент=-29436

19 элемент=12803

Максимальный эллемент в массиве---20483

Нажмите любую клавишу

Пример 2.Вывести на экран компьютера таблицу умножения размера n x n, где n вводит пользователь с клавиатуры.

Решение задачи:

/* Программа table.c "Таблица умножения" */

#include <stdio.h>

int main()

{

int i, j, n;

printf ("Введите n: ");

scanf ("%d", &n);

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

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

printf ("%5d", i * j);

}

printf("\n");

}

return 0;

}

Переменные iиjсоответствуют номеру строчки и номеру столбца.

Здесь мы встречаемся с так называемыми «вложенными циклами». Это означает, что один цикл находится в теле другого цикла. Переменная внешнего цикла iсначала равна 1. Начинает работу внутренний цикл

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

{

printf ("%5d", i * j);

}

он печатает первую строчку таблицы.

Переменная внутреннего цикла jменяется от 1 доnвключительно. При этом для каждого значенияjпечатается на экран результат произведенияi * j.

Когда заканчивается внутренний цикл, происходит переход на новую строчку (команда =printf ("\n") ). После этого переменная внешнего цикла iувеличивает своё значение на 1 и становится равна 2. Затем снова запускается внутренний цикл, и печатается вторая строчка таблицы умножения.

Пример работы программы (пользователь ввёл число 5 ):

Введите n: 5

1 2 3 4 5

2 4 6 8 10

3 6 9 12 15

4 8 12 16 20

5 10 15 20 2