Лекции.Орг


Поиск:




Категории:

Астрономия
Биология
География
Другие языки
Интернет
Информатика
История
Культура
Литература
Логика
Математика
Медицина
Механика
Охрана труда
Педагогика
Политика
Право
Психология
Религия
Риторика
Социология
Спорт
Строительство
Технология
Транспорт
Физика
Философия
Финансы
Химия
Экология
Экономика
Электроника

 

 

 

 


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




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

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

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

#include <iostream>

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

int main() {

int len = 0;

while (st++) ++len;

cout << len << ": " << st;

return 0;

}

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

Во второй версии программы эта погрешность устранена.

#include <iostream>

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

 

 

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++)

Класс string

Применение С-строк позволяет достичь высокой эффективности, но при этом небезопасно и неудобно из-за слишком низкого уровня реализации. Применение строкового класса повышает уровень абстракции и позволяет решить данные проблемы. Основные действия со строками выполняются в нем с помошью операций и методов, а длина строки изменяется динамически в соответствии с потребностями. Хотя при этом строковый класс уступает С-строкам в эффективности.

Стандартный строковый класс должен обладать следующим минимальным набором операций:

· инициализация массивом символов (С-строкой) или другим объектом типа string (для С-строк такая возможность недоступна);

· копирование одной строки в другую (для С-строк используется функция strcpy);

· доступ к отдельным символам строки для чтения и записи (для С-строк используется операция индексации или косвенная адресация);

· сравнение двух строк на равенство (для С-строк используется функция strcmp);

· конкатенация двух строк с записью результата либо в новую строку, либо в одну из исходных (для С-строк используется функция strcat, но для получения результата в новой строке, необходимо последовательно задействовать функции strcpy и strcat);

· вычисление длины строки (для С-строк используется функция strlen);

· возможность узнать, пуста ли строка (для С-строк необходимо проверять условие! str ||! *str).

В классе string стандартной библиотеки С++ реализуется большое колическтво функций, в том числе и все вышеперечисленные операции. Для того чтобы использовать объекты класса string, необходимо включить соответствующий заголовочный файл string.h.

Пример: сравнение работы с С-строками и строками класса string.

#include <string.h>

#include <iostream.h>

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 << c2; // Сравнение C-строк

else cout << c3;

if (s2 < s3) cout << s2; // Сравнение C-строк

else cout << s3;

return 0;

}

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

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





Поделиться с друзьями:


Дата добавления: 2016-11-12; Мы поможем в написании ваших работ!; просмотров: 781 | Нарушение авторских прав


Поиск на сайте:

Лучшие изречения:

Надо любить жизнь больше, чем смысл жизни. © Федор Достоевский
==> читать все изречения...

2355 - | 2039 -


© 2015-2025 lektsii.org - Контакты - Последнее добавление

Ген: 0.011 с.