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++ )
Более 800 000 книг и аудиокниг! 📚
Получи 2 месяца Литрес Подписки в подарок и наслаждайся неограниченным чтением
ПОЛУЧИТЬ ПОДАРОКЧитайте также
(3.5) Как отключить Dr. Watson, встроенный дебагер?
(3.5) Как отключить Dr. Watson, встроенный дебагер? Это не только позволит быстрее закрывать подвиснувшие приложения, но и позволит ускорить запуск программ и освободить пару мегабайт оперативной памяти. Сделать это можно выставив ключ Auto равным 0 по адресу
3.4. Как отключить Dr. Watson, встроенный дебагер?
3.4. Как отключить Dr. Watson, встроенный дебагер? Это не только позволит быстрее закрывать подвиснувшие приложения, но и позволит ускорить запуск программ и освободить пару мегабайт оперативной памяти. Сделать это можно выставив ключ Auto равным 0 по адресу HKEY_LOCAL_MACHINE -> SOFTWARE ->
Upsell, встроенный в корзину
Upsell, встроенный в корзину Последнее время в Рунете стала применяться методика, которая давно и успешно используется на Западе и позволяет увеличить средний чек в интернет-магазине.Когда человек после выбора товаров для заказа переходит в свою корзину, он видит там еще
ЛЕКЦИЯ № 5. Строковый тип данных
ЛЕКЦИЯ № 5. Строковый тип данных 1. Строковый тип в Pascal Последовательность символов определенной длины называется строкой. Переменные строкового типа определяются путем указания имени переменной, зарезервированного слова string, и возможно, но не обязательно указания
1. Строковый тип в Pascal
1. Строковый тип в Pascal Последовательность символов определенной длины называется строкой. Переменные строкового типа определяются путем указания имени переменной, зарезервированного слова string, и возможно, но не обязательно указания максимального размера, т. е. длины
Встроенный модуль ParentalControl Bar
Встроенный модуль ParentalControl Bar Если для серфинга в Интернете вы используете обозреватель Internet Explorer или Mozilla Firefox, то можно порекомендовать еще одну бесплатную и простую программу, точнее, встроенный модуль к браузеру – ParentalControl Bar.Домашняя страница, откуда можно ее
Глава 9 Встроенный ассемблерный код
Глава 9 Встроенный ассемблерный код Сегодня лишь немногие программисты используют в своей практике язык ассемблера. Языки высокого уровня, такие как С и C++, поддерживаются практически на всех архитектурах и обеспечивают достаточно высокую производительность программ.
2.1. Встроенный тип данных "массив"
2.1. Встроенный тип данных "массив" Как было показано в главе 1, С++ предоставляет встроенную поддержку для основных типов данных – целых и вещественных чисел, логических значений и символов:// объявление целого объекта ival// ival инициализируется значением 1024int ival = 1024;//
20.2.1. Строковый ввод
20.2.1. Строковый ввод Считывание можно производить как в C-строки, так и в объекты класса string. Мы рекомендуем пользоваться последними. Их главное преимущество – автоматическое управление памятью для хранения символов. Чтобы прочитать данные в C-строку, т.е. массив символов,
Встроенный сервер под Windows
Встроенный сервер под Windows Библиотека встроенного сервера под Windows, естественно, разработана для работы на машинах, которые не используются как полноценный сервер. Если у вас есть копия библиотеки fbembed.dll, расположенная где-нибудь на полностью серверной машине,
Пример 17-9. "Анонимный" Встроенный Документ
Пример 17-9. "Анонимный" Встроенный Документ #!/bin/bash: <<TESTVARIABLES${HOSTNAME?}${USER?}${MAIL?} # Если одна из переменных не определена, то выводится сообщение об ошибке.TESTVARIABLESexit 0 Подобную технику можно использовать для создания "блочных
8.4. Векторный редактор, встроенный в Word, или КОМПАС?
8.4. Векторный редактор, встроенный в Word, или КОМПАС? В учебнике [19] утверждается, что Word располагает простыми и вместе с тем мощными средствами для создания рисунков различной степени сложности: от элементарных геометрических фигур до сложных объемных фигур. В учебнике [20]
Встроенный мастер установки
Встроенный мастер установки Запускается мастер установки (рис. 15.1) с помощью значка Установка и удаление программ расположенного на Панели управления. Рис. 15.1. Окно изменения или удаления программУстановка программыЧтобы установить программу, щелкните на кнопке
11. Строковый тип в Pascal. Процедуры и функции для переменных строкового типа
11. Строковый тип в Pascal. Процедуры и функции для переменных строкового типа Последовательность символов определенной длины называется строкой. Переменные строкового типа определяются путем указания имени переменной, зарезервированного слова string, и возможно, но не