Как добавить элемент в начало строки с
Перейти к содержимому

Как добавить элемент в начало строки с

  • автор:

вставка символа в строку

Задача простая — есть строка, например std::string(«sfsfsgsdshhdfjj»), необходимо вставить через каждый второй символ символ «-«.Не пойму как такое реализовать, пожалуйста подскажите.

Отслеживать
задан 28 апр 2016 в 5:19
1,973 3 3 золотых знака 17 17 серебряных знаков 34 34 бронзовых знака

Не правьте, пожалуйста, вопросы, изменяя метки, меняя точки на запятые и добавляя кавычки/ненужные метки, зарабатывая по +2 репутации. Вносите бОльшие изменения в вопрос, чтобы он был полезней, либо не меняйте его. Это не приносит пользы вопросам и сообществу в целом. Спасибо.

15 сен 2016 в 14:52

@Denis — пожалуйста! Исправлять орфографические ошибки и правила расстановки знаков препинания не нужно? Нет? Делать вопросы более понятными для всех не нужно. Я все исправляю по правилам форума. Я не просто зарабатываю 2 балла репутации — но и делаю полезное дело! И да — это приносит пользу сообществу!

15 сен 2016 в 16:14

Например, вот эта правка не несёт пользы вопросу — кавычки тут не нужны, как и точка после ссылки, есть даже причина для отклонения таких правок — «Правка никак не делает сообщения более простым к прочтению, не упрощает его поиск, точность или доступность. Изменения абсолютно излишни или явно ухудшают читаемость.»

16 сен 2016 в 6:55

3 ответа 3

Сортировка: Сброс на вариант по умолчанию

Самый простой способ, пожалуй, — создать новую строку и посимвольно туда запихивать все это хозяйство.

string s("sfsfsgsdshhdfjj"); string d; for(auto c: s)

Update Как оказалось, не совсем верно понял, дефис надо через два на третий. Примерно так:

string d; for(size_t i = 0; i < s.length(); ++i) < d += s[i++]; if (i < s.length()) < d += s[i]; d += '-'; >> 

Отслеживать
ответ дан 28 апр 2016 в 5:39
219k 15 15 золотых знаков 119 119 серебряных знаков 230 230 бронзовых знаков
я бы добавил: d.reserve(s.length()*2-1)
28 апр 2016 в 5:58

Да, согласен, несколько быстрее. Тут — ideone.com/Jmlwde — сравнение с резервированием, без и с методом вставкой.

28 апр 2016 в 6:17

А вообще, самый быстрый вот такой: ideone.com/B4C7xG объясняю почему: operator[] не выполняет никаких проверок вообще, а operator+= — выполняет. Как минимум — вдруг ёмкость исчерпалась, а значит нужно как бы и памяти добавить. Правило наименьшего оверхеда вкупе с наименьшим удивлением. Ваш вариант ещё и ошибку содержит: всегда добавляется — во конце, хотя не должен вообще. Пруф: ideone.com/VbE5RW

28 апр 2016 в 8:02

Решение @Harry быстрое, а если жалко памяти на два буффера сразу, то можно либо как у вас или так (дополнительной памяти O(1)):

// Резервируем память, что бы исключить реаллокации при вставке s.reserve(s.length()*3/2); for (size_t i = 2; i < s.length(); i+=2) s.insert(i++, 1, '-'); // инкремент тут нужен, что бы уйти с только что вставленного '-' 

Минус: оно медленное за счёт того, что при каждой вставке нужно делать memmove / memcpy для оставшихся символов.

UPD: поправлено под условие (каждый второй символ)

UPD2: самый (пока?) шустрый вариант (дополнительной памяти O(n)):

string str; str.resize(s.length() * 3/2); size_t size = 0; for (size_t i = 0; i < s.length(); ++i) < str[size++] = s[i++]; if (i < s.length()) < str[size++] = s[i]; if (i != s.length() - 1) str[size++] = '-'; >> // ;-) str.resize(size); 

22.6 – Добавление данных к объектам std::string

Добавить строку в конец существующей строки легко, для этого необходимо воспользоваться функцией operator+= , append() или push_back() .

string& string::operator+= (const string& str)
string& string::append (const string& str)

Эти функции добавляют к строке символы str .

  • Обе функции возвращают *this , поэтому их можно объединить в «цепочку».
  • Обе функции вызывают исключение length_error , если результат превышает максимальное количество символов.
string sString("one"); sString += string(" two"); string sThree(" three"); sString.append(sThree); cout 
one two three

