2009-11-30 17 views
8

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).

+0

Jest to ciąg klasy std :: string, lub tablicę typu char z kończącym '\ 0' ? –

+0

jest std :: string – tinkertime

+6

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ś. –

Odpowiedz

9

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] = '_'; 
     } 
    } 
} 
+0

Metoda jednej linii zastępowania jest dobra, ale twoje rozwiązanie działa również dobrze –

+0

Jedna kolejka jest zdecydowanie ładniejsza (myślę, że będziesz potrzebować przynajmniej linii), ale nie jest tak wydajna. – notnoop

+0

+1 - prawidłowe, wydajne, dłuższe rozwiązanie :) – Jacob

0

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); 

Example program:

// 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; 
} 
+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

+0

Roger. Dlatego powiedziałem, że trzeba go uruchomić więcej niż jeden raz. To, czy jest to najlepsza metodologia, zależy od programisty. –

+0

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

3

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

2

boost :: replace_all (s, old, new);

0

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(); 
16

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'; 
}