2011-03-09 22 views
5

Estoy tratando de escribir algo que reemplace todos los espacios en una cadena con un guión bajo.Reemplazar el espacio con un guión bajo

Lo que tengo hasta ahora.

string space2underscore(string text) 
{ 
    for(int i = 0; i < text.length(); i++) 
    { 
     if(text[i] == ' ') 
      text[i] = '_'; 
    } 
    return text; 
} 

En general esto funcionaría, si estuviera haciendo algo así.

string word = "hello stackoverflow"; 
word = space2underscore(word); 
cout << word; 

Eso produciría "hello_stackoverflow", que es justo lo que quiero.

Sin embargo, si tuviera que hacer algo como

string word; 
cin >> word; 
word = space2underscore(word); 
cout << word; 

Me acaba de obtener la primera palabra, "hola".

¿Alguien sabe una solución para esto?

Respuesta

13

El problema es que cin >> word solo se leerá en la primera palabra. Si desea operar en un todo como a la vez, debe usar std::getline.

Por ejemplo:

std::string s; 
std::getline(std::cin, s); 
s = space2underscore(s); 
std::cout << s << std::endl; 

Además, es posible que desee comprobar que en realidad se han podido leer una línea. Puede hacerlo de esta manera:

std::string s; 
if(std::getline(std::cin, s)) { 
    s = space2underscore(s); 
    std::cout << s << std::endl; 
} 

Por último, como nota al margen, probablemente podría escribir su función de una manera más limpia. En lo personal me gustaría escribir así:

std::string space2underscore(std::string text) { 
    for(std::string::iterator it = text.begin(); it != text.end(); ++it) { 
     if(*it == ' ') { 
      *it = '_'; 
     } 
    } 
    return text; 
} 

O para los puntos de bonificación, use std::transform!

EDIT: Si quieres pasar a ser la suerte de ser capaz de utilizar C++ 0x características (y sé que es un gran si) se puede utilizar lambdas y std::transform, lo que resulta en un código muy simple:

std::string s = "hello stackoverflow"; 
std::transform(s.begin(), s.end(), s.begin(), [](char ch) { 
    return ch == ' ' ? '_' : ch; 
}); 
std::cout << s << std::endl; 
+0

Lamento ser pedante, pero estás confundiendo si usas 'std ::' o no. (Aunque técnicamente, su código funciona con 'using std :: cout;' en la parte superior) –

+0

@ Platinum Azure: tiene razón, personalmente me gusta usar un 'std ::' explícito, pero copié parte del código de OP en mi ejemplo Lo limpiaré. –

+0

¡Gracias señor! Mi programa funciona bien ahora :) –

5

el problema está en su comprensión de std::cin de la biblioteca iostream: Usando el operador >> en una corriente con un std::string como el argumento del lado de la derecha sólo se necesita una palabra a la vez (con espacios en blanco para separar).

Lo que quiere en su lugar es usar std::getline() para obtener su cadena.

-1

Reemplazar

cin >> word; 

Con

getline(cin, word); 
10

Tiene su problema getline solucionado, pero solo quería decir que la Biblioteca estándar contiene muchas funciones útiles.En lugar de un bucle enrollado a mano, puede hacer:

std::string space2underscore(std::string text) 
{ 
    std::replace(text.begin(), text.end(), ' ', '_'); 
    return text; 
} 

Esto funciona, es rápido y realmente expresa lo que está haciendo.

0

Para un enfoque moderno de C++ 1x tiene la opción de std::regex_replace.

#include <regex> 
#include <string> 
#include <cstdlib> 
#include <iostream> 

using std::cout; 
using std::endl; 
using std::regex; 
using std::string; 
using std::regex_replace; 

int main(const int, const char**) 
{ 
    const auto target = regex{ " " }; 
    const auto replacement = string{ "_" }; 
    const auto value = string{ "hello stackoverflow" }; 

    cout << regex_replace(value, target, replacement) << endl; 

    return EXIT_SUCCESS; 
} 

Pros: menos código.

Contras: Las expresiones regulares pueden nublar la intención.

Cuestiones relacionadas