Также есть вариант append() , который может добавлять подстроку:

string& string::append (const string& str, size_type index, size_type num)

Эта функция добавляет к строке num символов из строки str , начиная с index .

  • Возвращает *this , поэтому ее можно вставить в «цепочку».
  • Выбрасывает исключение out_of_range , если индекс выходит за пределы строки.
  • Выбрасывает исключение length_error , если результат превышает максимальное количество символов.
string sString("one "); const string sTemp("twothreefour"); // добавляем подстроку строки sTemp, начиная с индекса 3, длиной 5 sString.append(sTemp, 3, 5); cout 
one three

operator+= и append() также имеют версии, которые работают со строками в стиле C.

string& string::operator+= (const char* str)
string& string::append (const char* str)

Эти функции добавляют к строке символы str .

  • Обе функции возвращают *this , поэтому их можно объединить в «цепочку».
  • Обе функции вызывают исключение length_error , если результат превышает максимальное количество символов.
  • str не должна быть равна nullptr .
string sString("one"); sString += " two"; sString.append(" three"); cout 
one two three

Есть еще один дополнительный вариант append() , который работает со строками в стиле C:

string& string::append (const char* str, size_type len)

Добавляет в строку первые len символов строки str .

  • Возвращает *this , поэтому ее можно вставить в «цепочку».
  • Выбрасывает исключение length_error , если результат превышает максимальное количество символов.
  • Игнорирует специальные символы (включая " ).
string sString("one "); sString.append("threefour", 5); cout 
one three

Эта функция опасна, и ее использование не рекомендуется.

Также есть набор функций, которые добавляют символы. Обратите внимание, что имя неоператорной функции для добавления символа – push_back() , а не append() !

string& string::operator+= (char c)
void string::push_back (char c)

Эти функции добавляют к строке символ c .

  • operator+= возвращает *this , чтобы его можно было вставить в «цепочку».
  • Обе функции вызывают исключение length_error , если результат превышает максимальное количество символов.
string sString("one"); sString += ' '; sString.push_back('2'); cout 
one 2

Вам может быть интересно, почему имя этой функции – push_back() , а не append() . Это следует соглашению об именах, используемому для стеков, где push_back() – это функция, которая добавляет один элемент в конец стека. Если вы представляете строку, как стек символов, то для добавления одного символа в ее конец имеет смысл использовать push_back() . Однако, на мой взгляд, отсутствие функции append() выбивается из последовательности!

Оказывается, есть функция append() для символов, которая выглядит так:

string& string::append (size_type num, char c)

Добавляет количество вхождений символа c в строку

  • Возвращает *this , чтобы ее можно было вставить в «цепочку».
  • Выдает исключение length_error , если результат превышает максимальное количество символов.
string sString("aaa"); sString.append(4, 'b'); cout 
aaabbbb

Есть еще один, последний, вариант append() , который вы не поймете, если не знаете, что такое итераторы. Если вы не знакомы с итераторами, можете игнорировать эту функцию.

string& string::append (InputIterator start, InputIterator end)

Добавляет все символы из диапазона [ start , end ) (включая начало, но не включая конец)

  • Возвращает *this , чтобы ее можно было вставить в «цепочку».
  • Выдает исключение length_error , если результат превышает максимальное количество символов.

Урок №206. Вставка символов и строк в std::string

Вставлять символы/строки в std::string можно с помощью функции insert().

string& string::insert(size_type index, const string& str)
string& string::insert(size_type index, const char* str)

Обе функции вставляют символы/строки, начиная с определенного index std::string.

Генерируют исключение length_error, если результат превышает максимально допустимое количество символов.

Во второй версии функции insert() str не должен быть NULL .

std :: string sString ( "bbb" ) ;
std :: cout << sString << std :: endl ; sString . insert ( 2 , std :: string ( "mmm" ) ) ; std :: cout << sString << std :: endl ; sString . insert ( 5 , "aaa" ) ; std :: cout << sString << std :: endl ;

bbb
bbmmmb
bbmmmaaab

А вот версия функции insert(), которая позволяет вставить с определенного index std::string подстроку.

string& string::insert(size_type index, const string& str, size_type startindex, size_type num)

Эта функция вставляет с определенного index std::string указанное количество символов ( num ) строки str , начиная со startindex -а.

Возвращает скрытый указатель *this, что позволяет «связывать» объекты.

Генерирует исключение out_of_range, если index или startindex некорректны.

Генерирует исключение length_error, если результат превышает максимально допустимое количество символов.

std :: string sString ( "bbb" ) ;
const std :: string sInsert ( "012345" ) ;

sString . insert ( 1 , sInsert , 2 , 4 ) ; // вставляем подстроку sInsert длиной 4, начиная с символа под индексом 2, в строку sString, начиная с индекса 1

std :: cout << sString << std :: endl ;

А вот версия функции insert(), с помощью которой в std::string можно вставить часть строки C-style.

string& string::insert(size_type index, const char* str, size_type len)

Эта функция вставляет с определенного index std::string указанное количество символов ( len ) строки C-style str .

Возвращает скрытый указатель *this, что позволяет «связывать» объекты.

Генерирует исключение out_of_range, если index некорректен.

Генерирует исключение length_error, если результат превышает максимально допустимое количество символов.

Игнорирует специальные символы (такие как " ).

std :: string sString ( "bbb" ) ;
sString . insert ( 2 , "acdef" , 4 ) ;
std :: cout << sString << std :: endl ;

А вот версия функции insert(), которая вставляет в std::string один и тот же символ несколько раз.

string& string::insert(size_type index, size_type num, char c)

Эта функция вставляет с определенного index std::string указанное количество вхождений ( num ) символа c .

Возвращает скрытый указатель *this, что позволяет «связывать» объекты.

Генерирует исключение out_of_range, если index некорректен.

Генерирует исключение length_error, если результат превышает максимально допустимое количество символов.

std :: string sString ( "bbb" ) ;
sString . insert ( 2 , 3 , 'a' ) ;
std :: cout << sString << std :: endl ;

И, наконец, функция insert() имеет три разные версии, которые работают с итераторами.

void insert(iterator it, size_type num, char c)
iterator string::insert(iterator it, char c)
void string::insert(iterator it, InputIterator begin, InputIterator end)

Первая версия функции вставляет в std::string указанное количество вхождений ( num ) символа c перед итератором it .

Вторая версия функции вставляет в std::string одиночный символ c перед итератором it и возвращает итератор в позицию вставленного символа.

Третья версия функции вставляет в std::string все символы диапазона (begin, end) перед итератором it .

Все функции генерируют исключение length_error, если результат превышает максимально допустимое количество символов.

Строки в C++

Для работы со строкам в C++ используется тип string . В разделе про потоки мы уже создавали объекты типа string и использовали их с операторами > . Рассмотрим этот тип подробнее.

Примеры создания объектов string :

string a; // пустая строка string b("abc"); // строка проинициализирована списком символов string c1(b); // c1 является копией b string c2 = b; // c2 является копией b string d('d', 10); // d = "dddddddddd" 

Строки хранят в памяти последовательность объектов char , поэтому во многих случаях со строками можно работать как с массивом. Например, обращаться к символам через индекс.

string a("abz"); char c = a[2]; // 'z' char b = a.at(1); // 'b' a[2] = 'c'; // a = "abc" 

Механизмы обращения к элементу через оператор [] и с помощью метода at() отличаются. В первом случае не происходит проверки того, что индекс меньше, чем длина строки. Если это условие не выполняется, то мы приходим к ситуации неопределенного поведения. Метод at() выполняет эту проверку и генерирует исключение в случае некорректного индекса. За это более безопасное поведение мы платим процессорным временем для дополнительной проверки.

По символам строки можно пройти в цикле:

string s("abcde"); for (char ch : s)  cout  <ch  <' '; > 

Узнать длину строки можно с помощью метода size() .

Строки можно конкатенировать с помощью оператора + или метода append :

string a("Hello, "); string b("world!"); string c = a + b; // "Hello, world!" a.append(b); // a = "Hello, world!" a += b; // a = "Hello, world!world!" 

Добавить символ в конец строки можно с помощью метода push_back() , а удалить последний символ - с помощью метода pop_back() .

В типе string реализованы некоторые алгоритмы. Например, можно осуществлять поиск по строке:

string line("There are two needles in this haystack with needles."); string query("needle"); size_t found = line.find(query); // found = 14 if (found != string::npos)  cout  <"first '"  <query  <"' found at: "  <found  <'\n'; > 

Метод find() возвращает позицию первого символа, которому соответствует совпадение. Если совпадений не найдено, возвращается специальная константа. size_t - это беззнаковый целочисленный тип.

Больше возможностей типа string можно найти в документации.

Документация

  • en.cppreference.com/w/cpp/string/basic_string
  • en.cppreference.com/w/cpp/header/cctype

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *