|
Программирование >> Аргументация конструирования
Использование указателей для работы со строками Строку можно назвать массивом символов, в котором последний символ равен нулю (язык C + + использует ноль как символ конца строки). Такие нуль-завершенные массивы можно рассматривать как отдельный тип (точнее, квази-тип), о котором пша речь в главе 7, Хранение последовательностей в массивах . В C++ для работы со строками используются указатели. В приведенных ниже примерах показано, каковы отличия в работе со строками в случае применения массивов и указателей. Отличия в работе со строками с использованием указателей и массивов С помощью указателей можно работать с символьными массивами так же, как и с массивами любого другого типа. То, что в конце любой строки находится символ конца строки, делает их особенно удобными для работы с помощью указателей. В главе 7, Хранение последовательностей в массивах , рассматривалась функция concatString {), которая объединяла два символьных массива. Прототип этой функции был объявлен так: void concatString(char szTarget[], char szSource[]); Прототип описывает, какие аргументы принимает функция и какой тип имеет возвращаемый функцией результат. Прототип имеет такой же вид, как и объявление функции, однако в нем отсутствует тело функции. Для обнаружения нуля в конце массива функция concatString () про- сматривает содержимое всего массива с помощью цикла while: void concatString(char szTarget[], char szSource[]) найти конец первой строки int intTargetlndex = О; while(szTarget[intTargetlndex]) { intTargetIndex++; . . . Чтобы использовать для решения этой задачи указатели, следует объявить прототип функции так: voi ring(char* pszTarget, char* pszSource); А саму функцию необходимо переписать следующим образом: void concatString(char* pszTarget, char* pszSource) найти конец первой строки while (*pszTarget) pszTarget++; . . . В предыдущей версии функции concatString while повторялся тех пор, пока [intTargetlndex] не оказывался равным 0. В варианте с указателями считывание и сравнение с нулем элементов массива происходит с помощью указателя pszTarget. Выражение ptr++ представляет собой сокращенную форму записи ptr = После в1хода из цикла while указатель pszTarget указывает на конечный элемент массива, содержащий ноль. Теперь сказать, что pszTarget указывает на массив, нельзя, поскольку он больше не указывает на начало массива. Завершение функции concatstring() В этом примере приведена готовая программа для объединения двух строк в одну: ConcatenatePtr - соединяет две строки и добавляет между ишш - , используя для этого действия с указателями вместо индексов массива #include <stdio.h> Iinciude <iostream.h> voi ing(char* pszTarget, char* pszSource); in (int nArg, char* pszArgs[]) считать первую строку... char szStringl [25 6] ; cout Введите строку #1: ; cin.getline (szStringl, 128) ; теперь вторую.. . char szStringi [12 8] ; cout Введите строку #2: ; cin.getline(szString2, 128) ; ...присоединить - к концу первой... concatString(szStringl, - ) ; теперь добавить вторую строку... concatstring(szStringl, szString2); показать результат cout << \п szStringl \п ; return 0; - присоединяет к окончанию строки *pszTarget voi ing (char* pszTarget, char* pszSource) найти конец первой строки while(pszTarget) { pszTarget++; присоединяет вторую строку к концу первой (и копирует ноль из второй строки в конец созданной строки, чтобы было известно, где заканчивается полученная строка) while(*pszTarget++ = *ps2Source++) { } Функция mai) новой программы ничем не отличается от своей предшественницы, однако concatstring () существенно отличается от варианта с использованием массивов. Как можно заметить, теперь объявление прототипа функции concatstring в начале программы содержит аргументы типа char*. Кроме того, первый цикл while в функции concatstring {) ищет символ конца строки с помощью указателя pszTarget. Исключительно компактный цикл в конце подпрограммы concatstring () выполняет присоединение символьного массива pszSource к концу массива pszTarget. В этом выражении вся работа по соединению осуществляется самим оператором while (), который выполняет ряд операций. 1. Считывает символ, на который указывает 2. Увеличивает значение указателя pszSource для работы со следующим символом. 3. Записывает считанный символ в позицию, на которую указывает pszTarget. 4. Увеличивает значение указателя pszTarget для работы со следующим символом. 5. Выполняет тело цикла, если считанный символ не ноль. После выполнения пустого тела программы управление опять передается оператору while (). Этот цикл будет выполняться, пока скопированный в pszTarget символ не окажется символом конца строки. Почему при работе со строками пользуются указателями Иногда некоторая запутанность работы с указателями вызывает у читателя вполне резонный вопрос: почему стоит пользоваться указателями? Иными словами, что делает использование указателя char* предпочтительнее более простого для чтения варианта с массивами и индексами? Вариант функции concatenate () с использованием указателей гораздо распространеннее в C + + , чем вариант с массивами. Ответ следует искать отчасти в человеческой природе, отчасти в истории развития C++. Компилятор языка С, прародителя C++, в те времена, когда язык появился на свет, был довольно примитивен. Тогда компиляторы не были столь сложными, как сейчас, и не могли так хорошо оптимизировать код. Код while (*p:5zTatget++ = *pszSource++) {} может показаться читателю сложным, однако после компиляции с помощью даже самого древнего компилятора он будет состоять буквально из нескольких машинных инструкций. Старые компьютеры были не очень быстрыми по современным меркам. Во времена С экономия нескольких машинных инструкций значила очень много, что и привело к превосходству С над другими языками того времени, такими как FORTRAN, который не поддерживал работу с указателями. Именно тогда и зародилась традиция писать компактные и эффективные, правда, подчас несколько загадочные на вид программы на C++, и с тех пор никто не хочет возвращаться к индексам.
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |