Главная страница

Язык программирования C Пятое издание


Скачать 1.85 Mb.
НазваниеЯзык программирования C Пятое издание
Дата15.07.2019
Размер1.85 Mb.
Формат файлаpdf
Имя файла620354-www.libfox.ru.pdf
ТипДокументы
#84130
страница25 из 54
1   ...   21   22   23   24   25   26   27   28   ...   54
Упражнение 9.36. Может ли контейнер иметь емкость, меньшую, чем его размер?
Упражнение 9.37. Почему контейнеры list и array не имеют функции-члена capacity()?
Упражнение 9.38. Напишите программу, позволяющую исследовать рост вектора в библиотеке, которую вы используете.
Упражнение 9.39. Объясните, что выполняет следующий фрагмент программы: vector<string> svec; svec.reserve(1024); string word; while (cin >> word) svec.push_back(word); svec.resize(svec.size() + svec.size()/2);
Упражнение 9.40. Если программа в предыдущем упражнении читает 256 слов, какова ее вероятная емкость после вызова функции resize()? Что, если она читает 512, 1 000 или 1 048
слов?
9.5. Дополнительные операции со строками
Page 456/1103

Кроме операций, общих для всех последовательных контейнеров, тип string предоставляет множество дополнительных. По большей части, эти дополнительные операции либо обеспечивают взаимодействие класса string и символьных массивов в стиле С, либо являются дополнительными версиями функций, позволяющими использовать индексы вместо итераторов.
Библиотека string определяет множество функций, которые, к счастью, следуют единому шаблону. С учетом количества обсуждаемых функций этот раздел может показаться слишком громоздким при первом чтении; поэтому сначала его можно просто просмотреть.
Впоследствии, имея представление о существующих видах операций, можно при необходимости вернуться и изучить подробности использования конкретной функции.
9.5.1. Дополнительные способы создания строк
В дополнение к конструкторам, описанным в разделе 3.2.1, и конструкторам, общим для всех последовательных контейнеров (см. табл. 9.3), тип string предоставляет еще три конструктора, описанные в табл. 9.11.
Таблица 9.11. Дополнительные способы создания строк Все значения n, len2 и pos2
являются беззнаковыми. string s(cp, n); Строка s — копия первых n символов из массива, на который указывает cp. У того массива должно быть по крайней мере n символов string s(s2,
pos2); Строка s — копия символов из строки s2, начиная с позиции по индексу pos2. Если pos2 > s2.size(), результат непредсказуем string s(s2, pos2, len2); Строка s — копия len2
символов из строки s2, начиная с позиции по индексу pos2. Если pos2 > s2.size(), то результат непредсказуем. Независимо от значения len2, копируется по крайней мере s2.size()
- pos2 символов
Конструкторы, получающие тип string или const char*, получают дополнительные
(необязательные) аргументы, позволяющие задать количество копируемых символов. При передаче строки можно также указать индекс начала копирования: const char *cp = "Hello World!!!"; // массив с нулевым символом в конце char noNull[] = {'H', 'i' }; // без нулевого символа в конце string s1(cp); // копирует cp до нулевого символа;
// s1 == "Hello World!!!" string s2(noNull,2); // копирует два символа из noNull; s2 == "Hi" string s3(noNull); // непредсказуемо: noNull не завершается null
Page 457/1103
string s4(cp + 6, 5); // копирует 5 символов, начиная с cp[6];
// s4 == "World" string s5(s1, 6, 5); // копирует 5 символов, начиная с s1[6];
// s5 == "World" string s6(s1, 6); // копирует от s1[6] до конца s1;
// s6 == "World!!!" string s7(s1, 6, 20); // ok, копирует только до конца s1;
// s7 == "World!!!" string s8(s1, 16); // передает исключение out_of_range
Обычно строка создается из типа const char*. Массив, на который указывает указатель,
должен завершаться нулевым символом; символы копируются до нулевого символа. Если передается также количество, массив не обязан заканчиваться нулевым символом. Если количество не указано и нет нулевого символа или если указанное количество больше размера массива, результат непредсказуем.
При копировании из строки можно предоставить необязательный параметр исходной позиции и количество копируемых символов. Исходная позиция должна быть меньше или равна размеру переданной строки. Если исходная позиция больше размера, то конструктор передаст исключение out_of_range (см. раздел 5.6). При передаче количества копирование начинается с указанной позиции. Независимо от количества запрошенных символов,
копирование осуществляется до размера строки, но не более. Функция substr()
Функция substr() (представленная в табл. 9.12) возвращает копию части или всей исходной строки. Ей можно передать (необязательно) начальную позицию и количество копируемых символов: string s("hello world"); string s2 = s.substr(0, 5); // s2 = hello
Page 458/1103
string s3 = s.substr(6); // s3 = world string s4 = s.substr(6, 11); // s3 = world string s5 = s.substr(12); // передает исключение out_of_range
Если начальная позиция превышает размер исходной строки, функция substr() передает исключение out_of_range (см. раздел 5.6). Если начальная позиция в сумме с количеством копируемых символов превосходит размер строки, то копирование осуществляется только до конца строки.
Таблица 9.12. Функция substr() s.substr(pos, n) Возвращает строку, содержащую n символов из строки s, начиная с позиции pos. По умолчанию параметр pos имеет значение 0. Параметр n по умолчанию имеет значение, подразумевающее копирование всех символов строки s,
начиная с позиции pos Упражнения раздела 9.5.1
Упражнение 9.41. Напишите программу, инициализирующую строку из вектора vector<char>.
Упражнение 9.42. Учитывая, что символы в строку следует читать по одному и заранее известно, что прочитать предстоит по крайней мере 100 символов, как можно было бы улучшить производительность программы?
9.5.2. Другие способы изменения строки
Тип string поддерживает операторы присвоения последовательного контейнера, а также функции assign(), insert() и erase() (см. раздел 9.2.5, раздел 9.3.1 и раздел 9.3.3). В нем также определены дополнительные версии функций insert() и erase().
В дополнение к обычным версиям функций insert() и erase(), которые получают итераторы,
тип string предоставляет их версии, получающие индекс. Индекс указывает начальный элемент для функции erase() или начальную позицию для функции insert(): s.insert(s.size(), 5, '!'); // вставить пять восклицательных знаков
// в конец строки s s.erase(s.size() - 5, 5); // удалить последние пять символов из
//
Page 459/1103
строки s
Библиотека string предоставляет также версии функций insert() и assign(), получающие массивы символов в стиле С. Например, символьный массив с нулевым символом в конце можно использовать как значение, передаваемое функциям insert() и assign(): const char *cp = "Stately, plump Buck"; s.assign(cp, 7); // s == "Stately" s.insert(s.size(), cp + 7); // s == "Stately, plump Buck"
Сначала содержимое строки s заменяется при вызове функции assign(). Присваиваемые строке s символы — это семь символов из начала массива, на который указывает указатель cp. Количество запрашиваемых символов должно быть меньше или равно количеству символов массива (исключая завершающий нулевой символ), на который указывает cp.
Когда происходит вызов функции insert() для строки s, подразумевается вставка символов перед несуществующим элементом в позиции s[size()]. В данном случае копируются символы,
начиная с седьмого символа cp и до завершающего нулевого символа.
Символы для функций insert() и assign() можно также указать как исходящие из другой строки или ее подстроки: string s = "some string", s2 = "some other string"; s.insert(0, s2); // вставить копию s2 перед позицией 0 в s
// вставить s2.size() символов из s2,
// начиная с позиции s2[0] перед s[0] s.insert(0, s2, 0, s2.size()); Функции append() и replace()
Класс string определяет две дополнительные функции-члена, append() и replace(), способные изменить содержимое строки. Все эти функции описаны в табл. 9.13. Функция append() —
упрощенный способ вставки в конец: string s("C++ Primer"), s2 = s; // инициализация строк s и s2
// текстом "С++ Primer" s.insert(s.size(), " 4th Ed."); // s == "С++ Primer 4th Ed."
Page 460/1103
s2.append(" 4th Ed."); // эквивалент: добавление " 4th Ed." к s2;
// s == s2
Функция replace() — упрощенный способ вызова функций erase() и insert():
// эквивалентный способ замены "4th" на "5th" s.erase(11, 3); // s == "С++ Primer Ed." s.insert(11, "5th"); // s == "С++ Primer 5th Ed."
// начиная с позиции 11, удалить три символа, а затем вставить "5th" s2.replace(11, 3, "5th"); // эквивалент: s == s2
В вызове функции replace() вставляемый текст может быть того же размера, что и удаляемый. Но можно вставить большую или меньшую строку: s.replace(11, 3, "Fifth"); // s == "С++ Primer Fifth Ed."
В этом вызове удаляются три символа, но вместо них вставляются пять.
Таблица 9.13. Функции изменения содержимого строки s.insert( pos , args ) Вставка символов, определенных аргументом args , перед позицией pos . Позиция pos может быть задана индексом или итератором. Версии, получающие индекс, возвращают ссылку на строку s, а получающие итератор возвращают итератор, обозначающий первый вставленный символ s.erase( pos , len ) Удаляет
Page 461/1103
len символов, начиная с позиции pos . Если аргумент len пропущен, удаляет символы от позиции pos до конца строки s. Возвращает ссылку на строку s s.assign( args ) Заменяет символы строки s согласно аргументу args . Возвращает ссылку на строку s s.append( args ) Добавляет аргумент args к строке s. Возвращает ссылку на строку s s.replace( range , args ) Удаляет диапазон range символов из строки s и заменяет их символами, заданными аргументом args . Диапазон задан либо индексом и длиной, либо парой итераторов. Возвращает ссылку на строку s Аргументы args могут быть одним из следующих: функции append() и assign() могут использовать все формы. Строка str должна быть отлична от s, а итераторы b и е не могут принадлежать строке s str Строка str str, pos, len До len символов из строки str, начиная с позиции pos cp, len
До len символов из символьного массива, на который указывает указатель cp cp
Завершающийся нулевым символом массив, на который указывает указатель cp n, c n копий символа с b, e Символы в диапазоне, указанном итераторами b и е
Список инициализации Разделяемый запятыми список символов, заключенный в фигурные скобки Аргументы args для функций replace() и insert() зависят от того, использован ли диапазон или позиция replace(pos,len, args ) replace(b,е, args ) insert(pos, args ) insert(iter, args ) Возможные аргументы args Да Да Да Нет str Да Нет Да Нет str, pos, len Да Да Да Нет cp, len Да Да Нет Нет cp Да Да
Да Да n, с Нет Да Нет Да b2, e2 Нет Да Нет Да список инициализации Множество способов изменить строку
Функции append(), assign(), insert() и replace(), перечисленные в табл. 9.13, имеют несколько перегруженных версий. Аргументы этих функций зависят от того, как заданы добавляемые символы и какая часть строки изменится. К счастью, у этих функций общий интерфейс.
У функций assign() и append() нет необходимости определять изменяемые части строки:
функция assign() всегда заменяет все содержимое строки, а функция append() всегда добавляет в конец строки.
Page 462/1103

