Использование С-строк чревато ошибками из-за слишком низкого уровня реализации. Ниже приведены типичные ошибки при работе со строками.
Пример:вычисление длины строки.
Первый вариант программы:
#include
const char *st = Цена бутылки вина\n;
int main( ) {
int len = 0;
while (st++) ++len;
cout
return 0;
}
Указатель st не разыменовывается. Следовательно, на равенство 0 проверяется не символ, на который указывает st, а сам указатель. Поскольку изначально этот указатель имел ненулевое значение (адрес строки), то он никогда не станет равным нулю, и цикл будет выполняться бесконечно.
Во второй версии программы эта погрешность устранена.
#include
const char *st = Цена бутылки вина\n;
int main( )
{
int len = 0;
while ( *st++ ) ++len;
cout
return 0;
}
Программа успешно заканчивается, однако выдает некорректный результат. Ошибка состоит в том, что после завершения цикла указатель st адресует не исходный символьный литерал, а символ, расположенный в памяти после завершающего нуля этого литерала. В этом месте может находиться что угодно, и выводом программы будет случайная последовательность символов.
Если исправить эту ошибку следующим образом:
st = st – len;
cout
программа выведет:
18: ена бутылки вина
Ошибка обусловлена тем, что заключительный нулевой символ не был включен в подсчитанную длину. st должен быть смещен на длину строки плюс 1. Таким образом, необходимо записать:
st = st – len — 1;
и будет выведен правильный результат:
18: Цена бутылки вина
Хотя добавление оператора
st = st – len — 1;
не является хорошим стилем программирования. Он добавлен, чтобы исправить ошибку, допущенную на раннем этапе проектирования программы, – непосредственное увеличение указателя st. Этот оператор не вписывается в логику программы, и код теперь трудно понять. Исправления такого рода часто называют заплатками.
Гораздо лучшим решением было бы пересмотреть логику. Одним из вариантов может быть определение второго указателя, инициализированного значением st:
const char *p = st;
Теперь p можно использовать в цикле вычисления длины, оставив значение st неизменным:
while ( *p++ )
Класс string
Применение С-строк позволяет достичь высокой эффективности, но при этом небезопасно и неудобно из-за слишком низкого уровня реализации. Применение строкового класса повышает уровень абстракции и позволяет решить данные проблемы. Основные действия со строками выполняются в нем с помошью операций и методов, а длина строки изменяется динамически в соответствии с потребностями. Хотя при этом строковый класс уступает С-строкам в эффективности.
Стандартный строковый класс должен обладать следующим минимальным набором операций:
- инициализация массивом символов (С-строкой) или другим объектом типа string (для С-строк такая возможность недоступна);
- копирование одной строки в другую (для С-строк используется функция strcpy);
- доступ к отдельным символам строки для чтения и записи (для С-строк используется операция индексации или косвенная адресация);
- сравнение двух строк на равенство (для С-строк используется функция strcmp);
- конкатенация двух строк с записью результата либо в новую строку, либо в одну из исходных (для С-строк используется функция strcat, но для получения результата в новой строке, необходимо последовательно задействовать функции strcpy и strcat);
- вычисление длины строки (для С-строк используется функция strlen);
- возможность узнать, пуста ли строка (для С-строк необходимо проверять условие ! str || ! *str ).
В классе string стандартной библиотеки С++ реализуется большое колическтво функций, в том числе и все вышеперечисленные операции. Для того чтобы использовать объекты класса string, необходимо включить соответствующий заголовочный файл string.h.
Пример: сравнение работы с С-строками и строками класса string.
#include
#include
int main ( ){
char c1[80], c2[80], с3[80]; // C-строки
string s1, s2, s3; // строки класса string
strcpy(c1, С-string one); // Присваивание C-строк
strcpy(c2, c1);
s1 = С++ string one; // Присваивание строк класса string
s2 = s1;
strcpy(c3, c1); // Конкатенация C-строк
strcat (c3, c2);
s3 = s1 + s2; // Конкатенация строк класса string
if (strcmp(c2, c3)0 ) cout
else cout
if (s2s3) cout
else cout
return 0;
}
Как видно из примера, выполнение любых действий с C-строками требует использования функций и менее наглядно. Кроме того, необходимо проверять, достаточно ли места в строке-приемнике при копировании, т.е. код для работы с С-строками может быть еще и более длинным (в примере проверка не реализуется).
Строки класса string защищены от выхода информации за их границы и с ними можно работать так же, как с любым встроенным типом данных, т.е. с помощью операций.
Статьи к прочтению:
ТИПИЧНЫЙ ПРАЗДНИК НОВЫЙ ГОД
Похожие статьи:
-
Ошибки и сбои при работе в windows
ЭТАПЫ ЗАГРУЗКИ КОМПЬЮТЕРА ПОД УПРАВЛЕНИЕМ WINDOWS Аппаратная POST-диагностика При включении питания компьютера активируется BIOS, тестирующий готовность…
-
При работе в среде visualstudio необходимо уметь
Лабораторная работа № 01 Классы, свойства, индексаторы. Одномерные, прямоугольные и Ступенчатые массивы Время выполнения работы – 6 часов Цель работы…