Відповіді:
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-байт.
У випадках, коли:
надані рішення не можуть бути застосовані (оскільки вони замінюють лише окремі символи) або мають проблеми з продуктивністю, оскільки вони будуть викликати рядок :: замінювати кілька разів, що генерує копії розміру блобу знову і знову. (Я не знаю прискореного рішення, можливо, з цієї точки зору це нормально)
Це один ходить за всіма входжень в заданій стрічці і створює новий рядок по частинах один раз :
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
дзвінок двічі. Розглянемо, як зробити цей результат тимчасовою змінною.
Як запропонував Кирилл, або використовуйте метод заміни або повторіть уздовж рядка, замінюючи кожну таблицю незалежно.
Крім того, ви можете використовувати 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
довгий, під час виклику функції може виникнути велика кількість накладних витрат. Ви можете оптимізувати це шляхом передачі 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 \ audio \ youtube \ libre \ falta \
Це працює! Я використовував щось подібне до цього для книжкового додатка, де інвентар зберігався в CSV (наприклад, файл .dat). Але у випадку одного символу, що означає, що замінювач є лише одним знаком, наприклад, "|", він повинен бути у подвійних лапках "|" щоб не кидати недійсну таблицю const конверсії.
#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 в якомусь строці :
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
це контейнер, спеціально розроблений для роботи з послідовностями символів. посилання