variable - pedir datos en c++
Cómo leer un número arbitrario de valores usando std:: copy? (9)
Estoy tratando de codificar una acción opuesta a esto:
std::ostream outs; // properly initialized of course
std::set<int> my_set; // ditto
outs << my_set.size();
std::copy( my_set.begin(), my_set.end(), std::ostream_iterator<int>( outs ) );
debería ser algo como esto:
std::istream ins;
std::set<int>::size_type size;
ins >> size;
std::copy( std::istream_iterator<int>( ins ), std::istream_iterator<int>( ins ) ???, std::inserter( my_set, my_set.end() ) );
Pero estoy atascado con el iterador ''end'' - los interadores de entrada no pueden usar std :: advance y tampoco puedo usar dos streams con la misma fuente ...
¿Hay alguna manera elegante de cómo resolver esto? Por supuesto que puedo usar for loop, pero tal vez hay algo más lindo :)
(Editado: debería haber leído la pregunta más cerca ...)
Aunque es algo sospechoso, puede obtener aproximadamente el comportamiento correcto al tener una entrada en el archivo que "fallará" el primer ciclo, luego borrará el bit de falla en la transmisión y comenzará a leer más.
Datos, sin un tamaño explícito, pero como este
1 1 2 3 5 8 Fibb
Alimentado con el siguiente código parece hacer lo que quise decir, al menos en VS2005 con STLPort.
typedef std::istream_iterator < int, char, std::char_traits ,ptrdiff_t> is_iter; std::copy( is_iter(cin), is_iter(), inserter(my_set,my_set.end())); cin.clear(); std::cin >> instr;
Al analizar esto un poco, no creo que leer directamente en un conjunto funcione, ya que es necesario llamar a insertar para agregar realmente los elementos (podría estar equivocado, es bastante temprano aquí). Si bien analizo brevemente la documentación de STL en VS2005, creo que algo que use la función generate_n debería funcionar, por ejemplo:
std::istream ins;
std::set<int> my_set;
std::vector<int> my_vec;
struct read_functor
{
read_functor(std::istream& stream) :
m_stream(stream)
{
}
int operator()
{
int temp;
m_stream >> temp;
return temp;
}
private:
std::istream& m_stream;
};
std::set<int>::size_type size;
ins >> size;
my_vec.reserve(size);
std::generate_n(my_vec.begin(), size, read_functor(ins));
my_set.insert(my_vec.begin(), my_vec.end());
Con suerte, eso solucionó tu problema o te convenció de que el ciclo no es tan malo en el gran esquema de las cosas.
Sí, ¿pero cuando quiero usar otras estructuras de datos en ese archivo / secuencia? Probablemente debería escribir explícitamente aquí, quiero guardar otras cosas después de este set, esta es la razón por la que estoy almacenando el tamaño también.
¿Qué le parece usar un iterador alternativo para hacer el recorrido transversal y luego usar un objeto de función (o lambda) para completar el contenedor?
istream ins;
set<int>::size_type size;
set<int> new_set;
ins >> size;
ostream_iterator<int> ins_iter(ins);
for_each(counting_iterator<int>(0), counting_iterator<int>(size),
[&new_set, &ins_iter](int n) { new_set.insert(*ins_iter++); }
);
Por supuesto, esto supone que tiene un compilador compatible con C ++ 0x.
Por cierto, ''counting_iterator <>'' es parte de Boost.Iterator .
Gracias por las ideas chicos. Incluso cuando estas cosas parezcan interesantes, ciertamente no crearé una nueva clase / iterador ;-) Entiendo mejor por qué SGI decidió incluir el algoritmo "copy_n" ahora :)
Utilizar:
std::copy( std::istream_iterator<int>(ins),
std::istream_iterator<int>(),
std::inserter(my_set, my_set.end())
);
Tenga en cuenta el parámetro vacío:
std::istream_iterator<int>();
O podrías hacer esto:
my_set.insert(std::istream_iterator<int>(ins), std::istream_iterator<int>());
Puede derivar de istream_iterator <T>.
Aunque usar el método del generador Daemin es otra opción, aunque generaría directamente en el conjunto en lugar de usar un vector intermedio.
#include <set>
#include <iterator>
#include <algorithm>
#include <iostream>
template<typename T>
struct CountIter: public std::istream_iterator<T>
{
CountIter(size_t c)
:std::istream_iterator<T>()
,count(c)
{}
CountIter(std::istream& str)
:std::istream_iterator<T>(str)
,count(0)
{}
bool operator!=(CountIter const& rhs) const
{
return (count != rhs.count) && (dynamic_cast<std::istream_iterator<T> const&>(*this) != rhs);
}
T operator*()
{
++count;
return std::istream_iterator<T>::operator*();
}
private:
size_t count;
};
int main()
{
std::set<int> x;
//std::copy(std::istream_iterator<int>(std::cin),std::istream_iterator<int>(),std::inserter(x,x.end()));
std::copy(
CountIter<int>(std::cin),
CountIter<int>(5),
std::inserter(x,x.end())
);
}