Foros del Web » Programación para mayores de 30 ;) » C/C++ »

headers, carpetas y menúes c++

Estas en el tema de headers, carpetas y menúes c++ en el foro de C/C++ en Foros del Web. Cita: Iniciado por Instru Creo que lo de null object encontraste información que no es. Yo me refería al patron de diseño. En resumen es ...

  #31 (permalink)  
Antiguo 14/03/2016, 23:57
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 7 meses
Puntos: 204
Respuesta: headers, carpetas y menúes c++

Cita:
Iniciado por Instru Ver Mensaje
Creo que lo de null object encontraste información que no es. Yo me refería al patron de diseño. En resumen es que tengas un campo o "algo" dentro de la clase o estructura Persona que identifique si el objeto es válido. Entonces en vez de regresar Null, o lanzar una excepción, regresas un objeto tipo Persona pero con el campo "valido" como falso. Aclaro, esto es un ejemplo.

Código:
return Persona(false);
Es sólo un ejemplo, debes mejorarlo.
Y si revisas mis respuestas encontrarás formas de implementarlo sin tener que modificar tu estructura.

Un saludo
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.
  #32 (permalink)  
Antiguo 15/03/2016, 15:03
Avatar de detective_jd  
Fecha de Ingreso: abril-2011
Ubicación: Salto
Mensajes: 437
Antigüedad: 13 años
Puntos: 6
Respuesta: headers, carpetas y menúes c++

Hola instru, gracias por responder, me sirvió lo que me dijiste, al final creé una función fantasma creando un objeto vacío:

ManPersonas.h

Código C++:
Ver original
  1. Persona getPhantom(){
  2.         Persona p;
  3.         p.id = 0;
  4.         p.nom ="";
  5.         p.ape ="";
  6.         return p;
  7.     }
  8.     Persona getRow(std::string xnom){
  9.         for(Persona p : lista){
  10.             if(p.nom == xnom){
  11.                 return p;
  12.             }
  13.         }
  14.         return getPhantom();
  15.     }
  16.     Persona getRow(int xid){
  17.         for(Persona p : lista){
  18.             if(p.id == xid){
  19.                 return p;
  20.             }
  21.         }
  22.         return getPhantom();
  23.     }

y en crud_per.h hice unos if para solucionar el problema en updated y deleted:

Código C++:
Ver original
  1. void updated(){  
  2.     int op;
  3.     string xnom;
  4.     Persona p;
  5.     xnom = addString("Nombre");
  6.     p = getRow(xnom);
  7.     if(p.id == 0){
  8.         cout << "\n La persona deseada no existe :(" << endl;
  9.     }
  10.     else {
  11.         cout << "\n Persona: " << p.id << " Nombre: " << p.nom << " Apellido: " << p.ape;
  12.         cout << "\n ¿Desea algún dato? Aceptar=1/Cancelar=2 :";
  13.         cin >> op;
  14.         if(op == 1){
  15.             cout << "\n ¿Desea editar el nombre ("<< p.nom <<") actual? Aceptar=1/Cancelar=2 :";
  16.             cin >> op;
  17.             if(op == 1){
  18.                 p.nom = addString("Nombre");
  19.             }
  20.             else {
  21.                 pause(2);
  22.             }
  23.             cout << "\n ¿Desea editar el apellido ("<< p.ape <<") actual? Aceptar=1/Cancelar=2 :";
  24.             cin >> op;
  25.             if(op == 1){
  26.                 p.ape = addString("Apellido");
  27.             }
  28.             else {
  29.                 pause(2);
  30.             }
  31.             if(update(p)){            
  32.                 cout << "\n persona editada :)" << endl;            
  33.             }
  34.             else {
  35.                 cout << "\n la persona ya existe :(" << endl;
  36.             }
  37.         }
  38.         else if(op == 2) {        
  39.             pause(2);
  40.         }
  41.         else {
  42.             cout << "\n error :(" << endl;
  43.         }
  44.     }
  45. }
  46. void deleted(){
  47.     int op;
  48.     string xnom;
  49.     Persona p;
  50.     xnom = addString("Nombre");
  51.     p = getRow(xnom);
  52.     if(p.id == 0){
  53.         cout << "\n La persona deseada no existe :(" << endl;
  54.     }
  55.     else {
  56.         cout << "\n Persona: " << p.id << " Nombre: " << p.nom << " Apellido: " << p.ape;
  57.         cout << "\n ¿Desea eliminar la persona seleccionada? Aceptar=1/Cancelar=2 :";
  58.         cin >> op;
  59.         if(op == 1){
  60.             deleted(p);
  61.             cout << "\n persona eliminada :)" << endl;
  62.         }
  63.         else if(op == 2) {        
  64.             pause(2);
  65.         }
  66.         else {
  67.             cout << "\n error :(" << endl;
  68.         }
  69.     }
  70. }

