2010-08-20 24 views
6

SI una cadena puede incluir varios elementos innecesarios, por ejemplo, como @, #, $,%.análisis de cadena

¿Cómo encontrarlos y eliminarlos?

Sé que esto requiere una iteración de bucle, pero no sé cómo representar algo como @, #, $,%.

Si me puede dar un ejemplo de código, entonces seré realmente apreciado.

+0

Dado que estamos hablando de una cadena, que voy a que te refieres a C++, y voy a volver a etiquetar se como tal. – James

+2

Una cadena significa lo mismo en C también. –

+2

@James: Realmente no creo que puedas hacer esa suposición. – Vicky

Respuesta

13

El habitual estándar de C++ sería el erase/remove idiom:

#include <string> 
#include <algorithm> 
#include <iostream> 
struct OneOf { 
     std::string chars; 
     OneOf(const std::string& s) : chars(s) {} 
     bool operator()(char c) const { 
       return chars.find_first_of(c) != std::string::npos; 
     } 
}; 
int main() 
{ 
    std::string s = "string with @, #, $, %"; 
    s.erase(remove_if(s.begin(), s.end(), OneOf("@#$%")), s.end()); 
    std::cout << s << '\n'; 
} 

y sí, impulso ofrece algunas formas ordenadas de escribirlo más corto, por ejemplo usando boost::erase_all_regex

#include <string> 
#include <iostream> 
#include <boost/algorithm/string/regex.hpp> 
int main() 
{ 
    std::string s = "string with @, #, $, %"; 
    erase_all_regex(s, boost::regex("[@#$%]")); 
    std::cout << s << '\n'; 
} 
+1

+1 para STL y rubenvb

3

Si usted desea conseguir la suposición, hay Boost.Regex contrario, puede utilizar la función STL replace en combinación con la función strchr ..

-1

Un personaje está representado en C/C++ por comillas simples, por ejemplo, '@', '#', etc. (a excepción de algunos que deben ser escapados).

Para buscar un carácter en una cadena, use strchr(). Aquí hay un enlace a un código de ejemplo:

http://www.cplusplus.com/reference/clibrary/cstring/strchr/

+0

C/C++ no es un lenguaje, y tampoco son lo mismo. – rubenvb

+0

Una solución que funciona en C, también funciona (normalmente) en C++. Lo contrario no es verdad. La respuesta que proporcioné sugiere una solución que es ** portátil ** en C * y * C++. Por favor, evita la mezquindad cuando el significado de lo que se ha escrito sea claro. –

2

¿Es esta C o C++? (Lo ha etiquetado de ambas maneras.)

En C pura, prácticamente tiene que recorrer carácter por carácter y eliminar los no deseados. Por ejemplo:

char *buf; 
int len = strlen(buf); 
int i, j; 

for (i = 0; i < len; i++) 
{ 
    if (buf[i] == '@' || buf[i] == '#' || buf[i] == '$' /* etc */) 
    { 
     for (j = i; j < len; j++) 
     { 
      buf[j] = buf[j+1]; 
     } 
     i --; 
    } 
} 

Esto no es muy eficiente - se comprueba cada carácter de vuelta y todos ellos baraja arriba si hay uno que usted no desea. Luego debe disminuir el índice para asegurarse de verificar el nuevo carácter siguiente.

3

Y si, por alguna razón, tiene que hacerlo usted mismo estilo C, algo como esto funcionaría:

char* oldstr = ... something something dark side ... 

int oldstrlen = strlen(oldstr)+1; 
char* newstr = new char[oldstrlen]; // allocate memory for the new nicer string 
char* p = newstr; // get a pointer to the beginning of the new string 

for (int i=0; i<oldstrlen; i++) // iterate over the original string 
    if (oldstr[i] != '@' && oldstr[i] != '#' && etc....) // check that the current character is not a bad one 
     *p++ = oldstr[i]; // append it to the new string 
*p = 0; // dont forget the null-termination 
2

