Autor
|
Tema: Como intercambiar valores de un iterator en C++ (Leído 5,138 veces)
|
alpachino98
Desconectado
Mensajes: 37
Valar Morghulis
|
Hola, Si alguien puede ayudarme en como intercambiar dos valores de una lista (debe estar ordenada alfabéticamente). Esta lista contiene objetos de una clase contacto. Les dejo por aquí los atributos de la clase contactos. private: string nombre;// Cadena con el contenido de la palabra int nTlf; Atributos de la clase Agenda ( es la que contiene la lista). private: list<Contacto> listapal;// La lista STL con los contactos de la agenda. bool encuentraContacto(const string &, list<Contacto>::iterator &); Este es el método que debe ordenar la lista <listapal>. void/*list<Contacto>*/ Agenda:: ordenaListas() { list<Contacto> :: iterator aux; Contacto contI; Contacto contJ;
for (list<Contacto>::iterator it=listapal.begin();it != listapal.end(); it++) { for (list<Contacto>::iterator jt=it;jt!=listapal.end(); jt++) { jt++; contI=*it; contJ=*jt; if(!(contI.getNombre()<=contJ.getNombre())) { //Primer intento /* *aux=*it; *it=*jt; *jt=*aux;*/ //Segundo intento pos->setNombre(it->getNombre()); pos->setNumeroTelefono(it->getNumeroTelefono()); it->setNombre(jt->getNombre()); it->setNumeroTelefono(jt->getNumeroTelefono()); jt->setNombre(pos->getNombre()); jt->setNumeroTelefono(pos->getNumeroTelefono()); } }} Les he puesto las dos cosas que creo que más sentido tendrían. El problema es que al compilar y ejecutarlo se queda congelado cuando intenta ordenar la lista. Lo que pretendo hacer es usar el método de la burbuja. Les dejo una idea de lo que quisiera hacer pero con iteradores. for (i=0; i<n-1; i++) { for (j=i+1; j<n; j++) { if(V[i]>V[j]) { aux = V[i]; V[i] = V[j]; V[j] = aux; } } }
|
|
|
En línea
|
|
|
|
Loretz
Desconectado
Mensajes: 117
|
Mira, yo creo que en tu segundo for... cuando haces: estás asignando it a jt, y entonces, con lo que haces es incrementar los dos, jt apuntará al siguiente elemento en la lista, igual que it. Luego... if(!(contI.getNombre()<=contJ.getNombre())) jamás se cumplirá porque contI y contJ son iguales (mismo nombre, mismo nTlf). Y como esa condición jamás se cumple, el ciclo for interno va incrementando a jt (y también a it, que es el mismo iterador) hasta hacerlos igual a listapal.end(). Y ahora que it es == a listapal.end(), cuando vuelve a ejecutarse el incremento del ciclo for externo, it va a ser el siguiente de listapal.end() (undefined behavior), que va a cumplir con la condición porque efectivamente es distinto, es uno más allá que más allá del último. ¿Y entonces? El ciclo for más externo jamás se detendrá... (bueno, sí se detendrá, más temprano que tarde el sistema operativo se encargará de humillarte convenientemente). Pregunta. La std::list ya tiene su método sort(), ¿por qué no lo usas?
|
|
|
En línea
|
|
|
|
alpachino98
Desconectado
Mensajes: 37
Valar Morghulis
|
Vale ahora miraré como puedo solucionar todo eso que me has dicho, no había caído en todo eso que has dicho y creo que tienes toda la razón. Uso este método y no el de sort porque sort no puede ordenar objetos de la clase contacto, no he encontrado ninguna manera de decirle que quiero que lo ordene segun el atributo nombre. Si sabes algún modo de hacerlo, en plan operador ternario al que se le pasa la condición o algo asi.
Muchas gracias.
|
|
|
En línea
|
|
|
|
Loretz
Desconectado
Mensajes: 117
|
Un ejemplo con el estándar C++17 #include <iostream> #include <string> #include <list>
struct Contacto { std::string nombre; int nTlf; };
void mostrar(const std::list<Contacto>& Agenda) { for (const auto& [n, t] : Agenda) { std::cout << n << " -> " << t << '\n'; } std::cout << '\n'; }
int main() { std::list<Contacto> Agenda{ {"Juan", 14}, {"Ana", 23}, {"Susana", 19}, {"Abel", 22} }; std::cout << "desordenada:\n"; mostrar(Agenda);
// ordenada por nombre: Agenda.sort([](const auto& c1, const auto& c2) { return c1.nombre < c2.nombre; }); std::cout << "ordenada:\n"; mostrar(Agenda); }
|
|
|
En línea
|
|
|
|
alpachino98
Desconectado
Mensajes: 37
Valar Morghulis
|
No se si es que no lo he entedido mucho pero si hago : listapal.sort([](const Contacto& c1, const Contacto& c2) { return c1.nombre <c2.nombre; }); Me da error: [Error] no matching function for call to 'std::list<Contacto>::sort(Agenda::imprimeAgenda()::<lambda(const Contacto&, const Contacto&)>)' Y si lo hago tal cual lo tienes tu: listapal.sort([](const auto& c1, const auto& c2) { return c1.nombre <c2.nombre; }); Me da estos errores: [Error] request for member 'nombre' in 'c1', which is of non-class type 'const int' Error] request for member 'nombre' in 'c2', which is of non- type 'const int' [Error] no matching function for call to 'std::list<Contacto>::sort(Agenda::imprimeAgenda()::<lambda(const int&, const int&)>)' Y eso que he cambiado el atributo nombre a publico(ya se que no debería pero es que con el getNombre() me dice que no existe getNombre()). Pero es que tu código tampoco me funciona, no entiendo nada. No debe ser tan complicado
|
|
« Última modificación: 20 Enero 2019, 12:45 pm por alpachino98 »
|
En línea
|
|
|
|
|
alpachino98
Desconectado
Mensajes: 37
Valar Morghulis
|
En visual studio si me funciona pero prefiero hacerlo sin la lambda, en java hemos visto lambdas pero el estandar que usamos es c++ 11. He cambiado eso de adelantar el iterador jt y he cambiado la condicion del if. Sigue sin funcionar pero ya no se que hacer, supongo que lo dejare sin ordenar o lo pondré todo en una misma clase ( aunque prefería hacerlo en dos). for (list<Contacto>::iterator it=listapal.begin();it != listapal.end(); it++) { for (list<Contacto>::iterator jt=it;jt!=listapal.end()--; jt++) { //jt++; contI=*it; contJ=*jt; if(contI.getNombre().compare(contJ.getNombre())>0) { /* *pos=*it; *it=*jt; *jt=*pos;*/ pos->setNombre(it->getNombre()); pos->setNumeroTelefono(it->getNumeroTelefono()); it->setNombre(jt->getNombre()); it->setNumeroTelefono(jt->getNumeroTelefono()); jt->setNombre(pos->getNombre()); jt->setNumeroTelefono(pos->getNumeroTelefono());
}
|
|
« Última modificación: 20 Enero 2019, 14:08 pm por alpachino98 »
|
En línea
|
|
|
|
K-YreX
|
La buena noticia es que es posible hacer lo que quieres hacer, el único problema es que estabas teniendo un problema con el uso de los iteradores. Si asignas un iterador a otro e incrementas uno de ellos, no se incrementa el otro (solo lo aclaro) void Agenda::ordenar(){ Contacto auxiliar; for(list<Contacto>::iterator it1 = listapal.begin(); it1 != --listapal.end(); it1++) for(list<Contacto>::iterator it2 = ++it1--; it2 != listapal.end(); it2++) if(it1->getNombre() > it2->getNombre()){ auxiliar = *it1; *it1 = *it2; *it2 = auxiliar; } }
Ya sé que puede parecer muy raro eso de ++it1-- pero es la forma más rápido de hacerlo. Te lo explico por si lo quieres hacer de otra forma: Lo normal es que si el bucle externo se controla con <i>, el bucle interno empieza siempre en <i+1>. Al ser iteradores de una lista no se puede hacer <it2 = it1+1>... Entonces cómo lo arreglamos? Con el uso de los incrementos en prefijo y sufijo: - En prefijo primero se incrementa/decrementa y luego se asigna.
- En sufijo primero se asigna y luego se incrementa/decrementa.
Entonces así conseguimos incrementar <it1> en 1, después se asigna a <it2> y después se decrementa <it1> para dejarlo igual. Suerte
|
|
|
En línea
|
cout << "Todos tenemos un defecto, un error en nuestro código" << endl;
|
|
|
alpachino98
Desconectado
Mensajes: 37
Valar Morghulis
|
Vale muchas gracias, es verdad, me he mareado un poco ahí con los iteradores. He probado tu código y sigo con el mismo problema, el resto del programa funciona correctamente pero ya no se si puede que se quede pillado por otra cosa o que...el caso es que cada vez que intenta ordenar se queda congelado hasta que el sistema operativo decide mandarlo a la *****.
|
|
|
En línea
|
|
|
|
K-YreX
|
Yo he creado un programa similar al que mostrabas pero más sencillo para probar el ordenamiento y me ha funcionado sin problemas. Deja tu código a ver cómo te ha quedado por si el fallo está en otra cosa.
|
|
|
En línea
|
cout << "Todos tenemos un defecto, un error en nuestro código" << endl;
|
|
|
|
Mensajes similares |
|
Asunto |
Iniciado por |
Respuestas |
Vistas |
Último mensaje |
|
|
¿Es posible intercambiar dos valores sin usar variable auxiliar?
Programación C/C++
|
DickGumshoe
|
6
|
14,993
|
14 Noviembre 2011, 15:21 pm
por DickGumshoe
|
|
|
como relaciono una calse iterator con una clase lista...
Programación C/C++
|
.:BlackCoder:.
|
0
|
2,288
|
19 Noviembre 2011, 02:53 am
por .:BlackCoder:.
|
|
|
Duda iterator // Vector iterator not decrementable
Programación C/C++
|
cazagavilan
|
4
|
2,585
|
14 Agosto 2013, 13:17 pm
por frankener1986
|
|
|
intercambiar valores dentro de un vector
Programación C/C++
|
bash
|
8
|
4,422
|
21 Enero 2016, 23:46 pm
por bash
|
|
|
Intercambiar valores de dos variables (batch) --ayuda--
Scripting
|
juntacadaveres
|
7
|
4,089
|
24 Abril 2019, 18:08 pm
por Tachikomaia
|
|