Pero en ManPersonas.h con el update no me doy cuenta cómo editar, lo del if que me dijiste es para evitarlos duplicados en los nombres (en java usaba el equals), pero que debo usar de la lista para actualizar??

Código C++:
Ver original
  1. bool update(const Persona& p){
  2.         Persona per = getRow(p.id);
  3.         if(per.nom != p.nom){
  4.             if(check(p)){
  5.                 return false;
  6.             }
  7.         }
  8.         return true;
  9.     }

Espero sus respuestas y saludos
  #33 (permalink)  
Antiguo 16/03/2016, 03:03
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 7 meses
Puntos: 204
Respuesta: headers, carpetas y menúes c++

El problema que tiene la función getRow es que sí, vale, es capaz de localizar un elemento en la lista y devolverlo si es que existe... pero te devuelve una copia del elemento. Devolverte una copia implica que no tienes forma de saber dónde se encuentra el elemento original, por lo que para actualizar el elemento en la lista tienes que volver a buscarlo... pero claro, no puedes utilizar getRow porque entonces estarás en las mismas. Siempre puedes copiar parte del código de getRow directamente en la función updated y retocarlo para que cumpla con tus intereses.

¿Solución coñazo? Sí, pero es más un problema asociado a tu diseño que a C++

Un saludo.
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.
  #34 (permalink)  
Antiguo 16/03/2016, 11:23
Avatar de Instru  
Fecha de Ingreso: noviembre-2002
Ubicación: Mexico
Mensajes: 2.751
Antigüedad: 21 años, 5 meses
Puntos: 52
Respuesta: headers, carpetas y menúes c++

Creo que si getRow regresara un iterador, todo sería mas sencillo.

Saludos
  #35 (permalink)  
Antiguo 16/03/2016, 11:45
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 7 meses
Puntos: 204
Respuesta: headers, carpetas y menúes c++

Cita:
Iniciado por Instru Ver Mensaje
Creo que si getRow regresara un iterador, todo sería mas sencillo.
... o un puntero
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.
  #36 (permalink)  
Antiguo 17/03/2016, 21:01
Avatar de detective_jd  
Fecha de Ingreso: abril-2011
Ubicación: Salto
Mensajes: 437
Antigüedad: 13 años
Puntos: 6
Respuesta: headers, carpetas y menúes c++

Hola eferion y Instru, ayer estaba complicado, pero hoy seguí probando y de esta forma me modifica pero la fila queda cómo último elemento de la lista:

Código C++:
Ver original
  1. bool update(const Persona& p){
  2.         Persona per = getRow(p.id);
  3.         if(per.nom != p.nom){
  4.             if(check(p)){
  5.                 return false;
  6.             }
  7.         }
  8.         lista.remove(per);
  9.         lista.push_back(p);
  10.     }

¿Que devuelva un iterator o un puntero? Instru te refieres a q use la función find, pero intenté usar el insert de la lista y no funcionó.....

Espero sus respuestas y saludos
  #37 (permalink)  
Antiguo 18/03/2016, 00:14
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 7 meses
Puntos: 204
Respuesta: headers, carpetas y menúes c++

