Ответы:
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'
}
std::string::replace()
вместо std::replace()
! 'x' ( char
) косвенно приводится к size_t
[значению 120], поэтому вся строка или ее часть будет заполнена 120 копиями y.
Я думал, что я также добавлю решение для повышения :
#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, "#", "@");
-I
флагов для вашего компилятора, чтобы он мог найти библиотеки Boost в вашей системе. Возможно, вам даже нужно сначала установить его.
Вопрос сосредоточен на character
замене, но, поскольку я нашел эту страницу очень полезной (особенно замечание Конрада ), я хотел бы поделиться этой более обобщенной реализацией, которая также позволяет иметь дело с 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
РЕДАКТИРОВАТЬ:
Вышеприведенное может быть реализовано более подходящим способом, в случае, если производительность вас интересует, ничего не возвращая ( void
) и выполняя изменения непосредственно в строке, str
заданной в качестве аргумента, передаваемой по адресу, а не по значению . Это позволило бы избежать бесполезного и дорогостоящего копирования исходной строки при возврате результата. Твой звонок, тогда ...
Код:
static inline void ReplaceAll2(std::string &str, const std::string& from, const std::string& to)
{
// Same inner code...
// No return statement
}
Надеюсь, что это будет полезно для некоторых других ...
from
строка пустой, иначе произойдет бесконечный цикл.
Представьте большой двоичный двоичный объект, в котором все байты 0x00 должны быть заменены на «\ 1 \ x30», а все байты 0x01 - на «\ 1 \ x31», поскольку транспортный протокол не допускает байтов \ 0.
В случаях, когда:
предоставленные решения не могут быть применены (потому что они заменяют только отдельные символы) или имеют проблемы с производительностью, потому что они будут вызывать string :: 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);
}
Простой поиск и замена для одного символа будет выглядеть примерно так:
s.replace(s.find("x"), 1, "y")
Чтобы сделать это для всей строки, проще всего сделать цикл до тех пор, пока не s.find
начнется возврат npos
. Я полагаю, вы также можете поймать, range_error
чтобы выйти из цикла, но это довольно уродливо.
{
персонаж. Я не знаю, что такое "двойная скобка". Возможно, у вас есть какая-то проблема со шрифтом?
Если вы хотите заменить более одного символа и имеете дело только с этим std::string
, этот фрагмент будет работать, заменив sNeedle в sHaystack на sReplace, а sNeedle и sReplace не обязательно должны быть одинакового размера. Эта процедура использует цикл while для замены всех вхождений, а не только первый найденный слева направо.
while(sHaystack.find(sNeedle) != std::string::npos) {
sHaystack.replace(sHaystack.find(sNeedle),sNeedle.size(),sReplace);
}
find
звонок дважды. Попробуйте сделать этот результат временной переменной.
Как предложил Кирилл, либо используйте метод replace, либо итерируйте по строке, заменяя каждый символ независимо.
В качестве альтернативы вы можете использовать find
метод или в find_first_of
зависимости от того, что вам нужно сделать. Ни одно из этих решений не выполнит работу за один раз, но с несколькими дополнительными строками кода вы должны заставить их работать на вас. :-)
#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;
}
word
long, то при вызове функции может возникнуть много накладных расходов. Вы можете оптимизировать это путем передачи word
, target
и в replacement
качестве константных ссылок.
Как насчет Abseil StrReplaceAll ? Из заголовочного файла:
// This file defines `absl::StrReplaceAll()`, a general-purpose string
// replacement function designed for large, arbitrary text substitutions,
// especially on strings which you are receiving from some other system for
// further processing (e.g. processing regular expressions, escaping HTML
// entities, etc.). `StrReplaceAll` is designed to be efficient even when only
// one substitution is being performed, or when substitution is rare.
//
// If the string being modified is known at compile-time, and the substitutions
// vary, `absl::Substitute()` may be a better choice.
//
// Example:
//
// std::string html_escaped = absl::StrReplaceAll(user_input, {
// {"&", "&"},
// {"<", "<"},
// {">", ">"},
// {"\"", """},
// {"'", "'"}});
Старая школа :-)
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 \
Это работает! Я использовал нечто похожее на это для приложения книжного магазина, где инвентарь хранился в CSV (например, в файле .dat). Но в случае с одним символом, то есть заменяющим является только один символ, например '|', он должен быть в двойных кавычках "|" чтобы не скинуть недопустимую конверсию 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's 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, поэтому моя версия компилятора приведена ниже. Версия C ++ (g ++), C ++ 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.
Если вы хотите использовать 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
s в качестве параметров, чтобы вместо этого можно было передавать строки в стиле 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;
}
Для простых ситуаций это работает довольно хорошо, без использования какой-либо другой библиотеки, кроме 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");
}
}
Если строка большая или несколько вызовов для замены является проблемой, вы можете применить метод, упомянутый в этом ответе: https://stackoverflow.com/a/29752943/3622300
Вот решение, которое я выбрал, в духе максимального DRI. он будет искать sNeedle в sHaystack и заменять его на sReplace, nTimes, если не равно 0, иначе все вхождения sNeedle. он не будет искать снова в замененном тексте.
std::string str_replace(
std::string sHaystack, std::string sNeedle, std::string sReplace,
size_t nTimes=0)
{
size_t found = 0, pos = 0, c = 0;
size_t len = sNeedle.size();
size_t replen = sReplace.size();
std::string input(sHaystack);
do {
found = input.find(sNeedle, pos);
if (found == std::string::npos) {
break;
}
input.replace(found, len, sReplace);
pos = found + replen;
++c;
} while(!nTimes || c < nTimes);
return input;
}
std::string
представляет собой контейнер , специально предназначенный для работы с последовательностями символов. ссылка