2010-07-16 13 views
18

Tengo un std :: istream que se refiere a datos de la matriz, algo como:C++ leer desde istream hasta nueva línea (pero no los espacios en blanco)

0.0 1.0 2.0 
3.0 4.0 5.0 

Ahora, con el fin de evaluar el número de columnas me gustaría tener algo de código como:

std::vector<double> vec; 
double x; 
while((...something...) && (istream >> x)) 
{ 
    vec.push_back(x); 
} 
//Here vec should contain 0.0, 1.0 and 2.0 

donde el algo ... ... parte se evalúa como falsa después de leer 2.0 y istream en el punto debe estar en 3.0 para que la próxima

istream >> x; 

debe establecer x igual a 3.0.

¿Cómo lograrías este resultado? Supongo que la condición while

Muchas gracias de antemano por su ayuda!

+0

Solo para aclarar, la razón por la que me gustaría seguir este enfoque (si es factible) es evitar la creación de objetos temporales (aparte del doble x). La matriz se crea luego mediante std :: intercambiando el vector de arriba con el almacenamiento interno de la matriz (se implementa a través de un std :: vector). – stepelu

+0

bien, puedes hacerlo con un temporal en 10 líneas simples, o puedes hacerlo sin el temporal en 50 líneas duras. Use un temporal. –

Respuesta

12

utilizar el método de peek para comprobar el carácter siguiente:

while ((istream.peek()!='\n') && (istream>>x)) 
+3

Esto se rompe fácilmente si la línea contiene * cualquier * espacio en blanco antes del Clifford

+0

Verdadero; aquí no hay ninguna comprobación de errores, solo estoy suponiendo que la entrada está bien formada. – tzaman

6

Lea las líneas en una cadena std :: usando std::getline(), luego asigne la cadena a un objeto std::istringstream, y extraiga los datos de eso en lugar de directamente de istream.

+0

Lo siento, no lo dejé claro, pero esto es lo que trato de evitar. El punto es que no sé de antemano si la matriz va a tener muchos cols o muchas filas y tener un almacén de cadenas de 10.000 dobles no es un enfoque muy eficiente para el problema :) Lo siento de nuevo por no dejar esto en claro, mi culpa. – stepelu

0

Lea el número, luego lea un carácter para ver si es nueva.

1

Puede usar std::istream::peek() para verificar si el siguiente carácter es una nueva línea. Ver this entry en la referencia de cplusplus.com.

2
std::vector<double> vec; 
{ 
    std::string line; 
    std::getline(ifile, line); 
    std::istringstream is(line); 
    std::copy(std::istream_iterator<double>(is), std::istream_iterator<double>(), 
       std::back_inserter(vec)); 
} 
std::cout << "Input has " << vec.size() << " columns." << std::endl; 
std::cout << "Read values are: "; 
std::copy(vec.begin(), vec.end(), 
      std::ostream_iterator<double>(std::cout, " ")); 
std::cout << std::endl; 
+0

OP mencionó específicamente que no desea almacenar en búfer toda una línea primero. – tzaman

+0

Su código propuesto solicita que después de un tiempo el vector contenga la primera línea: '// Aquí vec debería contener 0.0, 1.0 y 2.0'. ¿No quiere leer una línea o todo el archivo? –

+0

Sí, quiero finalizar el ciclo while después de que se haya leído la primera línea (y mantener el resto en istream para seguir leyendo), pero me gustaría evitar tener que crear una cadena para almacenar la primera línea completa antes de ponerla en el vector . – stepelu

0

tuve problema similar
de entrada es la siguiente:

1 2 
3 4 5 

El primero dos eran N1 y N2
Luego hay una nueva línea
luego elementos 3 4 5, yo don Sé cuántos serán.

// read N1 & N2 using cin 
int N1, N2; 
cin >> N1; 
cin >> N2; 

// skip the new line which is after N2 (i.e; 2 value in 1st line) 
cin.ignore(numeric_limits<streamsize>::max(), '\n'); 

// now read 3 4 5 elements 
int ele; 
// 2nd EOF condition may required, 
// depending on if you dont have last new-line, and it is end of file. 
while ((cin_.peek() != '\n') && (cin_.peek() != EOF)) { 
    cin >> ele; 
    // do something with ele 
} 

Esto funcionó perfecto para mí.

Cuestiones relacionadas