Para poder modificar el elemento de la lista fuera de la función getRow necesitas que dica función devuelva algo que lo permita.

Devolver por valor un objeto de tipo Persona como estás haciendo actualmente no es la solución porque ese objeto no está relacionado de ninguna forma con la lista. Es simplemente una copia del elemento que se encuentra en la lista y modificar la copia no altera para nada el original ya que no hay relación alguna entre ellos.

En estos casos puedes devolver un iterador o un puntero.

Devolver un iterador tiene como ventaja que permite modificar la lista (puedes añadir un elemento antes o después del actual, puedes eliminar el elemento de la lista, ...) mientras que las desventajas pasan porque los iteradores son muy inestables (a nada que se modifique la lista el iterador puede quedar invalidado), y que la sintaxis de la función es más compleja y dependiente del tipo de contenedor que uses, lo que puede provocar problemas de mantenimiento. En el caso de tener que devolver la posición de un elemento que no está en la lista lo usual es devolver lista.end().


Un puntero no permite borrar elementos de la lista (pero eso en tu caso no es un problema pues ya tienes un remove), pero sí que permite modificar el elemento apuntado. Además la firma de la función getRow será más limpia y estable. En el caso de devolver un elemento que no está en la lista lo usual es devolver un puntero nulo (puntero=nullptr).

Puedes usar cualquiera de las dos opciones y será una solución válida. En tus manos queda.

Un saludo.
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.
  #38 (permalink)  
Antiguo 18/03/2016, 12:53
Avatar de Instru  
Fecha de Ingreso: noviembre-2002
Ubicación: Mexico
Mensajes: 2.751
Antigüedad: 21 años, 5 meses
Puntos: 52
Respuesta: headers, carpetas y menúes c++

Como comentario adicional.
Que no getrow() esta haciendo la misma verificacion que check()? No basta con una?

Por otro lado. Igual, en vez de regresar un iterador o un puntero, regresar una referencia? He visto la flexibilidad que da esto cuando se implementa correctamente.
El único problema que le veo es que no se pueden regresar referencias nulas, por lo que de nuevo caes en usar el patrón de objeto nulo.

En fin.
Ya tienes 3 opciones diferentes.

Saludos
  #39 (permalink)  
Antiguo 18/03/2016, 18:07
Avatar de detective_jd  
Fecha de Ingreso: abril-2011
Ubicación: Salto
Mensajes: 437
Antigüedad: 13 años
Puntos: 6
Respuesta: headers, carpetas y menúes c++

Hola eferion y Instru, gracias por responder, verán intenté hacer que me ordene después de modificar pero no logré implementarlo, Instru hice lo que me dijiste de simplificar y borré el check, quedándome el código de esta forma:

Código C++:
Ver original
  1. #include <list>
  2. #include "Persona.h"
  3. #include "Util.h"
  4. #ifndef MANPERSONAS_H
  5. #define MANPERSONAS_H
  6. using namespace std;    
  7.     std::list<Persona>lista;
  8.     static int maxIdP = 0;
  9.     int getMaxIdP(){
  10.         return ++maxIdP;
  11.     }
  12.     Persona getPhantom(){
  13.         Persona p;
  14.         p.id = 0;
  15.         p.nom ="";
  16.         p.ape ="";
  17.         return p;
  18.     }
  19.     Persona getRow(std::string xnom){
  20.         for(Persona p : lista){
  21.             if(p.nom == xnom){
  22.                 return p;
  23.             }
  24.         }
  25.         return getPhantom();
  26.     }
  27.     Persona getRow(int xid){
  28.         for(Persona p : lista){
  29.             if(p.id == xid){
  30.                 return p;
  31.             }
  32.         }
  33.         return getPhantom();
  34.     }  
  35.     bool create(const Persona& p){
  36.         if(getRow(p.nom).nom != ""){
  37.             return false;
  38.         }
  39.         else{
  40.             lista.push_back(p);
  41.             return true;
  42.         }
  43.     }
  44.     bool update(const Persona& p){
  45.         Persona per = getRow(p.id);
  46.         if(per.nom != p.nom){
  47.             if(getRow(p.nom).nom != ""){
  48.                 return false;
  49.             }
  50.         }
  51.         lista.remove(per);
  52.         lista.push_back(p);
  53.     }
  54.     void deleted(const Persona& p){
  55.         lista.remove(p);        
  56.     }
  57.     std::list<Persona> read(){
  58.         return lista;        
  59.     }  
  60. #endif  /* MANPERSONAS_H */

