Как я могу искать/находить и заменять в стандартной строке?
есть ли способ заменить все вхождения подстроки другой строкой в std::string
?
например:
void SomeFunction(std::string& str)
{
str = str.replace("hello", "world"); //< I'm looking for something nice like this
}
10 ответов:
почему бы не реализовать свою собственную замену?
void myReplace(std::string& str, const std::string& oldStr, const std::string& newStr) { std::string::size_type pos = 0u; while((pos = str.find(oldStr, pos)) != std::string::npos){ str.replace(pos, oldStr.length(), newStr); pos += newStr.length(); } }
#include <boost/algorithm/string.hpp> // include Boost, a C++ library ... std::string target("Would you like a foo of chocolate. Two foos of chocolate?"); boost::replace_all(target, "foo", "bar");
здесь официальная документация на replace_all.
Вот это презентация Я сделал в 2010 году на повышение строковых алгоритмов.
В C++11, вы можете сделать это как один лайнер с вызовом
regex_replace
:#include <string> #include <regex> using std::string; string do_replace( string const & in, string const & from, string const & to ) { return std::regex_replace( in, std::regex(from), to ); } string test = "Remove all spaces"; std::cout << do_replace(test, " ", "") << std::endl;
выход:
Removeallspaces
Почему бы не вернуть измененную строку?
std::string ReplaceString(std::string subject, const std::string& search, const std::string& replace) { size_t pos = 0; while((pos = subject.find(search, pos)) != std::string::npos) { subject.replace(pos, search.length(), replace); pos += replace.length(); } return subject; }
Если вам нужна производительность, вот оптимизированная функция, которая изменяет входную строку, она не создает копию строки:
void ReplaceStringInPlace(std::string& subject, const std::string& search, const std::string& replace) { size_t pos = 0; while((pos = subject.find(search, pos)) != std::string::npos) { subject.replace(pos, search.length(), replace); pos += replace.length(); } }
тесты:
std::string input = "abc abc def"; std::cout << "Input string: " << input << std::endl; std::cout << "ReplaceString() return value: " << ReplaceString(input, "bc", "!!") << std::endl; std::cout << "ReplaceString() input string not changed: " << input << std::endl; ReplaceStringInPlace(input, "bc", "??"); std::cout << "ReplaceStringInPlace() input string modified: " << input << std::endl;
выход:
Input string: abc abc def ReplaceString() return value: a!! a!! def ReplaceString() input string not modified: abc abc def ReplaceStringInPlace() input string modified: a?? a?? def
мой templatized inline in-place find-and-replace:
template<class T> int inline findAndReplace(T& source, const T& find, const T& replace) { int num=0; typename T::size_t fLen = find.size(); typename T::size_t rLen = replace.size(); for (T::size_t pos=0; (pos=source.find(find, pos))!=T::npos; pos+=rLen) { num++; source.replace(pos, fLen, replace); } return num; }
возвращает количество предметов-заменителей (для использования, если вы хотите успешно запустить и т. д.). Чтобы использовать его:
std::string str = "one two three"; int n = findAndReplace(str, "one", "1");
самый простой способ (предлагая что-то рядом с тем, что вы написали) - это использовать импульс.Регулярное выражение, в частности regex_replace.
std:: string имеет встроенные методы find() и replace (), но они более громоздки для работы, поскольку требуют работы с индексами и длинами строк.
Я считаю, что это будет работать. Он принимает const char* ' s в качестве параметра.
//params find and replace cannot be NULL void FindAndReplace( std::string& source, const char* find, const char* replace ) { //ASSERT(find != NULL); //ASSERT(replace != NULL); size_t findLen = strlen(find); size_t replaceLen = strlen(replace); size_t pos = 0; //search for the next occurrence of find within source while ((pos = source.find(find, pos)) != std::string::npos) { //replace the found string with the replacement source.replace( pos, findLen, replace ); //the next line keeps you from searching your replace string, //so your could replace "hello" with "hello world" //and not have it blow chunks. pos += replaceLen; } }
#include <iostream> #include <string> #include <boost/algorithm/string.hpp> #include <boost/tokenizer.hpp> #include <boost/foreach.hpp> using namespace boost::algorithm; using namespace std; using namespace boost; void highlighter(string terms, string text) { char_separator<char> sep(" "); tokenizer<char_separator<char> > tokens(terms, sep); BOOST_FOREACH(string term, tokens) { boost::replace_all(text, term, "<b>" + term + "</b>"); } cout << text << endl; } int main(int argc, char **argv) { cout << "Search term highlighter" << endl; string text("I love boost library, and this is a test of boost library!"); highlighter("love boost", text); }
Я любовь boost библиотека, и это испытание boost библиотека!
// Replace all occurrences of searchStr in str with replacer // Each match is replaced only once to prevent an infinite loop // The algorithm iterates once over the input and only concatenates // to the output, so it should be reasonably efficient std::string replace(const std::string& str, const std::string& searchStr, const std::string& replacer) { // Prevent an infinite loop if the input is empty if (searchStr == "") { return str; } std::string result = ""; size_t pos = 0; size_t pos2 = str.find(searchStr, pos); while (pos2 != std::string::npos) { result += str.substr(pos, pos2-pos) + replacer; pos = pos2 + searchStr.length(); pos2 = str.find(searchStr, pos); } result += str.substr(pos, str.length()-pos); return result; }
#include <string> using std::string; void myReplace(string& str, const string& oldStr, const string& newStr) { if (oldStr.empty()) { return; } for (size_t pos = 0; (pos = str.find(oldStr, pos)) != string::npos;) { str.replace(pos, oldStr.length(), newStr); pos += newStr.length(); } }
важно проверить, что oldStr пуст. Если по какой-либо причине этот параметр пуст, вы застрянете в бесконечном цикле.
Но да использовать испытанный C++11 или повысить решение, если вы можете.