Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Tekhnologia_programmirovania.pdf
Скачиваний:
182
Добавлен:
08.04.2015
Размер:
1.76 Mб
Скачать

122 10

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

Теперь можно разобраться, почему, аргументом функции, он не копируется объявлена функция с аргументом – массивом:

так как содержит адрес a = p, a++ недопустимы. во всем остальном имя

когда массив является внутрь функции. Пусть

void f(char s[]);

Так как имя массива – это указатель на первый элемент массива, то данное объявление эквивалентно такому:

void f(char* s);

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

10.3. Адресная арифметика

Как уже говорилось, указатели можно складывать и вычитать с целыми. Если p – указатель на некоторый элемент массива, то выражение p++ изменяет p так, чтобы он указывал на следующий элемент массива. Выражение p += i изменяет p так, чтобы он указывал на i - й элемент, после того, на который он указывал ранее.

Если p и q указывают на элементы одного и того же массива, то к ним можно применять операторы сравнения: ==, !=, <, <=, >, >=. Выражение p < q истинно, если p указывает на более ранний элемент массива, чем q.

Любой указатель можно сравнивать на равенство и неравенство с нулем. Если значение указателя равно нулю, это трактуется так, что указатель никуда не указывает.

Допускается вычитание указателей. Если p и q указывают на элементы одного и того же массива и p < q, то q - p + 1 есть число элементов от p до q включительно.

10.4. Символьные указатели

Для работы со строками символов часто используются указатели на char. Их определение имеет вид:

char *pc;

Строковая константа, написанная в виде ”Я строка”, есть массив символов. Во внутреннем представлении этот массив заканчивается

Указатели и ссылки 123

нулевым символом ’\0’, по которому программа может найти конец строки. Адрес начала массива, в котором расположена строковая константа, можно присвоить указателю:

pc = ”Я строка”;

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

Указатель на строку можно использовать там, где требуются строки. Например, при выполнении следующей инструкции:

cout << pc << ” длиной ” << strlen(pc) << ”символов”;

будет напечатано:

Я строка длиной 8 символов

При подсчете символов строки учитываются и пробелы, а завершающий символ ’\0’ не учитывается.

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

Указатели, как и любые другие переменные, можно группировать в массивы. Удобно, например, использовать массив символьных указателей при работе с несколькими строками, которые могут иметь различную длину.

Программа 26. Названия месяцев

Программа предлагает ввести номер месяца и выводит его название. Для доступа к строкам с названиями месяцев используется массив символьных указателей pmn.

//Файл NmMonths.cpp

//Использование массива указателей

//Программа выводит название месяца по его номеру

#include <iostream.h> #include <conio.h>

int main()

{

char *pmn[] = {"Неверный месяц", "Январь", "Февраль", "Март",

 

"Апрель", "Май", "Июнь", "Июль", "Август",

 

"Сентябрь", "Октябрь", "Ноябрь", "Декабрь"

 

};

int n;

// Номер месяца

cout << "\nВведите номер месяца: "; cin >> n;

124 10

cout << "Это " << (n > 0 && n <=12 ? pmn[n] : pmn[0]); getch();

return 0;

}

Массив pmn инициализируется строковыми константами. Сами константы размещены где-то в памяти, а их адреса запоминаются в указателях с помощью инициализации. Для доступа к нужному элементу массива использовано условное выражение:

n > 0 && n <= 12 ? pmn[n] : pmn[0]

Если n – допустимый номер, это выражение будет иметь значение pmn[n], если же значение n не может быть номером месяца, выражение будет равно pmn[0]. Данное выражение в программе заключено в скобки потому, что без них сначала выполнялся бы оператор <<, имеющий более высокий приоритет, который просто напечатал бы значение переменной n.

10.6.Указатели на функции

Вязыке С++ функция не является переменной, но можно определить указатель на функцию и работать с ним как с обычной переменной: присваивать, размещать в массиве, передавать в качестве параметра функции, возвращать как результат из функции. Например, определение:

double (*f) (double x, double y);

создает указатель f на функцию, имеющую два аргумента типа double и возвращающую значение типа double. Здесь скобки вокруг имени указателя (*f) важны, так как запись:

double *f (double x, double y);

определяет f как функцию, с двумя аргументами типа double, которая возвращает указатель на double.

Программа 27. Поиск максимума функции

Пусть требуется найти максимальное значение некоторой математической функции

y=f(x)

на отрезке [a, b]. Применим для решения этой задачи метод перебора. Выберем n точек на отрезке [a, b], расположенных на одинаковом расстоянии

Указатели и ссылки 125

x =(b - a)/(n - 1)

друг от друга. Их координаты можно вычислить по формуле: xi = a + i x, i = 0, 1, 2,…, n-1.

В каждой из этих точек вычислим значение функции: yi = f(xi), i = 0, 1, 2,…, n-1

и выберем среди этих значений максимальное.

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

// Файл MaxFunc.cpp

/* maxfun: возвращает максимальное значение функции, значения которой вычисляются с помощью функции, заданной указателем f */

double maxfun(double (*f)(double), double a, double b, int n)

/*

f – указатель на функцию с одним аргументом типа double, возвращающую значение типа double;

a, b – границы отрезка определения функции;

n – число точек на отрезке, в которых вычисляется функция. */

{

double dx, fx, max;

dx = (b - a)/(n - 1); // Расстояние между узлами

max = f(a); // Может быть максимум достигается на левой границе

while((a += dx) <= b){

 

fx = f(a);

// Значение функции в текущей точке

if(fx > max)

// Если текущее значение функции больше,

max = fx;

// запоминаем его

}

 

return max;

 

}

 

#include <math.h>

 

#include <iostream.h>

 

#include <conio.h>

 

double erf(double);

// Прототип некоторой функции

void main()