Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология
Образование Политология Производство Психология Стандартизация Технологии


Часть Становимся программистами. Использование указателей для работы со строками




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

Строку можно назвать массивом символов, в котором последний символ равен нулю (язык C++ использует ноль как символ конца строки). Такие нуль- завершенные массивы можно рассматривать как отдельный тип (точнее, квази- тип), о котором шла речь  в  главе 7,                                                                                  последовательностей в массивах". В C++ для работы со строками используются указатели. В приведенных ниже примерах показано, каковы отличия в работе со строками в случае применения массивов и указателей.

Отличия в работе со строками с использованием указателей и массивов

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

В главе 7, "Хранение последовательностей в массивах", рассматривалась функция

{), которая объединяла два символьных массива. Прототип этой функ- ции был объявлен так:

void                                                    char

 

Прототип описывает, какие аргументы принимает функция и какой тип имеет возвращаемый функцией результат. Прототип имеет такой же вид, как и объявление функции, однако в нем отсутствует тело функции.

 

Для обнаружения нуля в конце массива                         функция concatStrin g () про- сматривает содержимое всего массива с помощью цикла while:

void                                                    char szSource[] )

{

// найти конец первой строки int = 0;

 

{

 

 

Чтобы использовать для решения этой задачи указатели, следует объявить прото- тип функции так:

void                                pszTarget ,  char* pszSource) ;

А саму функцию необходимо переписать следующим образом:

void

{

// найти конец первой строки

 

{

 

 

В предыдущей версии функции concatStrin g ЦИКЛ while повторялся ДО пор, пока [intTargetlndex ] не оказывался равным 0. В варианте с указателями считывание и сравнение с нулем элементов массива происходит с по- мощью указателя pszTarget.

Глава 9. Второе знакомство с указателями                                 101


Выражение ptr++ представляет собой сокращенную форму записи pt r pt r + 1.

 

После выхода из цикла while указатель pszTarge t указывает на конечный эле- мент массива, содержащий ноль. Теперь сказать, что pszTarge t указывает на массив, нельзя, поскольку он больше не указывает на начало массива.

Завершение функции concatstring( )

В этом примере приведена готовая программа для объединения двух строк в одну:

// ConcatenatePtr — соединяет две строки и добавляет

//            между ними " - ",   зуя

//             действия с указателями вместо

//             индексов массива

<stdio.h>

 

void               pszTarget, char* pszSource);

int                     nArg, char* pszArgs[])

{

// считать первую строку... char szStringl [256];

« "Введите строку #1: ";

128);

 

//      вторую...

char szString2 [128];

cout << "Введите строку ";

128) ;

 

// ...присоединить " — " к концу первой...

" — ") ;

 

//      добавить вторую строку...

 

// показать результат

cout << "\п" « szStringl « "\п"; return 0;

 

//         — присоединяет        к окончанию

//           строки *pszTarget

void                pszTarget, char* pszSource)

{

// найти конец первой строки

 

pszTarget++;

}

// присоединяет вторую строку к концу первой

// (и копирует ноль из второй строки в конец

// созданной строки, чтобы было известно, где

 

102                                                     Часть Становимся программистами


// заканчивается полученная строка)

 

Функция main новой программы ничем не отличается от своей предшественни- цы, однако concatstrin g () существенно отличается от варианта с использованием массивов.

Как можно заметить, теперь объявление прототипа функции concatstrin g в начале программы содержит аргументы типа char*. Кроме того, первый цикл while в функ- ции concatstrin g {) ищет символ конца строки с помощью указателя pszTarget.

Исключительно компактный цикл в конце подпрограммы concatstrin g () вы- полняет присоединение символьного массива pszSource к концу массива pszTarget. В этом выражении вся работа по соединению осуществляется самим оператором while (), который выполняет ряд операций.

1. Считывает символ, на который указывает

2. Увеличивает значение указателя pszSource для работы со следующим

 

3. Записывает считанный символ в позицию, на которую указывает pszTarget.

4. Увеличивает значение указателя pszTarge t для работы со следующим

 

5. Выполняет тело цикла, если считанный символ не ноль.

После выполнения пустого тела программы управление опять передается операто- ру while (). Этот цикл будет выполняться, пока скопированный в pszTarget символ не окажется символом конца строки.

Почему при работе со строками пользуются указателями

Иногда некоторая запутанность работы с указателями вызывает у читателя вполне резонный вопрос: почему стоит пользоваться указателями? Иными словами, что дела- ет использование указателя char* предпочтительнее более простого для чтения вари- анта с массивами и индексами?

Вариант функции concatenat e () с использованием указателей гораздо распространеннее в C++, чем вариант с массивами.

 

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

=                              {} может показаться читателю сложным, однако после компиляции с помощью даже самого древнего компилятора он будет со- стоять буквально из нескольких машинных инструкций.

Старые компьютеры были не очень быстрыми по современным меркам. Во време- на С экономия нескольких машинных инструкций значила очень много, что и приве- ло к превосходству С над другими языками того времени, такими как FORTRAN, ко- торый не поддерживал работу с указателями.

Именно тогда и зародилась традиция писать компактные и эффективные, правда, подчас несколько загадочные на вид программы на C++, и с тех пор никто не хочет возвращаться к индексам.

 

Глава 9. Второе знакомство с указателями


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

 

// выражение

=

 

// и выражение

=      +

// после компиляции могут давать

// одинаковое количество машинных инструкций

Во времена примитивных компиляторов, которые не оптимизировали код, первый вариант вызвал бы использование меньшего количества машинных команд. Однако современным оптимизирующим компилятором в обоих случаях будет сгенерирован идентичный код.


Поделиться:



Последнее изменение этой страницы: 2019-04-19; Просмотров: 207; Нарушение авторского права страницы


lektsia.com 2007 - 2024 год. Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав! (0.019 с.)
Главная | Случайная страница | Обратная связь