3.4.1. Встроенный строковый тип

3.4.1. Встроенный строковый тип

Как уже было сказано, встроенный строковый тип перешел к С++ по наследству от С. Строка символов хранится в памяти как массив, и доступ к ней осуществляется при помощи указателя типа char*. Стандартная библиотека С предоставляет набор функций для манипулирования строками. Например:

// возвращает длину строки

int strlen( const char* );

// сравнивает две строки

int strcmp( const char*, const char* );

// копирует одну строку в другую

char* strcpy( char*, const char* );

Стандартная библиотека С является частью библиотеки С++. Для ее использования мы должны включить заголовочный файл:

#include cstring

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

const char *st = "Цена бутылки вина ";

компилятор помещает все символы строки в массив и затем присваивает st адрес первого элемента массива. Как можно работать со строкой, используя такой указатель?

Обычно для перебора символов строки применяется адресная арифметика. Поскольку строка всегда заканчивается нулевым символом, можно увеличивать указатель на 1, пока очередным символом не станет нуль. Например:

while (*st++ ) { ... }

st разыменовывается, и получившееся значение проверяется на истинность. Любое отличное от нуля значение считается истинным, и, следовательно, цикл заканчивается, когда будет достигнут символ с кодом 0. Операция инкремента ++ прибавляет 1 к указателю st и таким образом сдвигает его к следующему символу.

Вот как может выглядеть реализация функции, возвращающей длину строки. Отметим, что, поскольку указатель может содержать нулевое значение (ни на что не указывать), перед операцией разыменования его следует проверять:

int string_length( const char *st )

{

int cnt = 0;

if ( st )

while ( *st++ )

++cnt;

return cnt;

}

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

// pc1 не адресует никакого массива символов

char *pc1 = 0;

// pc2 адресует нулевой символ

const char *pc2 = "";

Для начинающего программиста использование строк встроенного типа чревато ошибками из-за слишком низкого уровня реализации и невозможности обойтись без адресной арифметики. Ниже мы покажем некоторые типичные погрешности, допускаемые новичками. Задача проста: вычислить длину строки. Первая версия неверна. Исправьте ее.

#include iostream

const char *st = "Цена бутылки вина ";

int main() {

int len = 0;

while ( st++ ) ++len;

cout len ": " st;

return 0;

}

В этой версии указатель st не разыменовывается. Следовательно, на равенство 0 проверяется не символ, на который указывает st, а сам указатель. Поскольку изначально этот указатель имел ненулевое значение (адрес строки), то он никогда не станет равным нулю, и цикл будет выполняться бесконечно.

Во второй версии программы эта погрешность устранена. Программа успешно заканчивается, однако полученный результат неправилен. Где мы не правы на этот раз?

#include iostream

const char *st = "Цена бутылки вина ";

int main()

{

int len = 0;

while ( *st++ ) ++len;

cout len ": " st endl;

return 0;

}

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

Можно попробовать исправить эту ошибку:

st = st – len;

cout len ": " st;

Теперь наша программа выдает что-то осмысленное, но не до конца. Ответ выглядит так:

18: ена бутылки вина

Мы забыли учесть, что заключительный нулевой символ не был включен в подсчитанную длину. st должен быть смещен на длину строки плюс 1. Вот, наконец, правильный оператор:

st = st – len - 1;

а вот и и правильный результат:

18: Цена бутылки вина

Однако нельзя сказать, что наша программа выглядит элегантно. Оператор

st = st – len - 1;

добавлен для того, чтобы исправить ошибку, допущенную на раннем этапе проектирования программы, – непосредственное увеличение указателя st. Этот оператор не вписывается в логику программы, и код теперь трудно понять. Исправления такого рода часто называют заплатками – нечто, призванное заткнуть дыру в существующей программе. Гораздо лучшим решением было бы пересмотреть логику. Одним из вариантов в нашем случае может быть определение второго указателя, инициализированного значением st:

const char *p = st;

Теперь p можно использовать в цикле вычисления длины, оставив значение st неизменным:

while ( *p++ )

Поделитесь на страничке

Следующая глава >

Похожие главы из других книг

Встроенный модуль ParentalControl Bar

Из книги Защита вашего компьютера автора Яремчук Сергей Акимович

Встроенный модуль ParentalControl Bar Если для серфинга в Интернете вы используете обозреватель Internet Explorer или Mozilla Firefox, то можно порекомендовать еще одну бесплатную и простую программу, точнее, встроенный модуль к браузеру – ParentalControl Bar.Домашняя страница, откуда можно ее


ЛЕКЦИЯ № 5. Строковый тип данных

Из книги Информатика и информационные технологии: конспект лекций автора Цветкова А В

