2009-11-30 33 views
8

¿Cuál es la mejor manera de reemplazar caracteres en una cadena?C++ character replace

Específicamente:

"This,Is A|Test" ----> "This_Is_A_Test" 

quiero reemplazar todas las comas, espacios, y "|" con guiones bajos.

(tengo acceso a Boost.)

+0

¿Es esta una cadena de clase std :: string, o una matriz de tipo char con un terminador '\ 0' ? –

+0

es std :: string – tinkertime

+6

Creo que las diversas respuestas de replace_if, p. UncleBens, son buenos. Sin embargo, un comentario general: si está reemplazando personajes para obtener algo que sea seguro para su uso, p. como nombre de archivo, debe enumerar los caracteres permitidos y reemplazar todo lo demás, en lugar de al revés. De esa forma no te sorprenderá ninguna entrada extraña en la que no hayas pensado. –

Respuesta

9

Como las demás respuestas indicadas, puede utilizar los diversos métodos replace. Sin embargo, estos enfoques tienen la desventaja de escanear la cadena varias veces (una vez para cada personaje). Yo recomendaría rodar su propio método de sustituir, si se preocupan por la velocidad:

void beautify(std::string &s) { 
    int i; 
    for (i = 0; i < s.length(); ++i) { 
     switch (s[i]) { 
     case ' ': 
     case ',': 
     case '|': 
      s[i] = '_'; 
     } 
    } 
} 
+0

el método de reemplazo de una línea es bueno, pero su solución también funciona bien –

+0

Una línea de reemplazo es definitivamente mejor (creo que necesitará líneas al menos), pero no es tan eficiente. – notnoop

+0

+1 - solución válida, eficiente y más larga :) – Jacob

0

La Biblioteca C++ Estándar tiene acceso a estas funciones, así, sin necesidad de impulso. Consulte el replace C++ Reference. Es esta la mejor manera ? Supongo que eso depende de la discusión. Para reemplazar caracteres múltiples/diferentes, es posible que deba llamar a reemplazar más de una vez.

#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

El método de reemplazo simplemente reemplaza un carácter (rango), no todas las apariciones de algo, así que diría que de hecho no es muy útil para esta tarea :) – UncleBens

+0

Roger. Es por eso que dije que necesita ser ejecutado más de una vez. Si es la mejor metodología, depende del desarrollador –

+0

En realidad, podría estar haciendo que el agua esté más embarrada. 'string :: replace' es para reemplazar un solo rango con otra cadena (o carácter (s)). OP desea reemplazar solo caracteres individuales, por lo tanto, en lugar del método de reemplazo de peso pesado, podría haber apuntado al operador [], lo que le permite "reemplazar" el valor de los caracteres individuales. – UncleBens

3

EDIT: ComoSpace_C0wb0y dicho, replace_if es definitivamente mejor. Aquí hay un código de ejemplo simpler:

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

vieja respuesta:

Uso std::replace con std::find_first_of

11

Usted podría utilizar el TEL-Algoritmo replace_if.

2

boost :: replace_all (s, viejo, nuevo);

0

estaba escribiendo esto, cuando Space_C0wb0y publicó su respuesta, que es la respuesta correcta para su pregunta. Esto es un poco más complicado, pero maneja más reemplazos posibles.

(lo siento, no compilado/prueba)

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

podría utilizar el algoritmo estándar replace_if, excepto el predicado es bastante complicado (que se expresa en línea con C++ estándar actual y sin lambda).

Usted puede escribir su propia, o utilizar is_any_of de algoritmos de cuerda de impulso, por lo que:

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