- Любовные романы
- Фантастика и фэнтези
- Ненаучная фантастика
- Ироническое фэнтези
- Научная Фантастика
- Фэнтези
- Ужасы и Мистика
- Боевая фантастика
- Альтернативная история
- Космическая фантастика
- Попаданцы
- Юмористическая фантастика
- Героическая фантастика
- Детективная фантастика
- Социально-психологическая
- Боевое фэнтези
- Русское фэнтези
- Киберпанк
- Романтическая фантастика
- Городская фантастика
- Технофэнтези
- Мистика
- Разная фантастика
- Иностранное фэнтези
- Историческое фэнтези
- LitRPG
- Эпическая фантастика
- Зарубежная фантастика
- Городское фентези
- Космоопера
- Разное фэнтези
- Книги магов
- Любовное фэнтези
- Постапокалипсис
- Бизнес
- Историческая фантастика
- Социально-философская фантастика
- Сказочная фантастика
- Стимпанк
- Романтическое фэнтези
- Ироническая фантастика
- Детективы и Триллеры
- Проза
- Юмор
- Феерия
- Новелла
- Русская классическая проза
- Современная проза
- Повести
- Контркультура
- Русская современная проза
- Историческая проза
- Проза
- Классическая проза
- Советская классическая проза
- О войне
- Зарубежная современная проза
- Рассказы
- Зарубежная классика
- Очерки
- Антисоветская литература
- Магический реализм
- Разное
- Сентиментальная проза
- Афоризмы
- Эссе
- Эпистолярная проза
- Семейный роман/Семейная сага
- Поэзия, Драматургия
- Приключения
- Детская литература
- Загадки
- Книга-игра
- Детская проза
- Детские приключения
- Сказка
- Прочая детская литература
- Детская фантастика
- Детские стихи
- Детская образовательная литература
- Детские остросюжетные
- Учебная литература
- Зарубежные детские книги
- Детский фольклор
- Буквари
- Книги для подростков
- Школьные учебники
- Внеклассное чтение
- Книги для дошкольников
- Детская познавательная и развивающая литература
- Детские детективы
- Домоводство, Дом и семья
- Юмор
- Документальные книги
- Бизнес
- Работа с клиентами
- Тайм-менеджмент
- Кадровый менеджмент
- Экономика
- Менеджмент и кадры
- Управление, подбор персонала
- О бизнесе популярно
- Интернет-бизнес
- Личные финансы
- Делопроизводство, офис
- Маркетинг, PR, реклама
- Поиск работы
- Бизнес
- Банковское дело
- Малый бизнес
- Ценные бумаги и инвестиции
- Краткое содержание
- Бухучет и аудит
- Ораторское искусство / риторика
- Корпоративная культура, бизнес
- Финансы
- Государственное и муниципальное управление
- Менеджмент
- Зарубежная деловая литература
- Продажи
- Переговоры
- Личная эффективность
- Торговля
- Научные и научно-популярные книги
- Биофизика
- География
- Экология
- Биохимия
- Рефераты
- Культурология
- Техническая литература
- История
- Психология
- Медицина
- Прочая научная литература
- Юриспруденция
- Биология
- Политика
- Литературоведение
- Религиоведение
- Научпоп
- Психология, личное
- Математика
- Психотерапия
- Социология
- Воспитание детей, педагогика
- Языкознание
- Беременность, ожидание детей
- Транспорт, военная техника
- Детская психология
- Науки: разное
- Педагогика
- Зарубежная психология
- Иностранные языки
- Филология
- Радиотехника
- Деловая литература
- Физика
- Альтернативная медицина
- Химия
- Государство и право
- Обществознание
- Образовательная литература
- Учебники
- Зоология
- Архитектура
- Науки о космосе
- Ботаника
- Астрология
- Ветеринария
- История Европы
- География
- Зарубежная публицистика
- О животных
- Шпаргалки
- Разная литература
- Зарубежная литература о культуре и искусстве
- Пословицы, поговорки
- Боевые искусства
- Прочее
- Периодические издания
- Фанфик
- Военное
- Цитаты из афоризмов
- Гиды, путеводители
- Литература 19 века
- Зарубежная образовательная литература
- Военная история
- Кино
- Современная литература
- Военная техника, оружие
- Культура и искусство
- Музыка, музыканты
- Газеты и журналы
- Современная зарубежная литература
- Визуальные искусства
- Отраслевые издания
- Шахматы
- Недвижимость
- Великолепные истории
- Музыка, танцы
- Авто и ПДД
- Изобразительное искусство, фотография
- Истории из жизни
- Готические новеллы
- Начинающие авторы
- Спецслужбы
- Подростковая литература
- Зарубежная прикладная литература
- Религия и духовность
- Старинная литература
- Справочная литература
- Компьютеры и Интернет
- Блог
Язык программирования C++. Пятое издание - Стенли Липпман
Шрифт:
Интервал:
Закладка:
Стандартная библиотека языка С предоставляет набор функций, перечисленных в табл. 3.8, для работы со строками в стиле С. Эти функции определены в заголовке cstring, являющемся версией С++ заголовка языка С string.h.
Функции из табл. 3.8 не проверяют свои строковые параметры
Указатель (указатели), передаваемый этим функциям, должен указывать на массив (массивы) с нулевым символом в конце.
char ca[] = {'C', '+', '+'}; // без нулевого символа в конце
cout << strlen(ca) << endl; // катастрофа: ca не завершается нулевым
// символом
В данном случае ca — это массив элементов типа char, но он не завершается нулевым символом. Результат непредсказуем. Вероятней всего, функция strlen() продолжит просматривать память уже за пределами массива ca, пока не встретит нулевой символ.
Таблица 3.8. Функции для символьных строк в стиле С
strlen(p) Возвращает длину строки p без учета нулевого символа strcmp(p1, p2) Проверяет равенство строк p1 и p2. Возвращает 0, если p1 == p2, положительное значение, если p1 > p2, и отрицательное значение, если p1 < p2 strcat(p1, p2) Добавляет строку p2 к p1. Результат возвращает в строку p1 strcpy(p1, p2) Копирует строку p2 в строку p1. Результат возвращает в строку p1 Сравнение строкСравнение двух строк в стиле С осуществляется совсем не так, как сравнение строк библиотечного типа string. При сравнении библиотечных строк используются обычные операторы равенства или сравнения:
string s1 = "A string example";
string s2 = "A different string";
if (s1 < s2) // ложно: s2 меньше s1
Использование этих же операторов для подобным образом определенных строк в стиле С приведет к сравнению значений указателей, а не самих строк.
const char ca1[] = "A string example";
const char ca2[] = "A different string";
if (ca1 < ca2) // непредсказуемо: сравниваются два адреса
Помните, что при использовании массива в действительности используются указатели на их первый элемент (см. раздел 3.5.3). Следовательно, это условие фактически сравнивает два значения const char*. Эти указатели содержат адреса разных объектов, поэтому результат такого сравнения непредсказуем.
Чтобы сравнить строки, а не значения указателей, можем использовать функцию strcmp(). Она возвращает значение 0, если строки равны, положительное или отрицательное значение, в зависимости от того, больше ли первая строка второй или меньше.
if (strcmp(ca1, ca2) < 0) // то же, что и сравнение строк s1 < s2
За размер строки отвечает вызывающая сторонаКонкатенация и копирование строк в стиле С также весьма отличается от таких же операций с библиотечным типом string. Например, если необходима конкатенация строк s1 и s2, определенных выше, то это можно сделать так:
// инициализировать largeStr результатом конкатенации строки s1,
// пробела и строки s2
string largeStr = s1 + " " + s2;
Подобное с двумя массивами, ca1 и ca2, было бы ошибкой. Выражение ca1 + ca2 попытается сложить два указателя, что некорректно и бессмысленно.
Вместо этого можно использовать функции strcat() и strcpy(). Но чтобы использовать эти функции, им необходимо передать массив для хранения результирующей строки. Передаваемый массив должен быть достаточно большим, чтобы содержать созданную строку, включая нулевой символ в конце. Хотя представленный здесь код следует традиционной схеме, потенциально он может стать причиной серьезной ошибки.
// катастрофа, если размер largeStr вычислен ошибочно
strcpy(largeStr, ca1); // копирует ca1 в largeStr
strcat(largeStr, " "); // добавляет пробел в конец largeStr
strcat(largeStr, ca2); // конкатенирует ca2 с largeStr
Проблема в том, что можно легко ошибиться в расчете необходимого размера largeStr. Кроме того, при каждом изменении значения, которые следует сохранить в largeStr, необходимо перепроверить правильность вычисления его размера. К сожалению, код, подобный этому, широко распространен в программах. Такие программы подвержены ошибкам и часто приводят к серьезным проблемам защиты.
Для большинства приложений не только безопасней, но и эффективней использовать библиотечный тип string, а не строки в стиле С.
Упражнения раздела 3.5.4Упражнение 3.37. Что делает следующая программа?
const char ca[] = {'h', 'e', 'l', 'l', 'o'};
const char *cp = ca;
while (*cp) {
cout << *cp << endl;
++cp;
}
Упражнение 3.38. В этом разделе упоминалось, что не только некорректно, но и бессмысленно пытаться сложить два указателя. Почему сложение двух указателей бессмысленно?
Упражнение 3.39. Напишите программу, сравнивающую две строки. Затем напишите программу, сравнивающую значения двух символьных строк в стиле С.
Упражнение 3.40. Напишите программу, определяющую два символьных массива, инициализированных строковыми литералами. Теперь определите третий символьный массив для содержания результата конкатенации этих двух массивов. Используйте функции strcpy() и strcat() для копирования этих двух массивов в третий.
3.5.5. Взаимодействие с устаревшим кодом
Множество программ С++ было написано до появления стандартной библиотеки, поэтому они не используют библиотечные типы string и vector. Кроме того, многие программы С++ взаимодействуют с программами, написанными на языке С или других языках, которые не могут использовать библиотеку С++. Следовательно, программам, написанным на современном языке С++, вероятно, придется взаимодействовать с кодом, который использует символьные строки в стиле С и/или массивы. Библиотека С++ предоставляет средства, облегчающие такое взаимодействие.
Совместное использование библиотечных строки строк в стиле СВ разделе 3.2.1 была продемонстрирована возможность инициализации строки класса string строковым литералом:
string s("Hello World"); // s содержит Hello World
В общем, символьный массив с нулевым символом в конце можно использовать везде, где используется строковый литерал.
• Символьный массив с нулевым символом в конце можно использовать для инициализации строки класса string или присвоения ей.
• Символьный массив с нулевым символом в конце можно использовать как один из операндов (но не оба) в операторе суммы класса string или как правый операнд в составном операторе присвоения (+=) класса string.
Однако нет никакого простого способа использовать библиотечную строку там, где требуется строка в стиле С. Например, невозможно инициализировать символьный указатель объектом класса string. Тем не менее класс string обладает функцией-членом c_str(), зачастую позволяющей выполнить желаемое.
char *str = s; // ошибка: нельзя инициализировать char* из string
const char *str = s.c_str(); // ok
Имя функции c_str() означает, что она возвращает символьную строку в стиле С. Таким образом, она возвращает указатель на начало символьного массива с нулевым символом в конце, содержащим те же символы, что и строка. Тип указателя const char* не позволяет изменять содержимое массива.
Допустимость массива, возвращенного функцией c_str(), не гарантируется. Любое последующее использование указателя s, способное изменить его значение, может сделать этот массив недопустимым.
Если программа нуждается в продолжительном доступе к содержимому массива, возвращенного функцией c_str(), то следует создать его копию.
Использование массива для инициализации вектораВ разделе 3.5.1 упоминалось о том, что нельзя инициализировать встроенный массив другим массивом. Инициализировать массив из вектора также нельзя. Однако можно использовать массив для инициализации вектора. Для этого необходимо определить адрес первого подлежащего копированию элемента и элемента, следующего за последним.
int int_arr[] = {0, 1, 2, 3, 4, 5};

