Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
uchebno-metodicheskoe_posobie_SiAOD_1chast / учебно-методическое пособие СиАОД 1часть.doc
Скачиваний:
94
Добавлен:
20.03.2015
Размер:
1 Mб
Скачать

1.3.Переменные типа "массив". Арифметические операции с указателями

В Си++ понятия массива и указателя тесно связаны. Рассмотрим оператор описания:

Int hours[6];

Этот массив состоит из 6-ти элементов:

hours[0] hours[1] hours[2] hours[3] hours[4] hours[5]

Массивы в Си++ реализованы так, как будто имя массива (например, "hours") является указателем. Поэтому, если добавить в программу объявление целочисленного указателя:

int* ptr;

то ему можно присвоить адрес массива (т.е. адрес первого элемента массива):

ptr = hours;

После выполнения этого оператора обе переменные – "ptr" и "hours" – будут указывать на целочисленную переменную, доступную в программе как "hours[0]".

Фактически, имена "hours[0]", "*hours" и "*ptr" являются тремя различными именами одной и той же переменной. У переменных "hours[1]", "hours[2]" и т.д. также появляются новые имена:

*(hours + 1) *(hours + 2) ...

или

*(ptr + 1) *(ptr + 2) ...

В данном случае "+2" означает "добавить к адресу указателя смещение, соответствующее 2-м целым значениям". Из арифметических операций к указателям часто применяется сложение и вычитание (в том числе операции инкремента и декремента"++" и "--"), а умножение и деление не используются. Значения однотипных указателей можно вычитать друг из друга.

Главное, что нужно запомнить относительно сложения и вычитания значений из указателя – в выражениях Си++ указывается не число, которое нужно вычесть (или добавить) из адреса, а количество переменных заданного типа, на которые нужно "сместить" адрес.

Арифметические выражения с указателями иногда позволяют более кратко записать обработку массивов. В качестве примера рассмотрим функцию для преобразования английской строки в верхний регистр:

Пример 1.5:

void ChangeToUpperCase( char phrase[ ] )

{

int index = 0;

while ( phrase[index] != '\0' )

{

if ( LowerCase(phrase[index]) )

ChangeToUpperCase( phrase[index] );

index++;

}

}

bool LowerCase( char character )

{

return ( character >= 'a' && character <= 'z');

}

void ChangeToUpperCase( char& character )

{

character += 'A' - 'a';

}

Обратите внимание на полиморфизм функции "ChangeToUpperCase(...)" – при обработке вызова компилятор различает две перегруженных функции, т.к. у них разные параметры (у одной – параметр типа "char", а у другой – параметр типа "символьный массив"). Имя массива "phrase" является переменной-указателем, поэтому функцию с параметром-массивом можно переписать короче, если использовать арифметические выражения с указателями:

Пример 1.6:

void ChangeToUpperCase( char* phrase )

{

while ( *phrase != '\0' )

{

if ( LowerCase(*phrase) )

ChangeToUpperCase(*phrase);

phrase++;

}

}

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

char a_string[] = "Hello World";

...

...

ChangeToUpperCase( a_string );

1.4. Динамические массивы

Правила создания и уничтожения динамических переменных типов "int", "char", "double" и т.п. распространяются и на динамические массивы. По отношению к массивам динамическое распределение памяти особенно полезно, поскольку иногда бывают массивы больших размеров.

Динамический массив из 10-ти целых чисел можно создать следующим образом:

int* number_ptr;

number_ptr = new int[10];

Для уничтожения динамического массива применяется оператор "delete" c квадратными скобками "[ ]":

delete[] number_ptr;

Скобки "[]" играют важную роль. Они сообщают оператору, что требуется уничтожить все элементы массива, а не только первый. Работа с динамическими массивами показана в приведенном фрагменте программы. У пользователя запрашивается список целых чисел, затем вычисляется и выводится на экран их среднее значение. ...

Пример 1.7:

...

int no_of_integers, *number_ptr;

cout << "Введите количество целых чисел в списке: ";

cin >> no_of_integers;

number_ptr = new int[no_of_integers];

if ( number_ptr == NULL )

{

cout << "Извините, недостаточно памяти.\n";

exit(1);

}

cout << "Наберите " << no_of_integers;

cout << " целых чисел, разделяя их пробелами:\n";

for ( int count = 0; count < no_of_integers; count++ )

cin >> number_ptr[count];

cout << "Среднее значение: ";

cout << average( number_ptr, no_of_integers );

delete[] number_ptr;

... Динамические массивы, как и обычные, можно передавать в качестве параметров функций.