Функция replace() предоставляет два способа определения диапазона удаления символов.
Диапазон можно определить по позиции и длине или парой итераторов. Функция insert()
предоставляет два способа определения позиции вставки: при помощи индекса или итератора. В любом случае новый элемент (элементы) вставляется перед указанным индексом или итератором.
Существует несколько способов определения символов, добавляемых в строку. Новые символы могут быть взяты из другой строки, из указателя на символ, из заключенного в фигурные скобки списка символов или как символ и как число. Когда символы исходят из строки или указателя на символ, можно передать дополнительные аргументы, указывающие,
копируются ли все символы аргумента или только часть.
Не каждая функция поддерживает все версии этих аргументов. Например, нет версии функции insert(), получающей индекс и список инициализации. Аналогично, если необходимо определить точку вставки, используя итератор, невозможно будет впоследствии передать символьный указатель как источник для новых символов. Упражнения раздела 9.5.2
Упражнение 9.43. Напишите функцию, получающую три строки: s, oldVal и newVal. Используя итераторы, а также функции insert(), и erase() замените все присутствующие в строке s экземпляры строки oldVal строкой newVal. Проверьте функцию на примере замены таких общепринятых сокращений, как "tho" на "though" и "thru" на "through".
Упражнение 9.44. Перепишите предыдущую функцию так, чтобы использовались индекс и функция replace().
Упражнение 9.45. Напишите функцию, получающую строку, представляющую имя и две другие строки, представляющие префикс, такой, как "Mr." или "Ms.", а также суффикс, такой,
как "Jr." или "III". Используя итераторы, а также функции insert() и append(), создайте новую строку с суффиксом и префиксом, добавленным к имени.
Упражнение 9.46. Перепишите предыдущее упражнение, используя на сей раз позицию,
длину и функцию insert().
9.5.3. Операции поиска строк
Класс string предоставляет шесть вариантов функций поиска, у каждой из которых есть четыре перегруженных версии. Функции-члены поиска и их аргументы описаны в табл. 9.14.
Каждая из них возвращает значение типа string::size_type, являющееся индексом найденного элемента. Если соответствие не найдено, функции возвращают статический член (см. раздел
7.6) по имени string::npos. Библиотека определяет значение npos как -1 типа const string::size_type. Поскольку npos имеет беззнаковый тип, это означает, что значение npos соответствует наибольшему возможному размеру, который может иметь любая строка (см.
раздел 2.1.2).
Таблица 9.14. Строковые функции поиска Функции поиска возвращают индекс искомого символа или значение npos, если искомое не найдено s.find( args ) Ищет первое местоположение аргумента args в строке s s.rfind(
Page 463/1103
args ) Ищет последнее местоположение аргумента args в строке s s.find_first_of( args ) Ищет первое местоположение любого символа аргумента args в строке s s.find_last_of( args ) Ищет последнее местоположение любого символа аргумента args в строке s s.find_first_not_of( args ) Ищет первое местоположение символа в строке s, который отсутствует в аргументе args s.find_last_not_of( args ) Ищет последнее местоположение символа в строке s, который отсутствует в аргументе args Аргумент args может быть следующим с, pos Поиск символа с, начиная с позиции pos в строке s. По умолчанию pos имеет значение 0 s2, pos Поиск строки s2, начиная с позиции pos в строке s.
По умолчанию pos имеет значение 0 cp, pos Поиск строки с завершающим нулевым символом в стиле С, на которую указывает указатель cp. Поиск начинается с позиции pos в строке s. По умолчанию pos имеет значение 0 cp, pos, n Поиск первых n символов в массиве, на который указывает указатель cp. Поиск начинается с позиции pos в строке s. Аргумент pos и n не имеет значения по умолчанию
Функции поиска строк возвращают значение беззнакового типа string::size_type. Поэтому не следует использовать переменную типа int или другого знакового типа для содержания значения, возвращаемого этими функциями (см. раздел 2.1.2).
Самой простой является функция find(). Она ищет первое местоположение переданного аргумента и возвращает его индекс или значение npos, если соответствующее значение не найдено: string name("AnnaBelle"); auto pos1 = name.find("Anna"); // pos1 == 0
Возвращает значение 0, т.е. индекс, по которому подстрока "Anna" расположена в строке "AnnaBelle".
Поиск (и другие операции со строками) чувствительны к регистру. При поиске в строке регистр имеет значение: string lowercase("annabelle"); pos1 = lowercase.find("Anna"); // pos1 == npos
Этот код присвоит переменной pos1 значение npos, поскольку строка "Anna" не соответствует строке "anna".
Немного сложней искать соответствие любому символу в строке. Например, следующий код
Page 464/1103
находит первую цифру в переменной name: string numbers("0123456789"), name("r2d2");
// возвращает 1, т.е. индекс первой цифры в имени auto pos = name.find_first_of(numbers);
Кроме поиска соответствия, вызвав функцию find_first_not_of(), можно искать первую позицию, которая не соответствует искомому аргументу. Например, для поиска первого нечислового символа в строке можно использовать следующий код: string dept("03714p3");
// возвращает 5 - индекс символа 'p' auto pos = dept.find_first_not_of(numbers); Откуда начинать поиск
Функциям поиска можно передать необязательный аргумент исходной позиции. Этот необязательный аргумент указывает позицию, с которой начинается поиск. По умолчанию значением этого аргумента является нуль. Общепринятой практикой программирования является использование этого аргумента в цикле перебора строки при поиске всех местоположений искомого значения. string::size_type pos = 0;
// каждая итерация находит следующее число в имени while ((pos = name.find_first_of(numbers, pos))
!= string::npos) { cout << "found number at index: " << pos
<< " element is " << name[pos] << endl;
++pos; // перевести на следующий символ
}
Условие цикла while присваивает переменной pos индекс первой встретившейся цифры,
начиная с текущей позиции pos. Пока функция find_first_of() возвращает допустимый индекс,
результат отображается, а значение pos увеличивается.
Если не увеличивать значение переменной pos в конце этого цикла, он никогда не завершится, поскольку при последующих итерациях поиск начнется сначала и найден будет тот же элемент. Поскольку значение npos так и не будет возвращено, цикл никогда не завершится. Поиск в обратном направлении
Page 465/1103