Sinceramente y no se enojen conmigo, pero lo que me sugieren lo tengo que ver implementado, ya que busque en google ejemplos de editar con lista, y no encontré nada, intenté implementar los ejemplos con iteradores.....
Los punteros no les agarro la mano...
Les pido disculpas por lo que escribo.

Espero su respuesta y saludos.
  #40 (permalink)  
Antiguo 18/03/2016, 18:36
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 7 meses
Puntos: 204
Respuesta: headers, carpetas y menúes c++

Código C++:
Ver original
  1. // v1
  2. std::list<Persona>::iterator getRow(const std::string& xnom){
  3.   auto lambda = [&xnom]
  4.   ( const Persona& p)
  5.   { return p.nom == xnom; };
  6.  
  7.   return std::find_if(lista.begin(),lista.end(),lambda);
  8. }
  9.  
  10. // v2
  11. std::list<Persona>::iterator getRow(const std::string& xnom){
  12.   auto it = lista.begin();
  13.  
  14.   for( ; it!=lista.end(); ++it )
  15.   {
  16.     if( it->nom == xnom )
  17.       break;
  18.   }  
  19.   return it;
  20. }
  21.  
  22. // v3
  23. Persona* getRow(const std::string& xnom){
  24.   Persona* ptr = nullptr;
  25.  
  26.   for(auto& p : lista){
  27.     if(p.nom == xnom){
  28.       ptr = &p;
  29.       break;
  30.     }
  31.   }
  32.  
  33.   return ptr;
  34. }

No las he compilado luego no garantizo que estén libres de errores... pero deberían.

¿Qué problema tienes con los punteros? Trabajar con punteros es casi igual a trabajar con Java. Vale que en C++ hay algo más de curro pero tampoco es excesivo.
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.
  #41 (permalink)  
Antiguo 18/03/2016, 23:05
Avatar de detective_jd  
Fecha de Ingreso: abril-2011
Ubicación: Salto
Mensajes: 437
Antigüedad: 13 años
Puntos: 6
Respuesta: headers, carpetas y menúes c++

Hola eferion, gracias por responder, lo mio es falta de costumbre, tal vez con un tiempo programando no tenga tantas mañas con c++, pero quería pedirte en vista que estoy usando listas en este caso una lista enlazada y por el tema de los iteradores, quería pedirte si podrías ponerme el código del create, update, remove y read aadaptado según los iteradores o punteros, el que tu quieras, digo para no mirar de a poco (y sacar mejores conclusiones)...

Espero sus respuestas y saludos.

PD: Ya es de noche en mi país zzzz.
  #42 (permalink)  
Antiguo 19/03/2016, 05:30
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 7 meses
Puntos: 204
Respuesta: headers, carpetas y menúes c++

Para borrar un elemento de un contenedor conociendo su iterador:

Código C++:
Ver original
  1. contenedor.erase(it);

Para actualizar un elemento de un contenedor dado su iterador:

Código C++:
Ver original
  1. // para sustituir objetos por valor o sustituir punteros
  2. *it=elemento;
  3.  
  4. // para copiar el contenido de un puntero en otro
  5. **it=*puntero;

Lo mejor que puedes hacer es buscar un tutorial sobre iteradores. En el fondo un iterador no deja de ser una especie de puntero que te permite navegar entre los elementos de un contenedor. Esto te permite tanto modificar el contenedor como los elementos almacenados en el mismo
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.
  #43 (permalink)  
