Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
книги / 277.pdf
Скачиваний:
9
Добавлен:
07.06.2023
Размер:
1.06 Mб
Скачать

printf ( «Введите элементы матрицы \n» ); for ( i = 0; i<n; i++ )

for ( j = 0; j<m; j++ ) scanf ( «%d», &a[i][j] );

printf ( «Исходный массив \n» ); for ( i =0; i<n; i++ )

{

for ( j = 0; j<m; j++ ) printf ( «%5d», a[i][j] ); printf ( «\n» );

}

s = 0;

//Сумма элементов главной диагонали for ( i = 0; i<n; i++ )

s = s+a[i][i];

//Замена элементов побочной диагонали for ( i = 0; i<n; i++ )

{

j = n-i-1;

if ( a[i][j]<0 ) a[i][j] = s;

}

printf ( «Полученный массив \n» ); for ( i = 0; i<n; i++ )

{

for ( j = 0; j<m; j++ ) printf ( «%5d», a[i][j] ); printf ( «\n» );

}

getch ();

}

Массивы и указатели

Известно, что данные хранятся в ячейках памяти компьютера. Все ячейки памяти пронумерованы. Номера ячеек памяти называются адресами. Указатели используются для работы с адресами. Указатель - это некоторое символическое представление адреса. Это означает, что будем работать с переменными, хранящими эти адреса. Описываются такие переменные следующим образом:

<тип> *<идентификатор>; Такое описание синтаксически отличается от описания простой

переменной только наличием знака * перед именем переменной. Как видно

93

из описания, указатель всегда связывается с переменной какого-то определенного типа. Это позволяет определить, сколько байт памяти необходимо выделить по указанному адресу. В переменной типа указатель хранится адрес первого байта, выделенного участка памяти:

int *ptr, *ptr1; float *p, *p1;

Над указателями можно выполнять следующие операции [6]:

-Одному указателю можно присвоить значение другого указателя, если они ссылаются на один и тот же тип:

ptr = ptr1; p1 = p;

-Значение указателя можно увеличить или уменьшить на константную величину:

ptr++;

ptr1 = ptr1-5; p1 = p1+2;

На самом деле ptr увеличивается не на 1, а на столько, сколько байт занимает целое число. Переменная ptr1 уменьшается на 5 умноженное на количество байт, выделяемых под целое число.

-Указателю можно присвоить значение адреса. Для получения адреса используется знакомый значок &:

int a, *ptr; ptr = &a;

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

int n = 12, *ptr, a ; ptr = &n;

а = *ptr;

После выполнения этого фрагмента переменная «а» будет иметь значение 12.

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

Здесь следует обратить внимание на то, что символы * и & имеют разное назначение в зависимости от контекста, в котором они используются.

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

синдексами. Имя массива является указателем на первый элемент массива. Элементы массива располагаются в непрерывной области памяти. Эти два

94

положения позволяют перемещаться по элементам массива, используя указатель. Пусть:

int a[10], *ptr; ptr=a;

тогда к пятому элементу массива можно обратиться: a[4]

*(a+4)

*(ptr+4)

и все эти обращения будут равносильны.

Напишем программу из примера pr17 с использованием указателей. //Пример pr17 с указателями

#include <stdio.h> #include <conio.h> #include <stdlib.h> void main()

{ const int N1 = 100; //Максимальный размер массива int a[N1],

*ptr, //Указатель на элементы массива

n, s; //Количество элементов в массиве и их сумма printf ( «\n Введите число элементов массива:» ); scanf ( «%d», &n );

// Формирование массива с помощью датчика случайных чисел randomize ();//Инициализация датчика случайных чисел

for ( ptr = a; ptr-a < n; ptr++ ) *ptr = random (10);

printf ( «Полученный массив: \n» ); for ( ptr = a; ptr-a < n; ptr++ )

printf ( «%5d», *ptr );

s = 0; // Нахождение суммы for ( ptr = a; ptr-a < n; ptr++ ) s = s+*ptr;

printf ( «\n s= %5d», s ); getch ();

}

Начинающие работать с указателями самую большую сложность испытывают при использовании операции косвенной адресации. Например, в заголовке первого же оператора цикла записано prt = a. Это означает, что переменной типа указатель присваивается адрес нулевого элемента массива а. В теле цикла записано *ptr = random(10). В этом случае переменной, хранящейся по адресу, на который указывает ptr, присваивается значение, полученное с датчика случайных чисел. Имя массива a как указатель на нулевой элемент массива является константой,

95

а указатель prt является переменной. Разность prt - a дает порядковый номер элемента массива.

Составим программу с использованием указателей для примера pr18. Исходные данные читаются из файла из файла in.txt (рис. 27), а результат пишется в файл out.txt (рис. 28).

// Пример pr17 с указателями

#include <stdio.h> #include <conio.h> #include <stdlib.h> void main()

{ FILE *in = fopen ("in.txt», «r"); FILE *out = fopen ("out.txt», «w");

const int n1 = 100; //максимальный размер массива int a[n1], *ptr, //указатель на элементы массива n; //Количество элементов в массиве

int p; //Произведение элементов в массиве

int *ptrmax;//Указатель на максимальный элемент fscanf (in, «%d», &n);

for (ptr = a; ptr-a < n; ptr++) fscanf(in, «%d», ptr);

p = 1;

ptrmax = a;//Пусть пеpвый элемент – максимальный for (ptr = a; ptr-a < n; ptr++)

{

//если элемент положительный, то умножаем на него if ( *ptr > 0 ) p = p* *ptr;

//если текущий элемент массива больше //максимального, то запоминаем указатель на него if ( *ptrmax < *ptr) ptrmax = ptr;

}

fprintf(out, «\n максимальный элемент массива

=%d\n», *ptrmax);

*ptrmax = p; // замена максимального произведением fprintf(out, «p = %d\n», p);

fprintf(out, «\nОбpаботанный массив:\n"); for ( ptr = a; ptr-a < n; ptr++ )

fprintf (out, «%5d», *ptr);

}

96

Соседние файлы в папке книги