Jaki jest najlepszy sposób zamiany znaków w łańcuch?Zastępowanie znaku C++
Konkretnie:
"This,Is A|Test" ----> "This_Is_A_Test"
Chcę wymienić wszystkie przecinki, spacje, a "|" z podkreśleniami.
(mam dostęp do Boost).
Jaki jest najlepszy sposób zamiany znaków w łańcuch?Zastępowanie znaku C++
Konkretnie:
"This,Is A|Test" ----> "This_Is_A_Test"
Chcę wymienić wszystkie przecinki, spacje, a "|" z podkreśleniami.
(mam dostęp do Boost).
Jak wskazano w innych odpowiedziach, można stosować różne metody replace
. Jednak te podejścia mają wadę wielokrotnego skanowania ciągu znaków (jeden raz dla każdego znaku). Polecam toczenia własne metody zastąpienia, jeśli zależy Ci na szybkości:
void beautify(std::string &s) {
int i;
for (i = 0; i < s.length(); ++i) {
switch (s[i]) {
case ' ':
case ',':
case '|':
s[i] = '_';
}
}
}
C++ Standardowa biblioteka ma dostęp do tych funkcji, jak również bez użycia impuls. Patrz: replace C++ Reference. Czy to najlepszy sposób? Myślę, że to jest do dyskusji. Aby zastąpić wiele/inne znaki, konieczne może być wywołanie zamiany więcej niż raz.
#include <string>
string& replace(size_type index, size_type num, const string& str);
string& replace(size_type index1, size_type num1, const string& str, size_type index2, size_type num2);
string& replace(size_type index, size_type num, const Char* str);
string& replace(size_type index, size_type num1, const Char* str, size_type num2);
string& replace(size_type index, size_type num1, size_type num2, Char ch);
string& replace(iterator start, iterator end, const string& str);
string& replace(iterator start, iterator end, const Char* str);
string& replace(iterator start, iterator end, const Char* str, size_type num);
string& replace(iterator start, iterator end, size_type num, Char ch);
string& replace(iterator start, iterator end, input_iterator start2, input_iterator end2);
// replacing in a string
#include <iostream>
#include <string>
using namespace std;
int main()
{
string base="this is a test string.";
string str2="n example";
string str3="sample phrase";
string str4="useful.";
// function versions used in the same order as described above:
// Using positions: *123456789*12345
string str=base; // "this is a test string."
str.replace(9,5,str2); // "this is an example string."
str.replace(19,6,str3,7,6); // "this is an example phrase."
str.replace(8,10,"just all",6); // "this is just a phrase."
str.replace(8,6,"a short"); // "this is a short phrase."
str.replace(22,1,3,'!'); // "this is a short phrase!!!"
// Using iterators: *123456789*
string::iterator it = str.begin(); //^
str.replace(it,str.end()-3,str3); // "sample phrase!!!"
str.replace(it,it+6,"replace it",7); // "replace phrase!!!"
it+=8; // ^
str.replace(it,it+6,"is cool"); // "replace is cool!!!"
str.replace(it+4,str.end()-4,4,'o'); // "replace is cooool!!!"
it+=3; // ^
str.replace(it,str.end(),str4.begin(),str4.end());
// "replace is useful."
cout << str << endl;
return 0;
}
Metoda replace zastępuje tylko jeden znak (zakres), nie wszystkie wystąpienia czegoś, więc powiedziałbym, że to naprawdę nie jest bardzo pomocne w tym zadaniu :) – UncleBens
Roger. Dlatego powiedziałem, że trzeba go uruchomić więcej niż jeden raz. To, czy jest to najlepsza metodologia, zależy od programisty. –
Właściwie możesz sprawić, że woda będzie bardziej błotnista. 'string :: replace' służy do zamiany pojedynczego zakresu na inny ciąg (lub znaki). OP chce zastąpić tylko pojedyncze znaki, więc zamiast metody zamiany wagi ciężkiej można było wskazać na operator [], który pozwala "zastąpić" wartość pojedynczych znaków. – UncleBens
EDIT: W Space_C0wb0y powiedział replace_if
jest zdecydowanie lepiej. Oto niektóre kodu simpler próbki:
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
bool isBad(char c)
{
const string bad_chars = "|, ";
return (bad_chars.find(c) != string::npos);
}
int main()
{
string str = "This,Is A|Test";
// Replace!
replace_if(str.begin(),str.end(),isBad,'_');
cout<<str<<endl;
return 0;
}
OLD ODPOWIEDŹ:
Zastosowanie std::replace z std::find_first_of
Można użyć STL algorytm replace_if.
boost :: replace_all (s, old, new);
Pisałem to, kiedy Space_C0wb0y pisał swoją odpowiedź, która jest prawidłowa odpowiedź na swoje pytanie. Jest to nieco bardziej skomplikowane, ale obsługuje bardziej możliwe zamienniki.
(przepraszam, nie kompilowane/przetestowane)
class MyReplacer
{
friend std::ostream& operator<<(std::ostream& os, const MyReplacer& Repl);
public:
MyReplacer(char c) : ch(c) {}
private:
char ch;
};
std::ostream& operator<<(std::ostream& os, const MyReplacer& Repl)
{
switch (Repl.ch)
{
case '|':
case ' ':
case ',': os << '_'; break;
default: os << Repl.ch;
}
return os;
}
std::ostringstream oss;
std::copy(str.begin(), str.end(), std::ostream_iterator<MyReplacer>(oss));
std::string result = oss.str();
Można użyć standardowego algorytmu replace_if
wyjątkiem orzecznikiem jest dość skomplikowane (być wyrażone inline z aktualnym standardem C++ i nie lambda).
Można napisać własną rękę lub skorzystać z algorytmów łańcuchowych is_any_of
impuls, więc:
#include <algorithm>
#include <string>
#include <boost/algorithm/string/classification.hpp>
#include <iostream>
int main()
{
std::string s("This,Is A|Test");
std::replace_if(s.begin(), s.end(), boost::is_any_of(", |"), '_');
std::cout << s << '\n';
}
Jest to ciąg klasy std :: string, lub tablicę typu char z kończącym '\ 0' ? –
jest std :: string – tinkertime
Myślę, że różne odpowiedzi replace_if, np. UncleBens, są dobre. Jeden ogólny komentarz: jeśli zastępujesz znaki, aby uzyskać coś bezpiecznego, np. jako nazwę pliku należy podać dozwolone znaki i zastąpić wszystko inne, a nie odwrotnie. W ten sposób nie zdziwi Cię żaden dziwny sygnał, o którym nie pomyślałeś. –