Использованные до сих пор функции поиска выполняется слева направо (т.е. от начала к концу). Библиотека предоставляет аналогичный набор функций, которые просматривают строку справа налево (т.е. от конца к началу). Функция-член rfind() ищет последнюю, т.е.
расположенную справа, позицию искомой подстроки. string river("Mississippi"); auto first_pos = river.find("is"); // возвращает 1 auto last_pos = river.rfind("is"); // возвращает 4
Функция find() возвращает индекс 1, указывая, что подстрока "is" первый раз встречается,
начиная с позиции 1, а функция rfind() возвращает индекс 4, указывая начало последнего местонахождения подстроки "is".
Функция find_last() аналогична функции find_first(), но возвращает последнее местоположение, а не первое.
• Функция find_last_of() ищет последний символ, который соответствует любому элементу искомой строки.
• Функция find_last_not_of() ищет последний символ, который не соответствует ни одному элементу искомой строки.
Каждая из этих функций имеет второй необязательный аргумент, который указывает позицию начала поиска. Упражнения раздела 9.5.3
Упражнение 9.47. Напишите программу, которая находит в строке "ab2c3d7R4E6" каждую цифру, а затем каждую букву. Напишите две версии программы: с использованием функции find_first_of() и функции find_first_not_of().
Упражнение 9.48. С учетом определения переменных name = "r2d2" и numbers =

1   ...   21   22   23   24   25   26   27   28   ...   54


написать администратору сайта