@poly Wydaje mi się, że musiałem o to poprosić również o C ++, ale nie mogę go znaleźć
Michael Mrozek
1
W pytaniu znajduje się znacznik std, ale być może być może interesują Cię algorytmy boost, które obejmują również szeroki wybór algorytmów zastępowania (wstawianie / kopiowanie, rozróżnianie wielkości liter / rozróżnianie wielkości liter, zamiana pierwsza / ostatnia / wszystko / n-ty ).
Istnieje funkcja znajdowania podłańcucha w ciągu string ( find) oraz funkcja zastępowania określonego zakresu w ciągu innym ciągiem ( replace), dzięki czemu można je łączyć, aby uzyskać pożądany efekt:
Jak mam to naprawić, jeśli oryginalny ciąg zawierał więcej niż jedno wystąpienie „$ name” i chciałem je wszystkie zastąpić.
Tom Leese
1
Dlaczego nie są fromi toprzekazywane za constodniesienia? Jaka jest twoja funkcja, jeśli jej fromnie ma? -1ode mnie za to.
sbi
10
@sbi Naprawiono, chociaż można by to sformułować jako rekomendacje zamiast ataków - po prostu nie constprzyszło mi to do głowy, rzadko myślę o użyciu, a gdybym napisał taką metodę użyteczności, nazwałbym to, gdybym wiedział wymiana była ważna
Michael Mrozek
10
@Michael: Dobrze, zamieniłem swój głos oddolny na głos wzrostowy. Odrzucenie constoznacza pominięcie jednego z najlepszych narzędzi C ++. Przekazywanie na constreferencję powinno być domyślnym trybem dla parametrów funkcji. (FTR, bez znaku, nie constmożna nawet przekazać literałów łańcuchowych do funkcji, ponieważ nie można powiązać tymczasowych elementów z const
niepowiązaniami
19
Czy to wciąż jedyne rozwiązanie w 2018 roku? Jeśli tak i jakikolwiek komitet C ++ to czyta, rozwiąż to. To jest zawstydzające. podziel (ciąg, ciąg) i zamień (ciąg, ciąg) proszę!
Jestem prawie pewien, std::regex_replaceże nie akceptuje ciągu Qt.
BartoszKP,
1
Masz rację. Tak się składa, że QString zapewnia metodę zastępowania, która akceptuje QRexExp, pozwalając na korzystanie z własnych rzeczy Qt. Ale myślę, że obecną odpowiedź można poprawić, zastępując stringją string.toStdString().
Tom
1
Lub po prostu zmieniając Stringna std::string, ponieważ pytanie nie jest związane z Qt. Zastanów się nad tym - chętnie poprę twoją odpowiedź później.
BartoszKP,
5
Surowy ciąg pozwala na pisanie R"(\$name)"zamiast "\\$name".
Jarod42
2
Ile to będzie wolniejsze niż znajdowanie / zamiana bez uwzględnienia czasu konstruowania std :: regex?
jw_
18
std::stringma replacemetodę, czy tego właśnie szukasz?
Twoje wywołanie podmiotu.replace w funkcji ReplaceStringInPlace () naprawdę modyfikuje ciąg w miejscu?
Damian
Krótko spojrzałem na źródło i wygląda na to, że używa semantyki move, aby przesunąć przód starego łańcucha na miejsce, więc to nie jest kopiowane, ale wstawiony nowy kawałek jest kopiowany na stary łańcuch i ogon starego łańcucha jest kopiowany do buforowanego rozmiaru starego łańcucha. Możliwe jest, że łańcuch rozszerzy się tak bardzo, że cały podstawowy bufor zostanie ponownie przydzielony, ale jeśli zastąpisz 1 do 1, jak w jego przykładzie, myślę, że dzieje się to „na miejscu” lub bez kopiowania, ale jeśli rozwiniesz łańcuch, tylko pierwsza część starego ciągu nie jest kopiowana i tylko wtedy.
Motes
6
Tak, możesz to zrobić, ale musisz znaleźć pozycję pierwszego łańcucha za pomocą elementu find () łańcucha, a następnie zastąpić go jego elementem replace ().
Jeśli planujesz korzystać ze Standardowej Biblioteki, powinieneś naprawdę zdobyć egzemplarz książki Standardowa Biblioteka C ++, która bardzo dobrze opisuje wszystkie te rzeczy.
Wielokrotnie wywołuje, std::string::find()aby zlokalizować inne wystąpienia szukanego ciągu, dopóki std::string::find()niczego nie znajdzie. Ponieważ std::string::find()zwraca pozycję dopasowania, nie mamy problemu z unieważnieniem iteratorów.
Możesz zawinąć to w funkcję, ale to rozwiązanie jednowierszowe wydaje się dopuszczalne. Problem polega na tym, że zmieni to tylko pierwsze wystąpienie, możesz zapętlić go, ale pozwala także wstawić kilka zmiennych do tego ciągu za pomocą tego samego tokena ( %s)
Podobnie jak styl, ale różne łańcuchy były mylące ^^str.replace(str.find("%s"), string("%s").size(), "Something");
Paul Würtz
3
Jeśli wszystkie ciągi są std :: string, znajdziesz dziwne problemy z odcięciem znaków, jeśli są używane, sizeof()ponieważ są przeznaczone do łańcuchów C, a nie C ++. Rozwiązaniem jest użycie .size()metody klasy std::string.
wstring myString = L"Hello $$ this is an example. By $$.";
wstring search = L"$$";
wstring replace = L"Tom";for(int i = myString.find(search); i >=0; i = myString.find(search))
myString.replace(i, search.size(), replace);
Jeśli chcesz to zrobić szybko, możesz zastosować metodę dwóch skanów. Pseudo kod:
pierwsza analiza. znajdź ile pasujących znaków.
rozwiń długość łańcucha.
druga analiza. Zacznij od końca łańcucha, gdy otrzymamy dopasowanie, które zastępujemy, w przeciwnym razie po prostu kopiujemy znaki z pierwszego łańcucha.
Nie jestem pewien, czy można to zoptymalizować do miejscowego algo.
I przykład kodu C ++ 11, ale szukam tylko jednego znaku.
Właśnie uczę się C ++, ale edytując część wcześniej opublikowanego kodu, prawdopodobnie użyłbym czegoś takiego. Zapewnia to elastyczność zastępowania 1 lub wielu wystąpień, a także pozwala określić punkt początkowy.
Odpowiedzi:
Istnieje funkcja znajdowania podłańcucha w ciągu string (
find
) oraz funkcja zastępowania określonego zakresu w ciągu innym ciągiem (replace
), dzięki czemu można je łączyć, aby uzyskać pożądany efekt:W odpowiedzi na komentarz myślę,
replaceAll
że prawdopodobnie wyglądałby mniej więcej tak:źródło
from
ito
przekazywane zaconst
odniesienia? Jaka jest twoja funkcja, jeśli jejfrom
nie ma?-1
ode mnie za to.const
przyszło mi to do głowy, rzadko myślę o użyciu, a gdybym napisał taką metodę użyteczności, nazwałbym to, gdybym wiedział wymiana była ważnaconst
oznacza pominięcie jednego z najlepszych narzędzi C ++. Przekazywanie naconst
referencję powinno być domyślnym trybem dla parametrów funkcji. (FTR, bez znaku, nieconst
można nawet przekazać literałów łańcuchowych do funkcji, ponieważ nie można powiązać tymczasowych elementów zconst
Z C ++ 11 możesz używać
std::regex
tak:Podwójny ukośnik jest wymagany do ucieczki przed znakiem ucieczki.
źródło
std::regex_replace
że nie akceptuje ciągu Qt.string
jąstring.toStdString()
.String
nastd::string
, ponieważ pytanie nie jest związane z Qt. Zastanów się nad tym - chętnie poprę twoją odpowiedź później.R"(\$name)"
zamiast"\\$name"
.std::string
mareplace
metodę, czy tego właśnie szukasz?Możesz spróbować:
Sam nie próbowałem, po prostu przeczytaj dokumentację na temat
find()
ireplace()
.źródło
Aby zwrócić nowy ciąg, użyj tego:
Jeśli potrzebujesz wydajności, oto zoptymalizowana funkcja, która modyfikuje ciąg wejściowy, nie tworzy kopii ciągu:
Testy:
Wynik:
źródło
Tak, możesz to zrobić, ale musisz znaleźć pozycję pierwszego łańcucha za pomocą elementu find () łańcucha, a następnie zastąpić go jego elementem replace ().
Jeśli planujesz korzystać ze Standardowej Biblioteki, powinieneś naprawdę zdobyć egzemplarz książki Standardowa Biblioteka C ++, która bardzo dobrze opisuje wszystkie te rzeczy.
źródło
Używam ogólnie tego:
Wielokrotnie wywołuje,
std::string::find()
aby zlokalizować inne wystąpienia szukanego ciągu, dopókistd::string::find()
niczego nie znajdzie. Ponieważstd::string::find()
zwraca pozycję dopasowania, nie mamy problemu z unieważnieniem iteratorów.źródło
To brzmi jak opcja
string.replace(string.find("%s"), string("%s").size(), "Something");
Możesz zawinąć to w funkcję, ale to rozwiązanie jednowierszowe wydaje się dopuszczalne. Problem polega na tym, że zmieni to tylko pierwsze wystąpienie, możesz zapętlić go, ale pozwala także wstawić kilka zmiennych do tego ciągu za pomocą tego samego tokena (
%s
)źródło
str.replace(str.find("%s"), string("%s").size(), "Something");
Jeśli wszystkie ciągi są std :: string, znajdziesz dziwne problemy z odcięciem znaków, jeśli są używane,
sizeof()
ponieważ są przeznaczone do łańcuchów C, a nie C ++. Rozwiązaniem jest użycie.size()
metody klasystd::string
.Zastępuje on wbudowany sHaystack - nie trzeba już wykonywać przypisania =.
Przykładowe użycie:
źródło
źródło
Jeśli chcesz to zrobić szybko, możesz zastosować metodę dwóch skanów. Pseudo kod:
Nie jestem pewien, czy można to zoptymalizować do miejscowego algo.
I przykład kodu C ++ 11, ale szukam tylko jednego znaku.
źródło
źródło
Moja własna implementacja, biorąc pod uwagę, że ciąg musi być zmieniany tylko raz, wtedy może nastąpić zamiana.
Użycie może być na przykład takie:
źródło
Właśnie uczę się C ++, ale edytując część wcześniej opublikowanego kodu, prawdopodobnie użyłbym czegoś takiego. Zapewnia to elastyczność zastępowania 1 lub wielu wystąpień, a także pozwala określić punkt początkowy.
źródło
Może być jeszcze lepszy w użyciu
źródło