ЛЕКЦИЯ № 5. Строковый тип данных 1. Строковый тип в Pascal Последовательность символов определенной длины называется строкой. Переменные строкового типа определяются путем указания имени переменной, зарезервированного слова string, и возможно, но не обязательно указания


1. Строковый тип в Pascal

Из книги Информатика и информационные технологии автора Цветкова А В

1. Строковый тип в Pascal Последовательность символов определенной длины называется строкой. Переменные строкового типа определяются путем указания имени переменной, зарезервированного слова string, и возможно, но не обязательно указания максимального размера, т. е. длины


11. Строковый тип в Pascal. Процедуры и функции для переменных строкового типа

Из книги Железо ПК [Популярный самоучитель] автора Пташинский Владимир

11. Строковый тип в Pascal. Процедуры и функции для переменных строкового типа Последовательность символов определенной длины называется строкой. Переменные строкового типа определяются путем указания имени переменной, зарезервированного слова string, и возможно, но не


Встроенный мастер установки

Из книги Win2K FAQ (v. 6.0) автора Шашков Алексей

Встроенный мастер установки Запускается мастер установки (рис. 15.1) с помощью значка Установка и удаление программ расположенного на Панели управления. Рис. 15.1. Окно изменения или удаления программУстановка программыЧтобы установить программу, щелкните на кнопке


(3.5) Как отключить Dr. Watson, встроенный дебагер?

Из книги WinXP FAQ (Часто задаваемые вопросы по ОС Windows XP) автора Шашков Алексей

(3.5) Как отключить Dr. Watson, встроенный дебагер? Это не только позволит быстрее закрывать подвиснувшие приложения, но и позволит ускорить запуск программ и освободить пару мегабайт оперативной памяти. Сделать это можно выставив ключ Auto равным 0 по адресу


3.4. Как отключить Dr. Watson, встроенный дебагер?

Из книги Технология XSLT автора Валиков Алексей Николаевич

3.4. Как отключить Dr. Watson, встроенный дебагер? Это не только позволит быстрее закрывать подвиснувшие приложения, но и позволит ускорить запуск программ и освободить пару мегабайт оперативной памяти. Сделать это можно выставив ключ Auto равным 0 по адресу HKEY_LOCAL_MACHINE -> SOFTWARE ->


Строковый тип (string)

Из книги Удвоение продаж в интернет-магазине автора Парабеллум Андрей Алексеевич


Upsell, встроенный в корзину

Из книги КОМПАС-3D для студентов и школьников. Черчение, информатика, геометрия автора Большаков Владимир

Upsell, встроенный в корзину Последнее время в Рунете стала применяться методика, которая давно и успешно используется на Западе и позволяет увеличить средний чек в интернет-магазине.Когда человек после выбора товаров для заказа переходит в свою корзину, он видит там еще


8.4. Векторный редактор, встроенный в Word, или КОМПАС?

Из книги Firebird РУКОВОДСТВО РАЗРАБОТЧИКА БАЗ ДАННЫХ автора Борри Хелен

8.4. Векторный редактор, встроенный в Word, или КОМПАС? В учебнике [19] утверждается, что Word располагает простыми и вместе с тем мощными средствами для создания рисунков различной степени сложности: от элементарных геометрических фигур до сложных объемных фигур. В учебнике [20]


Встроенный сервер под Windows

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

Встроенный сервер под Windows Библиотека встроенного сервера под Windows, естественно, разработана для работы на машинах, которые не используются как полноценный сервер. Если у вас есть копия библиотеки fbembed.dll, расположенная где-нибудь на полностью серверной машине,


Пример 17-9. "Анонимный" Встроенный Документ

Из книги Программирование для Linux. Профессиональный подход автора Митчелл Марк

Пример 17-9. "Анонимный" Встроенный Документ #!/bin/bash: <<TESTVARIABLES${HOSTNAME?}${USER?}${MAIL?} # Если одна из переменных не определена, то выводится сообщение об ошибке.TESTVARIABLESexit 0 Подобную технику можно использовать для создания "блочных


Глава 9 Встроенный ассемблерный код

Из книги C++ для начинающих автора Липпман Стенли

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


2.1. Встроенный тип данных "массив"

Из книги Описание языка PascalABC.NET автора Коллектив РуБоард

2.1. Встроенный тип данных "массив" Как было показано в главе 1, С++ предоставляет встроенную поддержку для основных типов данных – целых и вещественных чисел, логических значений и символов:// объявление целого объекта ival// ival инициализируется значением 1024int ival = 1024;//


20.2.1. Строковый ввод

Из книги автора

20.2.1. Строковый ввод Считывание можно производить как в C-строки, так и в объекты класса string. Мы рекомендуем пользоваться последними. Их главное преимущество – автоматическое управление памятью для хранения символов. Чтобы прочитать данные в C-строку, т.е. массив символов,