Класс insert_iterator
Описывает адаптер итератора, удовлетворяющий требованиям итератора вывода. Он вставляет элементы, а не перезаписывает их в последовательность. Таким образом он предоставляет семантику, которая отличается от семантики перезаписи, предоставляемой итераторами последовательности C++ и ассоциативными контейнерами. Класс insert_iterator шаблонизируется в адаптируемом типе контейнера.
Синтаксис
template class insert_iterator;
Параметры
Контейнер
Тип контейнера, в который итератор insert_iterator вставит элементы.
Замечания
Контейнер типа Container должен соответствовать требованиям для контейнера с переменным размером и иметь функцию-член с двумя аргументами, в которой параметры имеют тип Container::iterator и Container::value_type которые возвращают тип Container::iterator . Последовательности из стандартной библиотеки С++ и упорядоченные ассоциативные контейнеры удовлетворяют данным требованиям и могут быть адаптированы к использованию в сочетании с insert_iterator s. Для ассоциативных контейнеров аргумент позиции обрабатывается как подсказка, которая потенциально может увеличить или снизить производительность в зависимости от эффективности подсказки. Итератор insert_iterator всегда необходимо инициализировать с его контейнером.
Конструкторы
| Конструктор | Description |
|---|---|
| insert_iterator | Создает итератор insert_iterator , добавляющий элемент в указанную позицию в контейнере. |
Определения типов
| Введите имя | Description |
|---|---|
| container_type | Тип, представляющий контейнер, в который будет осуществляться вставка общего типа. |
| reference | Тип, который предоставляет ссылку на элемент последовательности под управлением связанного контейнера. |
Операторы
| Operator | Description |
|---|---|
| operator* | Оператор разыменования используется для реализации выражения итератора вывода * i = x для вставки общего типа. |
| оператор++ | Увеличивает insert_iterator до следующего местоположения, в котором можно сохранить значение. |
| operator= | Оператор присваивания, используемый для реализации выражения итератора вывода * i = x для вставки общего типа. |
Требования
Заголовок:
Пространство имен: std
insert_iterator::container_type
Тип, представляющий контейнер, в который будет осуществляться вставка общего типа.
typedef Container container_type;
Замечания
Этот тип является синонимом для параметра-шаблона Container.
Пример
// insert_iterator_container_type.cpp // compile with: /EHsc #include #include #include int main( ) < using namespace std; listL1; insert_iterator ::container_type L2 = L1; inserter ( L2, L2.end ( ) ) = 20; inserter ( L2, L2.end ( ) ) = 10; inserter ( L2, L2.begin ( ) ) = 40; list ::iterator vIter; cout /* Output: The list L2 is: ( 40 20 10 ). */
insert_iterator::insert_iterator
Создает итератор insert_iterator , добавляющий элемент в указанную позицию в контейнере.
insert_iterator(Container& _Cont, typename Container::iterator _It);
Параметры
_Продолжение
Контейнер, в который insert_iterator вставляет элементы.
_It
Позиция для вставки.
Замечания
Все контейнеры имеют функцию-член вставки, которая вызывается insert_iterator . Для ассоциативных контейнеров параметр позиции — это просто предложение. Функция вставки предоставляет удобный способ вставки значений.
Пример
// insert_iterator_insert_iterator.cpp // compile with: /EHsc #include #include #include int main( ) < using namespace std; int i; list ::iterator L_Iter; list L; for (i = 1 ; i < 4 ; ++i ) < L.push_back ( 10 * i ); >cout > Iter(L, L.end ( ) ); *Iter = 300; cout /* Output: The list L is: ( 10 20 30 ). After the insertions, the list L is: ( 2 10 20 30 300 ). */
insert_iterator::operator*
Разыменовывает итератор вставки и возвращает адреса элемента.
insert_iterator& operator*();
Возвращаемое значение
Функция-член возвращает значение адресованного элемента.
Замечания
Используется для реализации выражения итератора выходных данных *Iter. = Если Iter это итератор, который обращается к элементу в последовательности, то *Iter = заменяет этот элемент значением и не изменяет общее количество элементов в последовательности.
Пример
// insert_iterator_op_deref.cpp // compile with: /EHsc #include #include #include int main( ) < using namespace std; int i; list ::iterator L_Iter; list L; for (i = 0 ; i < 4 ; ++i ) < L.push_back ( 2 * i ); >cout > Iter(L, L.begin ( ) ); *Iter = 10; *Iter = 20; *Iter = 30; cout /* Output: The original list L is: ( 0 2 4 6 ). After the insertions, the list L is: ( 10 20 30 0 2 4 6 ). */
insert_iterator::operator++
Увеличивает insert_iterator до следующего местоположения, в котором можно сохранить значение.
insert_iterator& operator++(); insert_iterator operator++(int);
Параметры
insert_iterator , адресующий следующее местоположение, в котором можно сохранить значение.
Замечания
Операторы preincrementation и postincrementation возвращают одинаковый результат.
Пример
// insert_iterator_op_incr.cpp // compile with: /EHsc #include #include #include int main( ) < using namespace std; int i; vectorvec; for (i = 1 ; i < 5 ; ++i ) < vec.push_back ( i ); >vector ::iterator vIter; cout << "The vector vec is:\n ( "; for ( vIter = vec.begin ( ) ; vIter != vec.end ( ); vIter++ ) cout << *vIter << " "; cout << ")." << endl; insert_iterator ii ( vec, vec.begin ( ) ); *ii = 30; ii++; *ii = 40; ii++; *ii = 50; cout /* Output: The vector vec is: ( 1 2 3 4 ). After the insertions, the vector vec becomes: ( 30 40 50 1 2 3 4 ). */
insert_iterator::operator=
Вставляет значение в контейнер и возвращает итератор, который обновлен и указывает на новый элемент.
insert_iterator& operator=( typename Container::const_reference val,); insert_iterator& operator=( typename Container::value_type&& val);
Параметры
Val
Значение, которое должно быть присвоено контейнеру.
Возвращаемое значение
Ссылка на элемент, вставленный в контейнер.
Замечания
Первый оператор-член вычисляет
Iter = container->insert(Iter, val) ;
затем возвращает *this .
Второй оператор-член вычисляет
Iter = container->insert(Iter, std::move(val));
затем возвращает *this .
Пример
// insert_iterator_op_assign.cpp // compile with: /EHsc #include #include #include int main( ) < using namespace std; int i; list ::iterator L_Iter; list L; for (i = 0 ; i < 4 ; ++i ) < L.push_back ( 2 * i ); >cout > Iter(L, L.begin ( ) ); *Iter = 10; *Iter = 20; *Iter = 30; cout /* Output: The original list L is: ( 0 2 4 6 ). After the insertions, the list L is: ( 10 20 30 0 2 4 6 ). */
insert_iterator::reference
Тип, который предоставляет ссылку на элемент последовательности под управлением связанного контейнера.
typedef typename Container::reference reference;
Замечания
Тип, который описывает ссылку на элемент последовательности под управлением связанного контейнера.
Пример
// insert_iterator_container_reference.cpp // compile with: /EHsc #include #include #include int main( ) < using namespace std; listL; insert_iterator iivIter( L , L.begin ( ) ); *iivIter = 10; *iivIter = 20; *iivIter = 30; list::iterator LIter; cout << "The list L is: ( "; for ( LIter = L.begin ( ) ; LIter != L.end ( ); LIter++ ) cout << *LIter << " "; cout << ")." << endl; insert_iterator::reference RefFirst = *(L.begin ( )); cout /* Output: The list L is: ( 10 20 30 ). The first element in the list L is: 10. */
Основы работы со строками в C++
В языке C++ для удобной работы со строками есть класс string, для использования которого необходимо подключить заголовочный файл string.
Строки можно объявлять и одновременно присваивать им значения:
string S1, S2 = «Hello»;
Строка S1 будет пустой, строка S2 будет состоять из 5 символов.
К отдельным символам строки можно обращаться по индексу, как к элементам массива или C-строк. Например S[0] — это первый символ строки.
Для того, чтобы узнать длину строки можно использовать метод size() строки. Например, последний символ строки S это S[S.size() — 1 ].
Строки в языке C++ могут
Конструкторы строк
Строки можно создавать с использованием следующих конструкторов:
string() — конструктор по умолчанию (без параметров) создает пустую строку.
string(string & S) — копия строки S
string( size_t n, char c) — повторение символа c заданное число n раз.
string(size_t c) — строка из одного символа c .
string(string & S, size_t start, size_t len) — строка, содержащая не более, чем len символов данной строки S , начиная с символа номер start .
Конструкторы можно вызывать явно, например, так:
В этом примере явно вызывается конструктор string для создания строки, состоящей из 10 символов ‘z’ .
Неявно конструктор вызывается при объявлении строки с указанием дополнительных параметров. Например, так:
Подробней о конструкторах для строк читайте здесь.
Ввод-вывод строк
Строка выводится точно так же, как и числовые значения:
Для считывания строки можно использовать операцию «>>» для объекта cin:
В этом случае считывается строка из непробельных символов, пропуская пробелы и концы строк. Это удобно для того, чтобы разбивать текст на слова, или чтобы читать данные до конца файла при помощи while (cin >> S) .
Можно считывать строки до появления символа конца строки при помощи функции getline. Сам символ конца строки считывается из входного потока, но к строке не добавляется:
Арифметические операторы
Со строками можно выполнять следующие арифметические операции:
= — присваивание значения.
+= — добавление в конец строки другой строки или символа.
+ — конкатенация двух строк, конкатенация строки и символа.
== , != — посимвольное сравнение.
< , >, = — лексикографическое сравнение.
То есть можно скопировать содержимое одной строки в другую при помощи операции S1 = S2, сравнить две строки на равенство при помощи S1 == S2, сравнить строки в лексикографическом порядке при помощи S1 < S2, или сделать сложение (конкатенацию) двух строк в виде S = S1 + S2.
Подробней об операторах для строк читайте здесь.
Методы строк
У строк есть разные методы, многие из них можно использовать несколькими разными способами (с разным набором параметров).
Рассмотрим эти методы подробней.
size
Метод size() возращает длину длину строки. Возвращаемое значение является беззнаковым типом (как и во всех случаях, когда функция возращает значение, равное длине строке или индексу элемента — эти значения беззнаковые). Поэтому нужно аккуратно выполнять операцию вычитания из значения, которое возвращает size(). Например, ошибочным будет запись цикла, перебирающего все символы строки, кроме последнего, в виде for (int i = 0; i < S.size() - 1; ++i).
Кроме того, у строк есть метод length(), который также возвращает длину строки.
Подробней о методе size.
resize
S.resize(n) — Изменяет длину строки, новая длина строки становится равна n. При этом строка может как уменьшится, так и увеличиться. Если вызвать в виде S.resize(n, c) , где c — символ, то при увеличении длины строки добавляемые символы будут равны c.
Подробней о методе resize.
clear
S.clear() — очищает строчку, строка становится пустой.
Подробней о методе clear.
empty
S.empty() — возвращает true, если строка пуста, false — если непуста.
Подробней о методе empty.
push_back
S.push_back(c) — добавляет в конец строки символ c, вызывается с одним параметром типа char.
Подробней о методе push_back.
append
Добавляет в конец строки несколько символов, другую строку или фрагмент другой строки. Имеет много способов вызова.
S.append(n, c) — добавляет в конец строки n одинаковых символов, равных с. n имеет целочисленный тип, c — char.
S.append(T) — добавляет в конец строки S содержимое строки T. T может быть объектом класса string или C-строкой.
S.append(T, pos, count) — добавляет в конец строки S символы строки T начиная с символа с индексом pos количеством count.
Подробней о методе append.
erase
S.erase(pos) — удаляет из строки S с символа с индексом pos и до конца строки.
S.erase(pos, count) — удаляет из строки S с символа с индексом pos количеством count или до конца строки, если pos + count > S.size().
Подробней о методе erase.
insert
Вставляет в середину строки несколько символов, другую строку или фрагмент другой строки. Способы вызова аналогичны способам вызова метода append, только первым параметром является значение i — позиция, в которую вставляются символы. Первый вставленный символ будет иметь индекс i, а все символы, которые ранее имели индекс i и более сдвигаются вправо.
S.insert(i, n, c) — вставить n одинаковых символов, равных с. n имеет целочисленный тип, c — char.
S.insert(i, T) — вставить содержимое строки T. T может быть объектом класса string или C-строкой.
S.insert(i, T, pos, count) — вставить символы строки T начиная с символа с индексом pos количеством count.
Подробней о методе insert.
substr
S.substr(pos) — возвращает подстроку данной строки начиная с символа с индексом pos и до конца строки.
S.substr(pos, count) — возвращает подстроку данной строки начиная с символа с индексом pos количеством count или до конца строки, если pos + count > S.size().
Подробней о методе substr.
replace
Заменяет фрагмент строки на несколько равных символов, другую строку или фрагмент другой строки. Способы вызова аналогичны способам вызова метода append, только первыми двумя параметрами являются два числа: pos и count. Из данной строки удаляется count символов, начиная с символа pos, и на их место вставляются новые символы.
S.replace(pos, count, n, c) — вставить n одинаковых символов, равных с. n имеет целочисленный тип, c — char.
S.replace(pos, count, T) — вставить содержимое строки T. T может быть объектом класса string или C-строкой.
S.replace(pos, count, T, pos2, count2) — вставить символы строки T начиная с символа с индексом pos количеством count.
Подробней о методе replace.
find
Ищет в данной строке первое вхождение другой строки str. Возвращается номер первого символа, начиная с которого далее идет подстрока, равная строке str. Если эта строка не найдена, то возвращается константа string::npos (которая равна -1, но при этом является беззнаковой, то есть на самом деле является большим безннаковым положительным числом).
Если задано значение pos, то поиск начинается с позиции pos, то есть возращаемое значение будет не меньше, чем pos. Если значение pos не указано, то считается, что оно равно 0 — поиск осуществляется с начала строки.
S.find(str, pos = 0) — искать первое входение строки str начиная с позиции pos. Если pos не задано — то начиная с начала строки S.
S.find(str, pos, n) — искать в данной строке подстроку, равную первым n символам строки str. Значение pos должно быть задано.
Подробней о методе find.
rfind
Ищет последнее вхождение подстроки («правый» поиск). Способы вызова аналогичны способам вызова метода find.
Подробней о методе rfind.
find_first_of
Ищет в данной строке первое появление любого из символов данной строки str. Возвращается номер этого символа или значение string::npos.
Если задано значение pos, то поиск начинается с позиции pos, то есть возращаемое значение будет не меньше, чем pos. Если значение pos не указано, то считается, что оно равно 0 — поиск осуществляется с начала строки.
S.find_first_of(str, pos = 0) — искать первое входение любого символа строки str начиная с позиции pos. Если pos не задано — то начиная с начала строки S.
find_last_of
Ищет в данной строке последнее появление любого из символов данной строки str. Способы вызова и возвращаемое значение аналогичны методу find_first_of.
Подробней о методе find_last_of.
find_first_not_of
Ищет в данной строке первое появление символа, отличного от символов строки str. Способы вызова и возвращаемое значение аналогичны методу find_first_of.
find_last_not_of
Ищет в данной строке последнее появление символа, отличного от символов строки str. Способы вызова и возвращаемое значение аналогичны методу find_first_of.
c_str
Возвращает указать на область памяти, в которой хранятся символы строки, возвращает значение типа char*. Возвращаемое значение можно рассматривать как C-строку и использовать в функциях, которые должны получать на вход C-строку.
Подробней о методе c_str.
Вектора в С++ часть 5 (функции insert(), swap(), shrink_to_fit())
Вектора, позволяют помещать число в любую ячейку вектора (даже если эта ячейка уже занята), пример для понимания:
#include #include using namespace std; int main() < vector vecInt(3,100); ///Создаем вектор из 3 элементов и заполняем его значением 100 vector ::iterator it; it = vecInt.begin(); ///Итератор указывает на vec[0] ///Вектор расширяется теперь до 4 элементов vecInt.insert (it,200); ///И первым элементом записывается 200 ///Вектор расширяется теперь до 5 элементов it = vecInt.begin() + 3;///Вектор указывает на 4 элемент (0-элемент+3-элемента) vecInt.insert(it,300);///И четвертым элементом записывается 300 vecInt.insert(it+1,900);///Вектор расширяется теперь до 6 элементов и 5 элементом записывается 900 cout cout
Работа нашей программы:
CppStudio.com
Vector contains: 200 100 100 300 900 100
Vector max_size: 1073741823
Vector size: 6 New vector size: 10
В 6 строке объявлен вектор размером из трех элементов типа int и сразу же заполнили его числом 100. В строке 7 мы объявляем итератор it , в 8 строке наш итератор указывает на нулевой элемент нашего вектора. В 11 строке мы встречаем новую функцию vector::insert() .
Функция vector::insert() принимает два аргумента (первый – указатель на ячейку вектора, куда будет помещено число, второй – само помещаемое число). Так как итератор it указывает на vecInt[0] , нулевой элемент вектора, то теперь vecInt[0]=200 . Длина вектора соответственно увеличивается на один элемент. В строке 14 итератор it теперь указывает на третий элемент вектора, т. е. vecInt[3] , соответственно назначение строки 15 становиться уже понятно.
В строке 16 число 900 мы записываем в позицию it+1 или vecInt[3+1] . В строках с 19-22 осуществляется вывод вектора, но это должно быть уже Вам понятно. В строке 24 используется функция vector::max_size() , которая выводит максимальный размер вектора, т. е. максимально возможное количество, элементов которое может вместить в себя вектор. В строке 26 встречается новая функция vector::resize () , функция позволяет увеличить размер вектора до заданной величины, в данном случае вектор расширяется до 10 элементов.
Если функция vector::resize() позволяет уменьшить размер вектора, то функция vector::reserve( ) имеет обратное действие, она позволяет расширить вектор до заданной величины, рассмотрим пример:
#include #include using namespace std; int main() < vector vecFirst ,vecSecond; /// Создаем два вектора for ( int i=0; i cout << "vecFirst contains: "; for (int i=0; i
Функции insert()
Вводятся две строки, необходимо в первой строке найти вторую и заключить ее в скобки. "s3.insert(1,s2)" без этой команды программа работает, с этой командой программа зависает. Подскажите в чем проблема.
#include #include #include #include using namespace std; int main()< setlocale(LC_ALL,""); string s1,s2,s3; cout>s1; cout>s2; s3="()"; s3.insert(1,s2); int size = s2.size(); int x = s1.find (s2); while (xcout
Отслеживать
задан 5 июл 2018 в 8:26
43 1 1 серебряный знак 4 4 бронзовых знака
5 ответов 5
Сортировка: Сброс на вариант по умолчанию
Если нужно найти все вхождения строки s2 в s1, то цикл здесь нужен. Проблема в том, что следующее вхождение нужно искать не с начала строки, как вы это делали здесь:
а с определённого индекса, то есть (предыдущий x + длина найденной строки)
x = s1.find(s2, x + s3.size());
int x = s1.find(s2); while (x != string::npos)
Отслеживать
ответ дан 5 июл 2018 в 9:12
Влада Мамутова Влада Мамутова
76 6 6 бронзовых знаков
Например, такая функция вернет вам то что нужно:
string& enclose(string& s1, const string& s2, const char ch1 = '(', const char ch2 = ')') < size_t first = s1.find(s2); if (first != string::npos) < auto p = s1.insert(s1.begin() + first, ch1); s1.insert(p + s2.size() + 1, ch2); >return s1; >
Нет необходимости в дополнительном обьекте.
Отслеживать
ответ дан 5 июл 2018 в 8:53
AR Hovsepyan AR Hovsepyan
15.9k 3 3 золотых знака 14 14 серебряных знаков 30 30 бронзовых знаков
а если нет включения искомой строки? Ваша функция содержит серьезную ошибку
5 июл 2018 в 9:06
К тому же не думаю, что разумно использовать целочисленный тип для возвращаемого значения функции, которая использует отрицательное значение для сигнала об ошибке.
5 июл 2018 в 9:08
@Andrej Levkovitch, нетрудно найти во многих ответах неучтенные деталии и ставить минусы. А разве это делу поможет.
5 июл 2018 в 9:21
я поставил минус потому что в вашем ответе (была) не "неучтенный минус" - а серьезная ошибка, разве нет? Вы с этим не согласны? Но в любом случае, так как ошибка исправлена, мой минус я аннулирую
5 июл 2018 в 9:24
@Andrej Levkovitch, в таких случаях, для общего блага, любезно предупреждают об упущении. Но вы зря аннулировали минус, поскольку побольшому счету я должен был кинуть исключение, если строка не найдена, или как минимум, вывести сообщение на консоль.
5 июл 2018 в 9:32
Через метод find находим позицию начала строки s2 в строке s1. Если find не вернул std::string::npos , значит подстрока найдена, вставляем скобки методом insert .
#include #include int main()< std::string s1,s2; std::cout > s1; std::cout > s2; int pos = s1.find(s2); if(pos != std::string::npos) < s1.insert(pos, "("); s1.insert(pos+s2.length()+1, ")"); std::cout else std::cout
first string: foobar
second string: bar
Sucess!
foo(bar)
Отслеживать
ответ дан 5 июл 2018 в 9:12
Alexshev92 Alexshev92
3,135 6 6 золотых знаков 18 18 серебряных знаков 34 34 бронзовых знака
Ну так а что вы делаете сдесь:
int x = s1.find (s2); while (x
? У вас всегда условие в цикле будет верным!! Так как если искомая строка есть в s1 , то x , конечно, будет меньше size . А если нет, то x будет равен -1 , и тоже меньше чем size .
И зачем вам сдесь вообще цикл? Разве не достаточно простого if ?
int x = s1.find (s2); if (x != -1)
Так все работает.
Отслеживать
ответ дан 5 июл 2018 в 8:53
Andrej Levkovitch Andrej Levkovitch
8,047 2 2 золотых знака 19 19 серебряных знаков 46 46 бронзовых знаков
int x = s1.find (s2); while (x
при осутствии find возвращает std::string::npos == -1 , то есть в любом случае бесконечный цикл. Баг в алгоритме ещё, вы в переменной s1 не удаляете найденную строку, а делаете replace , при s1 == s2 будет опять зависон. Демонстрация этой проблемы:
# include # include int main() < std::string s1("abc"); std::string s2("a"); int size = s2.size(); std::string s3("aa"); int x = std::string::npos ; if (x == -1) std::coutif(not limit) std::cout
std::string::npos == -1 s1=aabc s1=aaabc s1=aaaabc s1=aaaaabc s1=aaaaaabc s1=aaaaaaabc s1=aaaaaaaabc s1=aaaaaaaaabc s1=aaaaaaaaaabc s1=aaaaaaaaaaabc Zavison!