Типичные ошибки при работе со строками

      Комментарии к записи Типичные ошибки при работе со строками отключены

Использование С-строк чревато ошибками из-за слишком низкого уровня реализации. Ниже приведены типичные ошибки при работе со строками.

Пример:вычисление длины строки.

Первый вариант программы:

#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 часов Цель работы…