Каков эффективный способ заменить все вхождения символа другим символом в std::string
?
Как заменить все вхождения символа в строке?
Ответ 1
std::string
не содержит такой функции, но вы можете использовать автономную replace
функцию из заголовка algorithm
.
#include <algorithm>
#include <string>
void some_func() {
std::string s = "example string";
std::replace( s.begin(), s.end(), 'x', 'y'); // replace all 'x' to 'y'
}
Ответ 2
Мне показалось, что я подбросил бы в решение для повышения:
#include <boost/algorithm/string/replace.hpp>
// in place
std::string in_place = "blah#blah";
boost::replace_all(in_place, "#", "@");
// copy
const std::string input = "blah#blah";
std::string output = boost::replace_all_copy(input, "#", "@");
Ответ 3
Вопрос основан на замене character
, но, поскольку я нашел эту страницу очень полезной (особенно Konrad), я хотел бы поделиться это более обобщенная реализация, которая позволяет иметь дело с substrings
:
std::string ReplaceAll(std::string str, const std::string& from, const std::string& to) {
size_t start_pos = 0;
while((start_pos = str.find(from, start_pos)) != std::string::npos) {
str.replace(start_pos, from.length(), to);
start_pos += to.length(); // Handles case where 'to' is a substring of 'from'
}
return str;
}
Использование:
std::cout << ReplaceAll(string("Number Of Beans"), std::string(" "), std::string("_")) << std::endl;
std::cout << ReplaceAll(string("ghghjghugtghty"), std::string("gh"), std::string("X")) << std::endl;
std::cout << ReplaceAll(string("ghghjghugtghty"), std::string("gh"), std::string("h")) << std::endl;
Выходы:
Number_Of_Beans
XXjXugtXty
hhjhugthty
EDIT:
Вышеприведенное может быть реализовано более подходящим образом, в случае, если производительность вас беспокоит, не возвращая ничего (void
) и выполняя изменения непосредственно в строке str
, указанной как аргумент, передается на адрес вместо по значению. Это позволит избежать ненужной и дорогостоящей копии исходной строки, возвращая результат. Ваш звонок, затем...
Код:
static inline void ReplaceAll2(std::string &str, const std::string& from, const std::string& to)
{
// Same inner code...
// No return statement
}
Надеюсь, это будет полезно для некоторых других людей.
Ответ 4
Представьте себе большое двоичное blob, где все 0x00 байтов должны быть заменены на "\ 1\x30" и все 0x01 байтов на "\ 1\x31", потому что в транспортном протоколе нет\0-байтов.
В тех случаях, когда:
- заменяющая и замененная строка имеют разную длину,
- существует множество вхождений заменяемой строки в исходной строке и
- строка источника большая,
предоставленные решения не могут быть применены (потому что они заменяют только отдельные символы) или имеют проблемы с производительностью, потому что они будут вызывать строку:: replace несколько раз, которая снова и снова генерирует копии размера блока. (Я не знаю, что такое ускорение, возможно, с этой точки зрения все в порядке)
Этот идет по всем вхождениям в исходной строке и создает новую строчку по частям один раз:
void replaceAll(std::string& source, const std::string& from, const std::string& to)
{
std::string newString;
newString.reserve(source.length()); // avoids a few memory allocations
std::string::size_type lastPos = 0;
std::string::size_type findPos;
while(std::string::npos != (findPos = source.find(from, lastPos)))
{
newString.append(source, lastPos, findPos - lastPos);
newString += to;
lastPos = findPos + from.length();
}
// Care for the rest after last occurrence
newString += source.substr(lastPos);
source.swap(newString);
}
Ответ 5
Простая находка и замена для одного символа будет выглядеть примерно так:
s.replace(s.find("x"), 1, "y")
Чтобы сделать это для всей строки, легко сделать цикл, пока ваш s.find
не вернется npos
. Полагаю, вы могли бы также поймать range_error
, чтобы выйти из цикла, но это было некрасиво.
Ответ 6
Если вы хотите заменить более одного символа и имеете дело только с std::string
, тогда этот фрагмент будет работать, заменив sNeedle на sHaystack на sReplace, а sNeedle и sReplace не должны быть одного размера, Эта процедура использует цикл while для замены всех вхождений, а не только первый, найденный слева направо.
while(sHaystack.find(sNeedle) != std::string::npos) {
sHaystack.replace(sHaystack.find(sNeedle),sNeedle.size(),sReplace);
}
Ответ 7
Как предложил Кирилл, либо используйте метод replace, либо итерацию по строке, заменяя каждый char независимо.
В качестве альтернативы вы можете использовать метод find
или find_first_of
в зависимости от того, что вам нужно сделать. Ни одно из этих решений не сделает работу за один раз, но с несколькими дополнительными строками кода вы должны заставить их работать на вас.: -)
Ответ 8
#include <iostream>
#include <string>
using namespace std;
// Replace function..
string replace(string word, string target, string replacement){
int len, loop=0;
string nword="", let;
len=word.length();
len--;
while(loop<=len){
let=word.substr(loop, 1);
if(let==target){
nword=nword+replacement;
}else{
nword=nword+let;
}
loop++;
}
return nword;
}
//Main..
int main() {
string word;
cout<<"Enter Word: ";
cin>>word;
cout<<replace(word, "x", "y")<<endl;
return 0;
}
Ответ 9
Это работает! Я использовал что-то похожее на это для книжного магазина, где инвентарь был сохранен в CSV (например, файл .dat). Но в случае единственного char, то есть заменитель - это только один char, например '|', он должен быть в двойных кавычках "|" чтобы не вызывать недопустимое преобразование const char.
#include <iostream>
#include <string>
using namespace std;
int main()
{
int count = 0; // for the number of occurences.
// final hold variable of corrected word up to the npos=j
string holdWord = "";
// a temp var in order to replace 0 to new npos
string holdTemp = "";
// a csv for a an entry in a book store
string holdLetter = "Big Java 7th Ed,Horstman,978-1118431115,99.85";
// j = npos
for (int j = 0; j < holdLetter.length(); j++) {
if (holdLetter[j] == ',') {
if ( count == 0 )
{
holdWord = holdLetter.replace(j, 1, " | ");
}
else {
string holdTemp1 = holdLetter.replace(j, 1, " | ");
// since replacement is three positions in length,
// must replace new replacement 0 to npos-3, with
// the 0 to npos - 3 of the old replacement
holdTemp = holdTemp1.replace(0, j-3, holdWord, 0, j-3);
holdWord = "";
holdWord = holdTemp;
}
holdTemp = "";
count++;
}
}
cout << holdWord << endl;
return 0;
}
// result:
Big Java 7th Ed | Horstman | 978-1118431115 | 99.85
Непосредственно я использую CentOS в настоящее время, поэтому моя версия компилятора ниже. Версия С++ (g++), С++ 98 по умолчанию:
g++ (GCC) 4.8.5 20150623 (Red Hat 4.8.5-4)
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Ответ 10
Если вы хотите использовать std::string
s, вы можете использовать эту функцию-образец strsub
как-либо или обновить его, если хотите, чтобы он использовал другой тип или набор параметров для достижения примерно та же цель. В основном, он использует свойства и функциональные возможности std::string
, чтобы быстро удалить соответствующий набор символов и вставить нужные символы непосредственно в std::string
. Каждый раз, когда он выполняет эту операцию замены, смещение обновляется, если он все еще может найти соответствующие символы для замены, и если он не может из-за нечего заменить, он возвращает строку в своем состоянии из последнего обновления.
#include <iostream>
#include <string>
std::string strsub(std::string stringToModify,
std::string charsToReplace,
std::string replacementChars);
int main()
{
std::string silly_typos = "annoiiyyyng syyyllii tiipos.";
std::cout << "Look at these " << silly_typos << std::endl;
silly_typos = strsub(silly_typos, "yyy", "i");
std::cout << "After a little elbow-grease, a few less " << silly_typos << std::endl;
silly_typos = strsub(silly_typos, "ii", "y");
std::cout << "There, no more " << silly_typos << std::endl;
return 0;
}
std::string strsub(std::string stringToModify,
std::string charsToReplace,
std::string replacementChars)
{
std::string this_string = stringToModify;
std::size_t this_occurrence = this_string.find(charsToReplace);
while (this_occurrence != std::string::npos)
{
this_string.erase(this_occurrence, charsToReplace.size());
this_string.insert(this_occurrence, replacementChars);
this_occurrence = this_string.find(charsToReplace,
this_occurrence + replacementChars.size());
}
return this_string;
}
Если вы не хотите полагаться на использование std::string
в качестве параметров, чтобы вместо этого вы могли передавать строки C-стиля, вы можете увидеть обновленный образец ниже:
#include <iostream>
#include <string>
std::string strsub(const char * stringToModify,
const char * charsToReplace,
const char * replacementChars,
uint64_t sizeOfCharsToReplace,
uint64_t sizeOfReplacementChars);
int main()
{
std::string silly_typos = "annoiiyyyng syyyllii tiipos.";
std::cout << "Look at these " << silly_typos << std::endl;
silly_typos = strsub(silly_typos.c_str(), "yyy", "i", 3, 1);
std::cout << "After a little elbow-grease, a few less " << silly_typos << std::endl;
silly_typos = strsub(silly_typos.c_str(), "ii", "y", 2, 1);
std::cout << "There, no more " << silly_typos << std::endl;
return 0;
}
std::string strsub(const char * stringToModify,
const char * charsToReplace,
const char * replacementChars,
uint64_t sizeOfCharsToReplace,
uint64_t sizeOfReplacementChars)
{
std::string this_string = stringToModify;
std::size_t this_occurrence = this_string.find(charsToReplace);
while (this_occurrence != std::string::npos)
{
this_string.erase(this_occurrence, sizeOfCharsToReplace);
this_string.insert(this_occurrence, replacementChars);
this_occurrence = this_string.find(charsToReplace,
this_occurrence + sizeOfReplacementChars);
}
return this_string;
}
Ответ 11
Для простых ситуаций это работает очень хорошо, не используя никакой другой библиотеки, а затем std :: string (которая уже используется).
Замените все вхождения символа a символом b в some_string:
for (size_t i = 0; i < some_string.size(); ++i) {
if (some_string[i] == 'a') {
some_string.replace(i, 1, "b");
}
}
Если строка большая или несколько вызовов для замены являются проблемой, вы можете применить метод, упомянутый в этом ответе: fooobar.com/questions/19539/...
Ответ 12
Старая школа :-)
std::string str = "H:/recursos/audio/youtube/libre/falta/";
for (int i = 0; i < str.size(); i++) {
if (str[i] == '/') {
str[i] = '\\';
}
}
std::cout << str;
Результат:
H:\Recursos\аудио\YouTube\НЬге\Falta\