2011-03-02 27 views
14

Estoy intentando utilizar istringstream para dividir una cadena simple en una serie de números enteros:Separar una cadena en enteros utilizando istringstream en C++

#include <string> 
#include <iostream> 
#include <sstream> 
#include <vector> 

using namespace std; 

int main(){ 

    string s = "1 2 3"; 
    istringstream iss(s); 

    while (iss) 
    { 
     int n; 
     iss >> n; 
     cout << "* " << n << endl; 
    } 
} 

y me sale:

* 1 
* 2 
* 3 
* 3 

¿Por qué es el último elemento siempre sale dos veces? ¿Como arreglarlo?

Respuesta

30

Sale dos veces porque su bucle es incorrecto, como se explica (indirectamente) en http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.5 (while (iss) no es diferente de while (iss.eof()) en este escenario).

Específicamente, en la iteración del tercer bucle, iss >> n tiene éxito y obtiene su 3, y deja la transmisión en buen estado. Luego, el bucle se ejecuta por cuarta vez debido a este buen estado, y no es hasta que falla el siguiente (cuarto) iss >> n que la condición de bucle se interrumpe. Pero antes de que finalice la cuarta iteración, todavía se obtiene n ... una cuarta vez.

Probar:

#include <string> 
#include <iostream> 
#include <sstream> 
#include <vector> 

using namespace std; 

int main() 
{ 
    string s = "1 2 3"; 
    istringstream iss(s); 
    int n; 

    while (iss >> n) { 
     cout << "* " << n << endl; 
    } 
} 
+0

¿cómo podemos hacer esto en bucle for()? –

+0

@SumitKandoi: ¿Qué quieres decir? ¿Por que lo harias? –

+0

en realidad, lo probé en el ciclo while(). Estaba pensando que podemos hacer esto en for() loop también –

0

Hope esto ayuda:
ISS: 1 2 3
iteración 1
ISS: 1 2 3 (inicialmente)
n = 1
ISS: 2 3
// * 1 está impreso
Iteración 2:
ISS: 2 3 (inicialmente)
n = 2
ISS: 3
// * 2 se imprime
iteración 3
ISS: 3
n = 3
ISS: ''
Iteration 4
ISS: ''
n no cambió // indicador establecido para eof de ISS como ninguna entrada adicional de la corriente
ISS: ''

Y como con razón mencionada por el post anterior, mientras que (ISS) no es diferente de tiempo (iss.eof()).
Internamente, la función (istream :: operator >>) accede a la secuencia de entrada construyendo primero un objeto sentry (con noskipws establecido en falso [Esto significa que el espacio es separador y su lista será 1,2,3]). Luego (si es good [aquí eof no alcanzado]), llama al num_get::get [Obtener el siguiente entero] para realizar tanto la extracción como las operaciones de análisis, ajustando las banderas de estado internas de la secuencia en consecuencia. Finalmente, destruye el objeto centinela antes de regresar.

Consulte: http://www.cplusplus.com/reference/istream/istream/operator%3E%3E/

Cuestiones relacionadas