Antiguo 19/03/2016, 21:04
Avatar de detective_jd  
Fecha de Ingreso: abril-2011
Ubicación: Salto
Mensajes: 437
Antigüedad: 13 años
Puntos: 6
Respuesta: headers, carpetas y menúes c++

Hola eferion, gracias por responder, verás hice unos cambios al código, pero lo que me dijiste para sustituir el objeto no me funcionó, me dio raramente este error que tuve que comentar:

Consola:

g++ -c -g -std=c++11 -MMD -MP -MF "build/Debug/GNU-Linux-x86/main.o.d" -o build/Debug/GNU-Linux-x86/main.o main.cpp
In file included from crud_per.h:3:0,
from menu_per.h:2,
from main.cpp:2:
ManPersonas.h: In function ‘bool update(const iterator&)’:
ManPersonas.h:65:14: error: no match for ‘operator=’ (operand types are ‘Persona’ and ‘const iterator {aka const std::_List_iterator<Persona>}’)
*per = p; //-> lo que me dijiste me da el error de conversión desconocida
^
ManPersonas.h:65:14: note: candidates are:
In file included from ManPersonas.h:3:0,
from crud_per.h:3,
from menu_per.h:2,
from main.cpp:2:
Persona.h:4:8: note: Persona& Persona::operator=(const Persona&)
struct Persona{
^
Persona.h:4:8: note: no known conversion for argument 1 from ‘const iterator {aka const std::_List_iterator<Persona>}’ to ‘const Persona&’
Persona.h:4:8: note: Persona& Persona::operator=(Persona&&)
Persona.h:4:8: note: no known conversion for argument 1 from ‘const iterator {aka const std::_List_iterator<Persona>}’ to ‘Persona&&’
make[2]: *** [build/Debug/GNU-Linux-x86/main.o] Error 1

ManPersonas.h

Código C++:
Ver original
  1. #include <list>
  2. #include <algorithm>
  3. #include "Persona.h"
  4. #include "Util.h"
  5. #ifndef MANPERSONAS_H
  6. #define MANPERSONAS_H
  7. using namespace std;    
  8.     std::list<Persona>lista;
  9.     int maxIdP = 0;
  10.     int getMaxIdP(){
  11.         return ++maxIdP;
  12.     }
  13.     // me parece que el fantasma será inútil ahora....
  14.     Persona getPhantom(){
  15.         Persona p;
  16.         p.id = 0;
  17.         p.nom ="";
  18.         p.ape ="";
  19.         return p;
  20.     }
  21.     /*
  22.     Persona getRow(std::string xnom){
  23.         for(Persona p : lista){
  24.             if(p.nom == xnom){
  25.                 return p;
  26.             }
  27.         }
  28.         return getPhantom();
  29.     }*/
  30.     std::list<Persona>::iterator getRow(const std::string& xnom){
  31.         return std::find_if(lista.begin(),lista.end(),[&xnom](const Persona& p){
  32.             return p.nom == xnom;
  33.         });
  34.     }
  35.     std::list<Persona>::iterator getRow(int xid){
  36.         return std::find_if(lista.begin(),lista.end(),[&xid](const Persona& p){
  37.             return p.id == xid;
  38.         });
  39.     }
  40.     /*
  41.     Persona getRow(int xid){
  42.         for(Persona p : lista){
  43.             if(p.id == xid){
  44.                 return p;
  45.             }
  46.         }
  47.         return getPhantom();
  48.     }*/
  49.     bool create(const Persona& p){
  50.         if(getRow(p.nom)->nom != ""){
  51.             return false;
  52.         }
  53.         else{
  54.             lista.push_back(p);            
  55.             return true;
  56.         }
  57.     }
  58.     bool update(const std::list<Persona>::iterator& p){
  59.         std::list<Persona>::iterator per = getRow(p->id);
  60.         if(per->nom != p->nom){
  61.             if(getRow(p->nom)->nom != ""){
  62.                 return false;
  63.             }
  64.         }
  65.        // *per = p; -> lo que me dijiste me da el error de conversión desconocida
  66.         return true;        
  67.     }
  68.     void deleted(const std::list<Persona>::iterator& p){
  69.         lista.erase(p);
  70.     }
  71.     std::list<Persona> read(){
  72.         return lista;        
  73.     }  
  74. #endif  /* MANPERSONAS_H */

Por otro lado, haciendo pruebas al agregar un elemento, me salió esto de error:

Consola:

---CRUD Personas---

1. Crear Persona
2. Editar Persona
3. Borrar Persona
4. Mostrar Personas
5. Salir

intento nro 1 Ingrese Opción: 1

¿Desea crear una nueva persona? Aceptar=1/Cancelar=2 : 1

intento nro 1 Ingrese Nombre: juandy

intento nro 1 Ingrese Apelido: ocampo

RUN FINISHED; Segmentation fault; real time: 8s; user: 0ms; system: 0ms

crud_per.h - created

Código C++:
Ver original
  1. void created(){
  2.     int op;
  3.     cout << "\n ¿Desea crear una nueva persona? Aceptar=1/Cancelar=2 : ";
  4.     cin >> op;
  5.     if(op == 1) {
  6.         Persona p;
  7.         p.id = getMaxIdP();
  8.         p.nom = addString("Nombre");
  9.         p.ape = addString("Apelido");
  10.         if(create(p)){
  11.             cout << "\n persona creada :)" << endl;            
  12.         }
  13.         else {
  14.             cout << "\n la persona ya existe :(" << endl;
  15.         }                        
  16.     }
  17.     else if(op == 2) {        
  18.         pause(2);
  19.     }
  20.     else {
  21.         cout << "\n error :(" << endl;
  22.     }
  23. }

Espero sus respuestas y saludos
  #44 (permalink)  
Antiguo 20/03/2016, 19:39
Avatar de detective_jd  
Fecha de Ingreso: abril-2011
Ubicación: Salto
Mensajes: 437
Antigüedad: 13 años
Puntos: 6
Respuesta: headers, carpetas y menúes c++

Hola eferion, ahora que lo recuerdo me dio el mismo error que cuando trataba de usar punteros y que lo resolví poniendo :

Código C++:
Ver original
  1. Persona* p = new Persona();

pero ahora que debo hacer para solucionar esto sin los punteros, ahí estoy medio perdido...
Perdonen mi lentitud con c++.

Espero sus respuestas y saludos.
  #45 (permalink)  
Antiguo 21/03/2016, 02:42
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 7 meses
Puntos: 204
Respuesta: headers, carpetas y menúes c++

Código C++:
Ver original
  1. bool update(const std::list<Persona>::iterator& p){

Cita:
ManPersonas.h:65:14: error: no match for ‘operator=’ (operand types are ‘Persona’ and ‘const iterator {aka const std::_List_iterator<Persona>}’)
Consejo general: dedica algunas horas a aprender C++.

¿Por qué lo digo? Tengo mis razones:
  • El & sirve para crear referencias. Una referencia tiene sentido si con ello evitas mover un volumen de datos importante o si necesitas modificar el estado de la variable y que dicho cambio sea visible fuera de la función. Un iterador es casi como un puntero y el tamaño que ocupa es mínimo (en el caso de std::list debería rondar los 8 bytes) luego no ganas nada pasando el dato por referencia. Si además indicas que la referencia es constante no podrás realizar cambios sobre dicha variable (de ahí el mensaje de error, que te está diciendo textualmente que no sabe cómo realizar una asignación sobre un objeto constante).
  • Pasar un entero como referencia constante es otro detalle que no tiene sentido por lo comentado anteriormente. No aporta nada.
  • Si no sabes usar las lambdas dedica un par de horas a estudiarlas. No son nada complicadas
  • Implementando el constructor por defecto en Persona te podrías ahorrar el método getPhantom. Entendiendo además cómo funcionan los constructores y cuándo son llamados verías que no es necesario en dicha función tener las siguientes líneas:
    Código C++:
    Ver original
    1. p.nom ="";
    2. p.ape ="";
  • Si getRow te devuelve un iterador es un suicidio asumir que dicho iterador va a ser siempre válido y tu lo estás asumiendo. Véase por ejemplo:
    Código C++:
    Ver original
    1. bool create(const Persona& p){
    2.         if(getRow(p.nom)->nom != ""){
  • No sabes leer los mensajes de error
  • No sabes usar el depurador de código

Y dado que soy el único que te responde yo de ti me plantearía si no estás abusando un poco de la situación. Quizás deberías poner más de tu parte o por lo menos que se note que estás intentando aprender de tus errores. Que no entiendas C++ es una excusa que sirve un tiempo pero después deja de tener validez. Hay infinidad de recursos en Internet donde explican gran parte de los entresijos de C++. Vale que C++ es complicado, pero aun así al menos yo no veo mejoras por tu parte.

Un saludo.
__________________
La ayuda se paga con esfuerzo o con dinero. Si no estás dispuesto a esforzarte y quieres que te hagan los deberes pide presupuesto, al menos así ahorrarás tiempo.
  #46 (permalink)  
Antiguo 21/03/2016, 15:09
Avatar de detective_jd  
Fecha de Ingreso: abril-2011
Ubicación: Salto
Mensajes: 437
Antigüedad: 13 años
Puntos: 6
Respuesta: headers, carpetas y menúes c++

Eferion, gracias por responder, verás nunca fue mi intención abusar de tu ayuda ni de nadie, no me ofende que digas que debo dedicarle horas a c++ xq no sé mucho de hecho los tipos de datos, los cout y cin, y lo poco de lo tradicional del c antiguo, cuando me dijeron de las estructuras std, me gusto, pero cuando me mencionaron sobre los punteros, iteradores y referencias, me fastidie y quedé mareado, ya te diste cuenta de eso.
Con esto te eigo que me pondré a hacer en un semana sin ayuda, empezando con el código anterior que tengo y veo cómo voy avanzando, si me quedó muy complicado escribiré por acá.
Tampoco uso mi poco conocimiento de c++ como excusa, porque lo dije en más de una ocasión...

Saludos y espero sus respuestas.
  #47 (permalink)  
Antiguo 21/03/2016, 20:19
Avatar de detective_jd  
Fecha de Ingreso: abril-2011
Ubicación: Salto
Mensajes: 437
Antigüedad: 13 años
Puntos: 6
Respuesta: headers, carpetas y menúes c++

Hola eferion, aunque parezca mentira solucioné mis problemas con el crud que tenía, la clave estaba en el struct Persona.

Código C++:
Ver original
  1. #ifndef PERSONA_H
  2. #define PERSONA_H
  3. using namespace std;
  4. struct Persona{
  5.     int id;
  6.     string nom;
  7.     string ape;
  8.     bool operator == (const Persona& p){
  9.         return p.id == id;
  10.     }
  11.     // este operator < lo tuve que usar para ordenar mis datos
  12.     bool operator < (const Persona & p) const
  13.     {
  14.         return id < p.id;
  15.     }
  16. };
  17. #endif  /* PERSONA_H */

Y en el ManPersonas, luego de borrar, reinsertar, ordeno los datos para que al editar mis datos no tenga problemas con el orden

Código C++:
Ver original
  1. #include <list>
  2. #include "../Model/Persona.h"
  3. #include "../Lib/Util.h"
  4. #ifndef MANPERSONAS_H
  5. #define MANPERSONAS_H
  6. using namespace std;    
  7.     std::list<Persona> lista;
  8.     int maxIdP = 0;
  9.     int getMaxIdP(){
  10.         return ++maxIdP;
  11.     }
  12.     Persona getPhantom(){
  13.         Persona p;
  14.         p.id = 0;
  15.         p.nom ="";
  16.         p.ape ="";
  17.         return p;
  18.     }    
  19.     Persona getRow(std::string xnom){
  20.         for(Persona p : lista){
  21.             if(p.nom == xnom){
  22.                 return p;
  23.             }
  24.         }
  25.         return getPhantom();
  26.     }    
  27.     Persona getRow(int xid){
  28.         for(Persona p : lista){
  29.             if(p.id == xid){
  30.                 return p;
  31.             }
  32.         }
  33.         return getPhantom();
  34.     }
  35.     bool create(const Persona& p){
  36.         if(getRow(p.nom).nom != ""){
  37.             maxIdP--;
  38.             return false;
  39.         }
  40.         else{
  41.             lista.push_back(p);            
  42.             return true;
  43.         }
  44.     }
  45.     bool update(const Persona& p){
  46.         Persona per = getRow(p.id);
  47.         if(per.nom != p.nom){
  48.             if(getRow(p.nom).nom != ""){
  49.                 return false;
  50.             }
  51.         }
  52.         lista.remove(per);
  53.         lista.push_back(p);
  54.         lista.sort();
  55.         return true;        
  56.     }
  57.     void deleted(const Persona& p){
  58.         lista.remove(p);
  59.     }
  60.     std::list<Persona> read(){
  61.         return lista;        
  62.     }  
  63. #endif  /* MANPERSONAS_H */

Ahora me quedan hacer andar bien las validaciones tanto en los string como en los enteros, en conclusión este código hecho comparado con lo que tu y Instru me dijeron es malo, pero para safar un poco da aunque debo mejorarlo...

Espero sus respuestas y saludos.
  #48 (permalink)  
Antiguo 21/03/2016, 21:45
Avatar de detective_jd  
Fecha de Ingreso: abril-2011
Ubicación: Salto
Mensajes: 437
Antigüedad: 13 años
Puntos: 6
Respuesta: headers, carpetas y menúes c++

Y resulta eferion, que logré hacer las validaciones, pongo el código:

Código C++:
Ver original
  1. #include <ctime>
  2. #include <ctype.h>
  3. #include <cstring>
  4. #ifndef UTIL_H
  5. #define UTIL_H
  6. using namespace std;
  7. bool checkInt(string s){
  8.     int cont =0;
  9.     for(int i=0; i < s.size(); i++){
  10.         if(s[i] >= 90 and s[i]<= 122) {
  11.             cont++;
  12.         }
  13.     }
  14.     return !s.empty() and cont == 0;
  15. }
  16. bool checkStr(string s){
  17.     int cont =0;
  18.     for(int i=0; i < s.size(); i++){
  19.         if(s[i] >= 48 and s[i]<= 57) {
  20.             cont++;
  21.         }
  22.     }
  23.     return !s.empty() and cont == 0;
  24. }
  25. void pause(int dur) {
  26.     int temp = time(NULL) + dur;
  27.     while(temp > time(NULL));
  28. }
  29. string passUpper(string s){
  30.     for(int i=0; i < s.size(); i++){
  31.         s[i] = toupper(s[i]);
  32.     }
  33.     return s;
  34. }
  35. string addString(string type){
  36.     int intento = 1;
  37.     string nom = "";    
  38.     while(!checkStr(nom)){
  39.         cout << "\n intento nro "<< intento << " Ingrese " << type <<": ";
  40.         cin >> nom;
  41.         intento++;
  42.     }
  43.     return passUpper(nom);
  44. }
  45.  
  46. int addInt(string type){
  47.     int intento = 1;    
  48.     string numero;
  49.     while(!checkInt(numero)){
  50.         cout << "\n intento nro "<< intento << " Ingrese " << type <<": ";
  51.         cin >> numero;
  52.         intento++;
  53.     }
  54.     return std::stoi(numero);
  55. }
  56. #endif  /* UTIL_H */

Mil gracias tanto a tí como a Instru.

Saludos.

Etiquetas: carpetas, char, funcion, headers, int
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 18:45.