algoritmo general:

  1. Construir una cadena que contiene los caracteres desea purgar: "@ # $%"
  2. Iterar carácter por carácter sobre la cadena de asunto.
  3. Buscar si cada carácter se encuentra en el conjunto de depuración.
  4. Si un personaje coincide, deséchelo.
  5. Si un carácter no coincide, agréguelo a una cadena de resultados.

Dependiendo de la biblioteca de cadenas que esté utilizando, existen funciones/métodos que implementan uno o más de los pasos anteriores, como strchr() o find() para determinar si un carácter está en una cadena.

1

utilice el operador caracterizador, es decir, a sería 'a'. no ha dicho si usa cadenas de C++ (en cuyo caso puede usar los métodos de búsqueda y reemplazo) o cadenas C, en cuyo caso usaría algo como esto (esta no es la mejor manera, pero es una simple ida):

void RemoveChar(char* szString, char c) 
{ 
    while(*szString != '\0') 
    { 
     if(*szString == c) 
      memcpy(szString,szString+1,strlen(szString+1)+1); 

     szString++; 
    } 
} 
+0

"¿Operador de caracterizador?" –

+0

ah, buena captura, era cosa del operador de caridad preprocesador de MSVC (# @) – Necrolis

1

Algo como esto haría :

bool is_bad(char c) 
{ 
    if(c == '@' || c == '#' || c == '$' || c == '%') 
    return true; 
    else 
    return false; 
} 

int main(int argc, char **argv) 
{ 
    string str = "a #test #@string"; 
    str.erase(std::remove_if(str.begin(), str.end(), is_bad), str.end()); 
} 

Si su compilador es Pports lambdas (o si puedes usar boost), puede hacerse aún más corto. Ejemplo utilizando el impulso :: lambda:

string str = "a #test #@string"; 
    str.erase(std::remove_if(str.begin(), str.end(), (_1 == '@' || _1 == '#' || _1 == '$' || _1 == '%')), str.end()); 

(! Yay dos líneas)

3

Creo que para este que haría uso de std::remove_copy_if:

#include <string> 
#include <algorithm> 
#include <iostream> 

struct bad_char { 
    bool operator()(char ch) { 
     return ch == '@' || ch == '#' || ch == '$' || ch == '%'; 
    } 
}; 

int main() { 
    std::string in("[email protected]#a$string%[email protected]#stuff$to%ignore"); 
    std::string out; 
    std::remove_copy_if(in.begin(), in.end(), std::back_inserter(out), bad_char()); 
    std::cout << out << "\n"; 
    return 0; 
} 

Resultado:

Thisisastringwithextrastufftoignore 

Dado que los datos que contienen estos caracteres no deseados normalmente provienen de un archivo de algún tipo, también vale la pena considerarlos ng deshacerse de ellos mientras lee los datos del archivo en lugar de leer los datos no deseados en una cadena, y luego filtrándolo. Para ello, se podría crear una faceta que clasifica los caracteres no deseados como el espacio en blanco:

struct filter: std::ctype<char> 
{ 
    filter(): std::ctype<char>(get_table()) {} 

    static std::ctype_base::mask const* get_table() 
    { 
     static std::vector<std::ctype_base::mask> 
      rc(std::ctype<char>::table_size,std::ctype_base::mask()); 

     rc['@'] = std::ctype_base::space; 
     rc['#'] = std::ctype_base::space; 
     rc['$'] = std::ctype_base::space; 
     rc['%'] = std::ctype_base::space; 
     return &rc[0]; 
    } 
}; 

a usar esto, Imbuyes el flujo de entrada con una configuración regional utilizando esta faceta, y luego lee normalmente. Por el momento voy a utilizar un istringstream, aunque normalmente tendría que utilizar algo así como un istream o ifstream:

int main() { 
    std::istringstream in("[email protected]#a$string%[email protected]#stuff$to%ignore"); 
    in.imbue(std::locale(std::locale(), new filter)); 

    std::copy(std::istream_iterator<char>(in), 
     std::istream_iterator<char>(), 
     std::ostream_iterator<char>(std::cout)); 

    return 0; 
} 
+0

Sus ejemplos están haciendo que las facetas sean menos aterradoras ... lentamente. – Cubbi