Yanıtlar:
std::string
böyle bir işlev içermez, ancak üstbilgiden bağımsız replace
işlevi kullanabilirsiniz 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()
yerine tam olarak ne oluyor std::replace()
! 'x' ( char
), size_t
[değer 120] 'ye dolaysız olarak dökülür , bu nedenle dizenin tamamı veya bir kısmı 120 kopya' y 'ile doldurulur.
Ben de destek çözümü de atmak düşündüm :
#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
sisteminizde Boost kütüphanelerini bulmak için derleyiciniz için birkaç bayrak eksik . Belki de önce yüklemeniz gerekir.
Soru character
değiştirme üzerine odaklanmıştır , ancak bu sayfayı çok yararlı bulduğumdan (özellikle Konrad'ın sözleri), bu daha genel uygulamayı paylaşmak istiyorum, bu da başa çıkmaya izin veriyor 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;
}
Kullanımı:
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;
Çıktılar:
Number_Of_Beans
XXjXugtXty
hhjhugthty
DÜZENLE:
Performanslar endişe duymanız durumunda, hiçbir şey ( void
) döndürmeyerek ve değere göre adres yerine str
iletilen bağımsız değişken olarak verilen dize üzerinde doğrudan değişiklikler gerçekleştirerek yukarıdakiler daha uygun bir şekilde uygulanabilir . Bu, sonucu döndürürken orijinal dizenin işe yaramaz ve maliyetli bir kopyasını önler. Çağrınız o zaman ...
Kod:
static inline void ReplaceAll2(std::string &str, const std::string& from, const std::string& to)
{
// Same inner code...
// No return statement
}
Bu diğerleri için yararlı olacağını umuyoruz ...
from
dizenin boş olup olmadığını kontrol etmelisiniz , aksi takdirde sonsuz bir döngü oluşur.
Taşıma protokolünün \ 0-bayta izin vermediği için, tüm 0x00 baytlarının "\ 1 \ x30" ve tüm 0x01 baytlarının "\ 1 \ x31" ile değiştirileceği büyük bir ikili blob düşünün.
Aşağıdaki durumlarda:
sağlanan çözümler uygulanamaz (çünkü yalnızca tek karakterleri değiştirirler) veya bir performans problemi vardır, çünkü dize :: replace'i birkaç kez çağırırlar, bu da blob boyutunun tekrar tekrar kopyasını oluşturur. (Güçlendirme çözümünü bilmiyorum, belki bu açıdan sorun yok)
Bu, kaynak dizgideki tüm oluşumlar boyunca yürür ve yeni dizeyi bir kez parça parça oluşturur :
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);
}
Tek bir karakter için basit bir bulma ve değiştirme şöyle bir şey olur:
s.replace(s.find("x"), 1, "y")
Tüm dize için bunu yapmak için, yapılacak en kolay şey s.find
geri dönmeye başlayana kadar döngü olacaktır npos
. Sanırım range_error
döngüden çıkmak için de yakalayabilirsiniz , ama bu biraz çirkin.
{
karakter. "Çifte parantez" in ne olduđunu bilmiyorum. Belki bir tür yazı sorununuz var mı?
Tek bir karakterden daha fazlasını değiştirmek istiyorsanız ve sadece bununla uğraşıyorsanız std::string
, bu snippet çalışır, sHaystack'taki sNeedle'ı sReplace ile değiştirir ve sNeedle ve sReplace'in aynı boyutta olması gerekmez. Bu yordam, soldan sağa yalnızca birincisi yerine tüm olayları değiştirmek için while döngüsünü kullanır.
while(sHaystack.find(sNeedle) != std::string::npos) {
sHaystack.replace(sHaystack.find(sNeedle),sNeedle.size(),sReplace);
}
find
iki kez bir çağrı var . Bu sonucu temp değişkeni yapmayı düşünün.
Kirill'in önerdiği gibi, replace yöntemini kullanın veya her bir karakteri bağımsız olarak değiştiren dize boyunca yineleyin.
Alternatif olarak, find
yöntemi veya find_first_of
ne yapmanız gerektiğine bağlı olarak kullanabilirsiniz . Bu çözümlerin hiçbiri işi bir seferde yapmayacak, ancak birkaç ekstra kod satırıyla bunları sizin için çalıştırabilmelisiniz. :-)
#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
uzun işlevi arama sırasında, yükü bir sürü olabilir. Sen geçirerek bu optimize edebilirsiniz word
, target
ve replacement
const-referans olarak.
Abseil StrReplaceAll ne olacak ? Başlık dosyasından:
// 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, {
// {"&", "&"},
// {"<", "<"},
// {">", ">"},
// {"\"", """},
// {"'", "'"}});
Eski okul :-)
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;
Sonuç:
H: \ Recursos \ ses \ youtube \ libre \ falta \
Bu çalışıyor! Envanterin bir CSV'de (bir .dat dosyası gibi) depolandığı bir kitapçı uygulaması için buna benzer bir şey kullandım. Ancak tek bir karakter söz konusu olduğunda, yani yer değiştirici yalnızca tek bir karakterdir, örneğin '|', çift tırnak işareti "|" olmalıdır. geçersiz bir dönüşüm const char atmamak için.
#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
Alışılmadık şu anda CentOS kullanıyorum, bu yüzden derleyici sürümüm aşağıda. C ++ sürümü (g ++), C ++ 98 varsayılanı:
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.
S'yi kullanmak std::string
istiyorsanız, bu örnek uygulamanın strsub
işlevini olduğu gibi kullanabilir veya kabaca aynı hedefe ulaşmak için farklı bir tür veya parametre kümesi almasını istiyorsanız güncelleyebilirsiniz. Temel olarak, std::string
eşleşen karakter kümesini hızlı bir şekilde silmek ve istenen karakterleri doğrudan std::string
. Bu değiştirme işlemini her gerçekleştirdiğinde, dengeleme yine de değiştirilecek karakterleri bulabilirse güncellenir ve değiştirilecek başka bir şey olmadığından, dizeyi son güncellemeden itibaren durumuna döndürür.
#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
Parametreleriniz olarak s kullanmaya güvenmek istemiyorsanız, bunun yerine C stili dizeleri aktarabilirsiniz, aşağıdaki güncellenmiş örneği görebilirsiniz:
#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;
}
Basit durumlar için bu başka bir kütüphane kullanmadan oldukça iyi çalışır sonra std :: string (zaten kullanımda).
Karakter tüm tekrarlarını değiştirin a karakteri ile b içinde some_string :
for (size_t i = 0; i < some_string.size(); ++i) {
if (some_string[i] == 'a') {
some_string.replace(i, 1, "b");
}
}
Dize büyükse veya değiştirmek için birden fazla çağrı varsa, bu yanıtta belirtilen tekniği uygulayabilirsiniz: https://stackoverflow.com/a/29752943/3622300
İşte en büyük DRI ruhuyla yuvarladığım bir çözüm. sHaystack'te sNeedle öğesini arar ve sReplace ile değiştirir, n 0 değilse, nTimes, aksi takdirde tüm sNeedle oluşumları. değiştirilen metinde tekrar arama yapmaz.
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
olan bir kap , özellikle karakter dizisi ile çalışmak üzere dizayn edilmiştir. bağlantı