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. Hola a todos, quería hacer una consulta sobre c++, antes que nada uso netbeans 8.0.2 y linuz mint 17.1, mi problema es que intento simplificar ...

  #1 (permalink)  
Antiguo 06/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
headers, carpetas y menúes c++

Hola a todos, quería hacer una consulta sobre c++, antes que nada uso netbeans 8.0.2 y linuz mint 17.1, mi problema es que intento simplificar el código para que no quede demasiado largo, y hasta ahí bien pero cuando ejecuto el menú no me funcionan la parte para acceder a las modificaciones y las bajas, pongo el código:

Header Files:

Persona.h

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. };
  9. #endif  /* PERSONA_H */

ManPersonas.h

Código C++:
Ver original
  1. #include "Persona.h"
  2. #ifndef CONTRPERSONAS_H
  3. #define CONTRPERSONAS_H
  4. using namespace std;    
  5.     struct persona lista[20];
  6.     int maxIdP = 0;
  7.     int lastP = 0;
  8.     int ind = 0;
  9.     int getMaxIdP(){
  10.         return maxIdP+1;
  11.     }
  12.     void upMaxIdP(){
  13.         maxIdP++;
  14.     }
  15.     bool check(persona p){
  16.         for (int i=0; i< lastP; i++){
  17.             if(lista[i].nom == p.nom){
  18.                 ind = i;
  19.                 return true;
  20.             }
  21.         }
  22.         return false;
  23.     }
  24.     persona getRow(string xnom){
  25.         persona p;
  26.         for (int i=0; i< lastP; i++){
  27.             if(lista[i].nom == xnom){
  28.                 p = lista[i];
  29.                 break;
  30.             }
  31.         }
  32.         return p;
  33.     }
  34.     persona getRow(int id){
  35.         persona p;
  36.         for (int i=0; i< lastP; i++){
  37.             if(lista[i].id == id){
  38.                 p = lista[i];
  39.                 break;
  40.             }
  41.         }
  42.         return p;
  43.     }
  44.     bool create(persona p){
  45.         if(check(p)){            
  46.             return false;
  47.         }
  48.         else{
  49.             lista[lastP] = p;
  50.             lastP++;
  51.             upMaxIdP();
  52.             return true;
  53.         }
  54.     }
  55.     bool update(persona p){
  56.         persona p1 = getRow(p.id);
  57.         if(p1.nom != p.nom){
  58.             if(check(p)){
  59.                 return false;                
  60.             }            
  61.         }        
  62.         lista[ind] = p;
  63.         ind = 0;
  64.         return true;
  65.     }
  66.     void remove(persona p){
  67.         if(check(p)){
  68.             for(int i=ind; i<lastP-1; i++){
  69.                 lista[i] = lista[i+1];
  70.             }
  71.             lastP--;
  72.             ind = 0;
  73.         }
  74.     }
  75.     persona * read(){
  76.         return lista;        
  77.     }
  78.    
  79. #endif  /* CONTRPERSONAS_H */

crud_per.h

Código C++:
Ver original
  1. #include <iostream>
  2. #include "Util.h"
  3. #include "ManPersonas.h"
  4. #ifndef CRUD_PER_H
  5. #define CRUD_PER_H
  6. using namespace std;
  7. void created(){
  8.     int op;
  9.     cout << "\n ¿Desea crear una nueva persona? Aceptar=1/Cancelar=2 : ";
  10.     cin >> op;
  11.     if(op == 1) {
  12.         persona p;
  13.         p.id = getMaxIdP();
  14.         p.nom = addString("Nombre");
  15.         p.ape = addString("Apelido");
  16.         if(create(p)){
  17.             cout << "\n persona creada :)" << endl;            
  18.         }
  19.         else {
  20.             cout << "\n la persona ya existe :(" << endl;
  21.         }                        
  22.     }
  23.     else if(op == 2) {        
  24.         pause(2);
  25.     }
  26.     else {
  27.         cout << "\n error :(" << endl;
  28.     }
  29. }
  30. void updated(){  
  31.     int op;
  32.     string xnom;
  33.     persona p;
  34.     cout << "\n Ingrese nombre: ";
  35.     cin >> xnom;
  36.     p = getRow(xnom);
  37.     cout << "\n Persona: " << p.id << " Nombre: " << p.nom << " Apellido: " << p.ape;
  38.     cout << "\n ¿Desea algún dato? Aceptar=1/Cancelar=2 :";
  39.     cin >> op;
  40.     if(op == 1){
  41.         cout << "\n ¿Desea editar el nombre ("<< p.nom <<") actual? Aceptar=1/Cancelar=2 :";
  42.         cin >> op;
  43.         if(op == 1){
  44.             p.nom = addString("Nombre");
  45.         }
  46.         else {
  47.             pause(2);
  48.         }
  49.         cout << "\n ¿Desea editar el apellido ("<< p.ape <<") actual? Aceptar=1/Cancelar=2 :";
  50.         cin >> op;
  51.         if(op == 1){
  52.             p.ape = addString("Apellido");
  53.         }
  54.         else {
  55.             pause(2);
  56.         }
  57.         if(update(p)){            
  58.             cout << "\n persona editada :)" << endl;            
  59.         }
  60.         else {
  61.             cout << "\n la persona ya existe :(" << endl;
  62.         }
  63.     }
  64.     else if(op == 2) {        
  65.         pause(2);
  66.     }
  67.     else {
  68.         cout << "\n error :(" << endl;
  69.     }
  70. }
  71. void deleted(){
  72.     int op;
  73.     string xnom;
  74.     persona p;
  75.     cout << "\n Ingrese nombre: ";
  76.     cin >> xnom;
  77.     p = getRow(xnom);
  78.     cout << "\n Persona: " << p.id << " Nombre: " << p.nom << " Apellido: " << p.ape;
  79.     cout << "\n ¿Desea eliminar la persona seleccionada? Aceptar=1/Cancelar=2 :";
  80.     cin >> op;
  81.     if(op == 1){
  82.         remove(p);
  83.         cout << "\n persona eliminada :)" << endl;
  84.     }
  85.     else if(op == 2) {        
  86.         pause(2);
  87.     }
  88.     else {
  89.         cout << "\n error :(" << endl;
  90.     }
  91. }
  92. void list(){
  93.     cout << "\n ---Mostrar Personas--- \n";        
  94.     cout << "Persona\t  Nombre\t  Apellido \n";    
  95.     for (int i=0; i< lastP; i++){
  96.         cout << read()[i].id << "\t  " << read()[i].nom << "\t  " << read()[i].ape << "\n";                        
  97.     }
  98. }
  99. #endif  /* CRUD_PER_H */

menu_per.h

Código C++:
Ver original
  1. #include "crud_per.h"
  2. #ifndef MENU_PER_H
  3. #define MENU_PER_H
  4. void menu(){
  5.     int op = 0;
  6.     cout << "\n ---CRUD Personas---\n";
  7.     cout << "\n 1. Crear Persona";
  8.     cout << "\n 2. Editar Persona";
  9.     cout << "\n 3. Borrar Persona";
  10.     cout << "\n 4. Mostrar Personas";
  11.     cout << "\n 5. Salir \n";
  12.     cout << "\n Ingrese Opción: ";
  13.     cin >> op;    
  14.     switch(op){
  15.         case 1:
  16.             created();
  17.             break;  
  18.         case 2:
  19.             updated();
  20.             break;
  21.         case 3:
  22.             deleted();
  23.             break;    
  24.         case 4:
  25.             list();
  26.             break;
  27.         case 5:
  28.             cout << "\n Gracias por usarme ;) \n";
  29.             exit(0);
  30.             break;
  31.         default:
  32.             cout << "\n Error :( \n";
  33.             break;    
  34.     }
  35.     menu();
  36. }
  37. #endif  /* MENU_PER_H */

Util.h

Código C++:
Ver original
  1. #ifndef UTIL_H
  2. #define UTIL_H
  3. using namespace std;
  4. bool checkInt(int s){
  5.     return s >= 48 and s <= 57;
  6. }
  7. bool checkStr(string s){
  8.     for(int i=0; i < s.size(); i++){
  9.         if((s[i] >= 65 and s[i]<= 90) or (s[i] >= 90 and s[i]<= 122)){
  10.             return true;
  11.         }
  12.     }
  13.     return false;
  14. }
  15. void pause(int dur) {
  16.     int temp = time(NULL) + dur;
  17.     while(temp > time(NULL));
  18. }
  19. string addString(string type){
  20.     int intento = 1;
  21.     string nom = "";    
  22.     while(!checkStr(nom)){
  23.         cout << "\n intento nro "<< intento << " Ingrese " << type <<": ";
  24.         cin >> nom;
  25.         intento++;
  26.     }
  27.     return nom;
  28. }
  29. #endif  /* UTIL_H */

Sources Files:

main.cpp

Código C++:
Ver original
  1. #include <iostream>
  2. #include <stdlib.h>
  3. #include "menu_per.h"
  4. using namespace std;
  5. int main(int argc, char** argv) {
  6.     menu();
  7.     exit(2);
  8. }

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

Código C++:
Ver original
  1. struct persona lista[20];
  2.     int maxIdP = 0;
  3.     int lastP = 0;
  4.     int ind = 0;

¿Variables globales? Evítalas salvo que sea imperativo usarlas... y en un programa de 200 líneas dudo mucho que sea imprescindible tirar de variables globales.

Una forma de eliminar algunas variables globales:

Código C++:
Ver original
  1. int getMaxIdP(){
  2.   static int maxIdp = 0;
  3.   return ++maxIdP;
  4. }

Además, No tiene demasiado sentido que esperes a que el nuevo registro se añada definitamente a la lista para actualizar maxIdp... int, para el uso particular que tienen estos identificadores, tiene un rango lo suficientemente amplio como para poder desaprovechar valores.

Aunque también, puestos a simplificar el código, yo pasaría de los arreglos tipo C y consideraría el uso de contenedores. Como ventaja principal que no te tienes que preocupar del número de elementos en el contenedor. Hablando del número de elementos... ¿Compruebas en algún punto que no se intentan meter más de 20 elementos en la lista?

Código C++:
Ver original
  1. std::vector<persona> lista;

Por cierto, nota que en C++ no hace falta poner "struct" a la hora de declarar elementos de tipo "persona". Aunque compile no es necesario en C++... al no ser necesario podemos decir que no aporta absolutamente nada al código, luego lo mejor es eliminarlo para tener un código lo más limpio posible. Otro detalle respecto a este punto es que en C++, como norma general, las clases y estructuras se suelen nombrar con la primera letra en maýusculas. Es una pequeña pijotada pero ayuda a leer mejor el código.

Código C++:
Ver original
  1. void menu(){
  2.   // ...
  3.   menu();
  4. }

¿De verdad es necesario que menu se llame a sí misma de forma recursiva? ¿No conoces los bucles tipo while o do-while?

Código C++:
Ver original
  1. void menu(){
  2.   while(true)
  3.   {
  4.     // ...
  5.   }
  6. }

Y pasando un poco a la chicha del programa:

Código C++:
Ver original
  1. persona getRow(std::string xnom){
  2.     persona p;
  3.     for (int i=0; i< lastP; i++){
  4.         if(lista[i].nom == xnom){
  5.             p = lista[i];
  6.             break;
  7.         }
  8.     }
  9.     return p;
  10. }
  11.  
  12. void updated(){  
  13.   // ...
  14.   p = getRow(xnom);
  15.     std::cout << "\n Persona: " << p.id << " Nombre: " << p.nom << " Apellido: " << p.ape;
  16.     std::cout << "\n ¿Desea algún dato? Aceptar=1/Cancelar=2 :";
  17. }

¿Por qué asumes que el usuario va a introducir un nombre válido? ¿No puede equivocarse?

Por otro lado... si tu idea es simplificar el código... ¿Por qué no dejas a la STL hacer su trabajo?

Código C++:
Ver original
  1. // Lo suyo sería devolver un puntero... si el puntero es nulo es que no se ha encontrado el registro.
  2. persona* getRow(std::string xnom){
  3.     persona* toReturn = nullptr; // inicialización de puntero nulo
  4.  
  5.     auto it = std::find_if(std::begin(lista),std::end(lista),
  6.                                      [&xnom](const presona& p)
  7.                                      { return p.nom == xnom; });
  8.    
  9.     if( it != std::end(lista) )
  10.       toReturn = &(*it); // it
  11.     return p;
  12. }

Aun así tendrías que lidiar con situaciones como... ¿Qué sucede si el usuario únicamente quiere cambiar el apellido? Ahora mismo el programa te va a decir que la persona ya existe y no va a actualizarlo.

Para borrar elementos de la lista tienes problemas similares que deberías corregir.

Más posibles mejoras:

Código C++:
Ver original
  1. bool check(const persona& p){
  2.   int num_reg = std::count_if(std::begin(lista),std::end(lista),
  3.                               [&p](const persona& p2)
  4.                               { return p2.nom == p.nom; });
  5.  
  6.   return num_reg > 0;
  7. }

Código C++:
Ver original
  1. bool create(const persona& p){
  2.   bool toReturn = false;
  3.  
  4.   if(!check(p)){
  5.       // Esta línea...
  6.       lista[lastP] = p;
  7.       // ...con std::vector podría quedar tal que
  8.       lista.push_back(p);
  9.  
  10.       lastP++; // Esto con contenedores no es necesario
  11.       upMaxIdP(); // Si haces caso de lo que te he dicho antes esta línea también sobra
  12.       toReturn = true;
  13.   }
  14.  
  15.   return toReturn;
  16. }

Y bueno aquí tienes algunas guías para mejorar tu código, el resto, dado que hay que tomar decisiones respecto al diseño, es cosa tuya.

PD.: find_if, count_if forman parte de la librería algorithm.

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.
  #3 (permalink)  
Antiguo 07/03/2016, 17:11
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 lo que me dijiste y me marcan errores y no sé xq razón, pongo el código, no sé si puedes pasar por privado tu correo, ya que esto no sólo es para mí y no sé cómo arreglarlo ya que c++ no lo dominio bien.

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

No deberias tener problemas para poner aquí tu código actual para que te sigamos ayudando
__________________
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.
  #5 (permalink)  
Antiguo 08/03/2016, 12:38
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, gracias por responder, verás te hice caso y adapté lo que me dijiste pero me da error en todos los headers y no sé porque:

ManPersonas.h

Código C++:
Ver original
  1. #include <list>
  2. #include <algorithm>
  3. #include "Persona.h"
  4. #ifndef CONTRPERSONAS_H
  5. #define CONTRPERSONAS_H
  6. using namespace std;    
  7.     std::list<Persona>lista;
  8.     static int maxIdP = 0;
  9.     int getMaxIdP(){
  10.         return ++maxIdP;
  11.     }
  12.     bool check(const Persona& p){
  13.         int num_reg = std::count_if(lista.begin(),lista.end(),[&p](const Persona& p2){
  14.             return p2.nom == p.nom;
  15.         });
  16.         return num_reg > 0;
  17.     }
  18.     Persona* getRow(std::string xnom){
  19.         Persona* toReturn = NULL; // inicialización de puntero nulo
  20.         auto it = std::find_if(lista.begin,lista.end,[&xnom](const Persona& p){
  21.             return p.nom == xnom;
  22.         });    
  23.         if( it != lista.end())
  24.             toReturn = &(it); // it
  25.         return toReturn;
  26.     }
  27.     Persona* getRow(int xid){
  28.         Persona* toReturn = nullptr; // inicialización de puntero nulo
  29.         auto it = std::find_if(lista.begin,lista.end,[&xid](const Persona& p){
  30.             return p.id == xid;
  31.         });    
  32.         if( it != lista.end())
  33.             toReturn = &(it); // it
  34.         return toReturn;
  35.     }
  36.     bool create(Persona p){
  37.         if(check(p)){            
  38.             return false;
  39.         }
  40.         else{
  41.             lista.push_back(p);
  42.             return true;
  43.         }
  44.     }
  45.     bool update(Persona p){
  46.         /*
  47.         Persona p1 = getRow(p.id);
  48.         if(p1.nom != p.nom){
  49.             if(check(p)){
  50.                 return false;                
  51.             }            
  52.         }        
  53.         lista[ind] = p;
  54.         ind = 0;
  55.         return true; */
  56.     }
  57.     void remove(Persona p){
  58.         if(check(p)){
  59.             lista.remove(p);
  60.         }
  61.     }
  62.     std::list<Persona> read(){
  63.         return lista;        
  64.     }
  65.    
  66. #endif  /* CONTRPERSONAS_H */

Persona.h

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. };
  9. #endif  /* PERSONA_H */

Util.h

Código C++:
Ver original
  1. #ifndef UTIL_H
  2. #define UTIL_H
  3. using namespace std;
  4. bool checkInt(int s){
  5.     return s >= 48 and s <= 57;
  6. }
  7. bool checkStr(string s){
  8.     for(int i=0; i < s.size(); i++){
  9.         if((s[i] >= 65 and s[i]<= 90) or (s[i] >= 90 and s[i]<= 122)){
  10.             return true;
  11.         }
  12.     }
  13.     return false;
  14. }
  15. void pause(int dur) {
  16.     int temp = time(NULL) + dur;
  17.     while(temp > time(NULL));
  18. }
  19. string addString(string type){
  20.     int intento = 1;
  21.     string nom = "";    
  22.     while(!checkStr(nom)){
  23.         cout << "\n intento nro "<< intento << " Ingrese " << type <<": ";
  24.         cin >> nom;
  25.         intento++;
  26.     }
  27.     return nom;
  28. }
  29. int addInt(string type){
  30.     int intento = 1;
  31.     int nro;    
  32.     while(!checkInt(nro)){
  33.         cout << "\n intento nro "<< intento << " Ingrese " << type <<": ";
  34.         cin >> nro;
  35.         intento++;
  36.     }
  37.     return nro;
  38. }
  39. #endif  /* UTIL_H */

crud_per.h

Código C++:
Ver original
  1. #include <iostream>
  2. #include "Util.h"
  3. #include "ManPersonas.h"
  4. #ifndef CRUD_PER_H
  5. #define CRUD_PER_H
  6. using namespace std;
  7. void created(){
  8.     int op;
  9.     cout << "\n ¿Desea crear una nueva persona? Aceptar=1/Cancelar=2 : ";
  10.     cin >> op;
  11.     if(op == 1) {
  12.         Persona p;
  13.         p.id = getMaxIdP();
  14.         p.nom = addString("Nombre");
  15.         p.ape = addString("Apelido");
  16.         if(create(p)){
  17.             cout << "\n persona creada :)" << endl;            
  18.         }
  19.         else {
  20.             cout << "\n la persona ya existe :(" << endl;
  21.         }                        
  22.     }
  23.     else if(op == 2) {        
  24.         pause(2);
  25.     }
  26.     else {
  27.         cout << "\n error :(" << endl;
  28.     }
  29. }
  30. void updated(){  
  31.     int op;
  32.     string xnom;
  33.     Persona p;
  34.     xnom = addString("Nombre para la búsqueda");
  35.     p = getRow(xnom);
  36.     cout << "\n Persona: " << p.id << " Nombre: " << p.nom << " Apellido: " << p.ape;
  37.     cout << "\n ¿Desea algún dato? Aceptar=1/Cancelar=2 :";
  38.     cin >> op;
  39.     if(op == 1){
  40.         cout << "\n ¿Desea editar el nombre ("<< p.nom <<") actual? Aceptar=1/Cancelar=2 :";
  41.         cin >> op;
  42.         if(op == 1){
  43.             p.nom = addString("Nombre");
  44.         }
  45.         else {
  46.             pause(2);
  47.         }
  48.         cout << "\n ¿Desea editar el apellido ("<< p.ape <<") actual? Aceptar=1/Cancelar=2 :";
  49.         cin >> op;
  50.         if(op == 1){
  51.             p.ape = addString("Apellido");
  52.         }
  53.         else {
  54.             pause(2);
  55.         }
  56.         if(update(p)){            
  57.             cout << "\n persona editada :)" << endl;            
  58.         }
  59.         else {
  60.             cout << "\n la persona ya existe :(" << endl;
  61.         }
  62.     }
  63.     else if(op == 2) {        
  64.         pause(2);
  65.     }
  66.     else {
  67.         cout << "\n error :(" << endl;
  68.     }
  69. }
  70. void deleted(){
  71.     int op;
  72.     string xnom;
  73.     Persona p;
  74.     xnom = addString("Nombre para la búsqueda");
  75.     p = getRow(xnom);
  76.     cout << "\n Persona: " << p.id << " Nombre: " << p.nom << " Apellido: " << p.ape;
  77.     cout << "\n ¿Desea eliminar la persona seleccionada? Aceptar=1/Cancelar=2 :";
  78.     cin >> op;
  79.     if(op == 1){
  80.         remove(p);
  81.         cout << "\n persona eliminada :)" << endl;
  82.     }
  83.     else if(op == 2) {        
  84.         pause(2);
  85.     }
  86.     else {
  87.         cout << "\n error :(" << endl;
  88.     }
  89. }
  90. void listed(){
  91.     cout << "\n ---Mostrar Personas--- \n";        
  92.     cout << "Persona\t  Nombre\t  Apellido \n";
  93.     for(std::list<Persona>::iterator it = read().begin(); it != read().end(); it++) {
  94.         cout << (it)->id << "\t  " << (it)->nom << "\t  " << (it)->ape << "\n";
  95.     }
  96. }
  97. #endif  /* CRUD_PER_H */

menu_per.h
Código C++:
Ver original
  1. #include "Util.h"
  2. #include "crud_per.h"
  3. #ifndef MENU_PER_H
  4. #define MENU_PER_H
  5. void menu(){
  6.     int op;
  7.     cout << "\n ---CRUD Personas---\n";
  8.     cout << "\n 1. Crear Persona";
  9.     cout << "\n 2. Editar Persona";
  10.     cout << "\n 3. Borrar Persona";
  11.     cout << "\n 4. Mostrar Personas";
  12.     cout << "\n 5. Salir \n";
  13.     op = addInt("Opción");
  14.     while (op != 5){
  15.         switch(op){
  16.             case 1:
  17.                 created();
  18.                 break;  
  19.             case 2:
  20.                 updated();
  21.                 break;
  22.             case 3:
  23.                 deleted();
  24.                 break;    
  25.             case 4:
  26.                 listed();
  27.                 break;
  28.             default:
  29.                 cout << "\n Error :( \n";
  30.                 break;    
  31.         }
  32.     }
  33.     cout << "\n Gracias por usarme ;) \n";
  34.     pause(2);
  35. }
  36. #endif  /* MENU_PER_H */

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

Las funciones, con paréntesis

Código C++:
Ver original
  1. Persona* getRow(std::string xnom){
  2.   Persona* toReturn = NULL; // inicialización de puntero nulo
  3.   auto it = std::find_if(lista.begin,lista.end,[&xnom](const Persona& p){
  4.     return p.nom == xnom;
  5.   });
  6.   if( it != lista.end())
  7.     toReturn = &(it); // it
  8.   return toReturn;
  9. }

begin y end son métodos de lista, luego deben llevar paréntesis.

Los includes son obligatorios

Si usas time para simular una pausa debes añadir el include donde se declara dicha función.

Cuidado con las conversiones

Código C++:
Ver original
  1. Persona* getRow(std::string xnom){
  2.   Persona* toReturn = NULL; // inicialización de puntero nulo
  3.   auto it = std::find_if(lista.begin,lista.end,[&xnom](const Persona& p){
  4.     return p.nom == xnom;
  5.   });
  6.   if( it != lista.end())
  7.     toReturn = &(it); // it
  8.   return toReturn;
  9. }

En el código que yo te puse la penúltima línea no era exactamente así, sino más bien:

Código C++:
Ver original
  1. toReturn = &(*it);

Está claro que si trabajamos con tipos nativos & y * son complementarios y se anulan entre sí, pero cuando trabajamos con clases (con las que se pueden sobrecargar dichos operadores) la cosa cambia:
  • *it te devuelve el elemento apuntado por el iterador, en este caso un objeto de tipo Persona por valor.
  • &(*it) coge el objeto por valor anterior y obtiene su dirección de memoria, que es lo que almacenas en el puntero toReturn

Cuidado con las variables no inicializadas

Las variables se han de inicializar SIEMPRE, y si no fíjate en el siguiente fragmento:

Código C++:
Ver original
  1. bool checkInt(int s){
  2.   return s >= 48 and s <= 57;
  3. }
  4.  
  5. int addInt(string type){
  6.   int intento = 1;
  7.   int nro;
  8.   while(!checkInt(nro)){
  9.     cout << "\n intento nro "<< intento << " Ingrese " << type <<": ";
  10.     cin >> nro;
  11.     intento++;
  12.   }
  13.   return nro;
  14. }

En teoría, addInt va a pedir al usuario que introduzca un número, y va a repetir la petición hasta que se introduzca un número válido. La realidad dice que nro va a tener inicialmente un valor aleatorio. Si resulta que dicho valor se encuentra en el rango (48,57) va a tomar ese valor como bueno y no va a mostrar el mensaje...

¿Soluciones? Aparte de inicializar la variable se puede usar un do-while para aumentar la protección.

La función tiene otros problemas:
  • Dado que nro es de tipo int, cin va a intentar convertir la entrada del usuario a entero. En consecuencia checkInt va a tomar como válidos números mayores de 47 y menores de 58.
  • Si se introduce un valor no numérico, p.ej "prueba", cin no va a ser capaz de convertir el dato a tipo int y activará el flag de error que no compruebas... tu programa no se va a comportar como esperas.

La solución pasaría por recoger la entrada del usuario en un string e intentar convertir dicho string a int. Si la conversión es satisfactoria el dato introducido por el usuario se toma como bueno.

Los tipos son muy importantes en C++

Código C++:
Ver original
  1. Persona* getRow(int xid){
  2.   // ...
  3. }
  4.  
  5. Persona p;
  6. p = getRow(xnom);

Si getRow devuelve un dato de tipo Persona* no puedes pretender almacenar ese retorno en una variable de tipo Persona. La gracia de devolver un puntero era para poder identificar cuándo estabamos intentando localizar un registro que no se encuentra en la lista. Puedes ahorrarte el puntero si utilizas alguna convención, por ejemplo devolver un objeto de tipo Persona con 'id=-1' en el caso de registros no válidos.

Prestar atención a los errores

Uno de los errores te está indicando que no se encuentra la sobrecarga del operador de comparación para la clase Persona. En concreto dicho operador se usa aquí:

Código C++:
Ver original
  1. void remove(Persona p){
  2.   if(check(p)){
  3.     lista.remove(p); // <<<--- AQUI!!!!
  4.   }
  5. }

Y se usa porque es la forma en la que remove puede encontrar un elemento equivalente al que le estás pasando como parámetro. Si quieres usar esta función tienes que implementar dicho operador en la clase Persona.

Y con esto el código ya debería compilarte... sigue teniendo algún error más, pero depurando el código deberíais ser capaces de localizarlos.

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.
  #7 (permalink)  
Antiguo 09/03/2016, 13:26
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 lo que me dijiste pero sigue dando error, todo apunta a ManPersonas, te pongo el código y en dónde marcan los errores:

Código C++:
Ver original
  1. #include <list> //aqui marca error
  2. #include <algorithm>
  3. #include "Persona.h"
  4. #ifndef CONTRPERSONAS_H
  5. #define CONTRPERSONAS_H
  6. using namespace std;    
  7.     std::list<Persona>lista;
  8.     static int maxIdP = 0;
  9.     int getMaxIdP(){
  10.         return ++maxIdP;
  11.     }
  12.     bool check(const Persona& p){
  13.         int num_reg = std::count_if(lista.begin(),lista.end(),[&p](const Persona& p2){
  14.             return p2.nom == p.nom;
  15.         }); //aqui marca error
  16.         return num_reg > 0;
  17.     }
  18.     Persona* getRow(std::string xnom){
  19.         Persona* toReturn = NULL; // inicialización de puntero nulo
  20.         auto it = std::find_if(lista.begin(),lista.end(),[&xnom](const Persona& p){  //aqui marca error
  21.             return p.nom == xnom;
  22.         });    
  23.         if(it != lista.end()) //aqui marca error
  24.             toReturn = &(it); // it
  25.         return toReturn;
  26.     }
  27.     Persona* getRow(int xid){
  28.         Persona* toReturn = NULL; // inicialización de puntero nulo
  29.         auto it = std::find_if(lista.begin(),lista.end(),[&xid](const Persona& p){ //aqui marca error
  30.             return p.id == xid;
  31.         });    
  32.         if( it != lista.end()) //aqui marca error
  33.             toReturn = &(*it);
  34.         return toReturn;
  35.     }
  36.     bool create(Persona p){
  37.         if(check(p)){            
  38.             return false;
  39.         }
  40.         else{
  41.             lista.push_back(p);
  42.             return true;
  43.         }
  44.     }
  45.     bool update(Persona p){ }
  46.     void remove(Persona p){
  47.         if(check(p)){
  48.             lista.remove(p); //aqui marca error
  49.         }
  50.     }
  51.     std::list<Persona> read(){
  52.         return lista;        
  53.     }  
  54. #endif  /* CONTRPERSONAS_H */

Pero cuando ejecuto, los errores que me saltan son estos:

In file included from crud_per.h:3:0,
from menu_per.h:2,
from main.cpp:3:
ManPersonas.h: In function ‘bool check(const Persona&)’:
ManPersonas.h:15:9: warning: lambda expressions only available with -std=c++11 or -std=gnu++11 [enabled by default]
});
^
ManPersonas.h:15:10: error: no matching function for call to ‘count_if(std::list<Persona>::iterator, std::list<Persona>::iterator, check(const Persona&)::__lambda0)’
});
^
ManPersonas.h:15:10: note: candidate is:
In file included from /usr/include/c++/4.8/algorithm:62:0,
from ManPersonas.h:2,
from crud_per.h:3,
from menu_per.h:2,
from main.cpp:3:
/usr/include/c++/4.8/bits/stl_algo.h:4647:5: note: template<class _IIter, class _Predicate> typename std::iterator_traits<_Iterator>::difference_type std::count_if(_IIter, _IIter, _Predicate)
count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred)
^
/usr/include/c++/4.8/bits/stl_algo.h:4647:5: note: template argument deduction/substitution failed:
In file included from crud_per.h:3:0,
from menu_per.h:2,
from main.cpp:3:
ManPersonas.h: In substitution of ‘template<class _IIter, class _Predicate> typename std::iterator_traits<_Iterator>::difference_type std::count_if(_IIter, _IIter, _Predicate) [with _IIter = std::_List_iterator<Persona>; _Predicate = check(const Persona&)::__lambda0]’:
ManPersonas.h:15:10: required from here
ManPersonas.h:15:10: error: template argument for ‘template<class _IIter, class _Predicate> typename std::iterator_traits<_Iterator>::difference_type std::count_if(_IIter, _IIter, _Predicate)’ uses local type ‘check(const Persona&)::__lambda0’
});
^
ManPersonas.h:15:10: error: trying to instantiate ‘template<class _IIter, class _Predicate> typename std::iterator_traits<_Iterator>::difference_type std::count_if(_IIter, _IIter, _Predicate)’
ManPersonas.h: In function ‘Persona* getRow(std::string)’:
ManPersonas.h:20:14: error: ‘it’ does not name a type
auto it = std::find_if(lista.begin(),lista.end(),[&xnom](const Persona& p){
^
ManPersonas.h:22:10: error: expected primary-expression before ‘)’ token
});
^
ManPersonas.h:22:10: error: expected ‘;’ before ‘)’ token
ManPersonas.h:23:12: error: ‘it’ was not declared in this scope
if(it != lista.end())
^
ManPersonas.h: In function ‘Persona* getRow(int)’:
ManPersonas.h:29:14: error: ‘it’ does not name a type
auto it = std::find_if(lista.begin(),lista.end(),[&xid](const Persona& p){
^
ManPersonas.h:31:10: error: expected primary-expression before ‘)’ token
});
^
ManPersonas.h:31:10: error: expected ‘;’ before ‘)’ token
ManPersonas.h:32:13: error: ‘it’ was not declared in this scope
if( it != lista.end())
^
In file included from menu_per.h:2:0,
from main.cpp:3:
crud_per.h: In function ‘void updated()’:
crud_per.h:35:7: error: no match for ‘operator=’ (operand types are ‘Persona’ and ‘Persona*’)
p = getRow(xnom);
^
crud_per.h:35:7: note: candidate is:
In file included from ManPersonas.h:3:0,
from crud_per.h:3,
from menu_per.h:2,
from main.cpp:3:
Persona.h:4:8: note: Persona& Persona::operator=(const Persona&)
struct Persona{
^
Persona.h:4:8: note: no known conversion for argument 1 from ‘Persona*’ to ‘const Persona&’
In file included from menu_per.h:2:0,
from main.cpp:3:
crud_per.h: In function ‘void deleted()’:
crud_per.h:75:7: error: no match for ‘operator=’ (operand types are ‘Persona’ and ‘Persona*’)
p = getRow(xnom);
^
crud_per.h:75:7: note: candidate is:
In file included from ManPersonas.h:3:0,
from crud_per.h:3,
from menu_per.h:2,
from main.cpp:3:
Persona.h:4:8: note: Persona& Persona::operator=(const Persona&)
struct Persona{
^
Persona.h:4:8: note: no known conversion for argument 1 from ‘Persona*’ to ‘const Persona&’
In file included from /usr/include/c++/4.8/list:64:0,
from ManPersonas.h:1,
from crud_per.h:3,
from menu_per.h:2,
from main.cpp:3:
/usr/include/c++/4.8/bits/list.tcc: In instantiation of ‘void std::list<_Tp, _Alloc>::remove(const value_type&) [with _Tp = Persona; _Alloc = std::allocator<Persona>; std::list<_Tp, _Alloc>::value_type = Persona]’:
ManPersonas.h:48:27: required from here
/usr/include/c++/4.8/bits/list.tcc:248:17: error: no match for ‘operator==’ (operand types are ‘Persona’ and ‘const value_type {aka const Persona}’)
if (*__first == __value)
^
/usr/include/c++/4.8/bits/list.tcc:248:17: note: candidates are:
In file included from /usr/include/c++/4.8/iosfwd:40:0,
from /usr/include/c++/4.8/ios:38,
from /usr/include/c++/4.8/ostream:38,
from /usr/include/c++/4.8/iostream:39,
from main.cpp:1:
/usr/include/c++/4.8/bits/postypes.h:216:5: note: template<class _StateT> bool std::operator==(const std::fpos<_StateT>&, const std::fpos<_StateT>&)
operator==(const fpos<_StateT>& __lhs, const fpos<_StateT>& __rhs)
^
Entre otros errores, pero esos son los que me llaman más la atención

¿y ahora? espero sus respuestas y saludos
  #8 (permalink)  
Antiguo 09/03/2016, 14:27
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 6 meses
Puntos: 204
Respuesta: headers, carpetas y menúes c++

Existe una herramienta muy útil en este mundo que es google.

Una de las responsabilidades a asumir cuando programas es saber leer los mensajes de error... Al menos la mayoría.

Los errores te están diciendo que el compilador está montando el código conforme al estándar C++99 y que, sin embargo, está encontrando elementos propios del estándar C++11, que para poder compilar el programa tienes que activar el estándar C++11 o C++14 usando los flags correspondientes.

Si no quieres/no puedes hacer uso de dichos estándares en clase (lo cual sería motivo para recriminar al profesor puesto que son estándares más modernos y actuales) tendrás que adaptar el código para que sea compatible con el antiguo estándar.

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.
  #9 (permalink)  
Antiguo 09/03/2016, 22:32
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, estuve viendo en google y parece que tengo que editar en Makefile pero intenté código del páginas y ningún cambio hace que habilite el C++11 o C++14.

¿Me puedes dar una idea?

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

No puedo estar allí para probar tu caso concreto pero el compilador ya te está dando pistas:

warning: lambda expressions only available with -std=c++11 or -std=gnu++11

Tienes que poner uno de estos dos flags cada vez que compilas un fichero. Tampoco has puesto tu makefile por lo que mucho más no se puede hacer.
__________________
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.
  #11 (permalink)  
Antiguo 10/03/2016, 13: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++

Mirá hasta intenté ponder esos flags que dicen pero tampoco funciona, te pongo el Makefile:

-------------------------------------------------------------------------------------------------------------------
#
# There exist several targets which are by default empty and which can be
# used for execution of your targets. These targets are usually executed
# before and after some main targets. They are:
#
# .build-pre: called before 'build' target
# .build-post: called after 'build' target
# .clean-pre: called before 'clean' target
# .clean-post: called after 'clean' target
# .clobber-pre: called before 'clobber' target
# .clobber-post: called after 'clobber' target
# .all-pre: called before 'all' target
# .all-post: called after 'all' target
# .help-pre: called before 'help' target
# .help-post: called after 'help' target
#
# Targets beginning with '.' are not intended to be called on their own.
#
# Main targets can be executed directly, and they are:
#
# build build a specific configuration
# clean remove built files from a configuration
# clobber remove all built files
# all build all configurations
# help print help mesage
#
# Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and
# .help-impl are implemented in nbproject/makefile-impl.mk.
#
# Available make variables:
#
# CND_BASEDIR base directory for relative paths
# CND_DISTDIR default top distribution directory (build artifacts)
# CND_BUILDDIR default top build directory (object files, ...)
# CONF name of current configuration
# CND_PLATFORM_${CONF} platform name (current configuration)
# CND_ARTIFACT_DIR_${CONF} directory of build artifact (current configuration)
# CND_ARTIFACT_NAME_${CONF} name of build artifact (current configuration)
# CND_ARTIFACT_PATH_${CONF} path to build artifact (current configuration)
# CND_PACKAGE_DIR_${CONF} directory of package (current configuration)
# CND_PACKAGE_NAME_${CONF} name of package (current configuration)
# CND_PACKAGE_PATH_${CONF} path to package (current configuration)
#
# NOCDDL

# Environment
MKDIR=mkdir
CP=cp
CCADMIN=CCadmin


# build
build: .build-post

.build-pre:
# Add your pre 'build' code here...

.build-post: .build-impl
# Add your post 'build' code here...


# clean
clean: .clean-post

.clean-pre:
# Add your pre 'clean' code here...

.clean-post: .clean-impl
# Add your post 'clean' code here...


# clobber
clobber: .clobber-post

.clobber-pre:
# Add your pre 'clobber' code here...

.clobber-post: .clobber-impl
# Add your post 'clobber' code here...


# all
all: .all-post

.all-pre:
# Add your pre 'all' code here...

.all-post: .all-impl
# Add your post 'all' code here...


# build tests
build-tests: .build-tests-post

.build-tests-pre:
# Add your pre 'build-tests' code here...

.build-tests-post: .build-tests-impl
# Add your post 'build-tests' code here...


# run tests
test: .test-post

.test-pre: build-tests
# Add your pre 'test' code here...

.test-post: .test-impl
# Add your post 'test' code here...


# help
help: .help-post

.help-pre:
# Add your pre 'help' code here...

.help-post: .help-impl
# Add your post 'help' code here...



# include project implementation makefile
include nbproject/Makefile-impl.mk

# include project make variables
include nbproject/Makefile-variables.mk

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

Ese makefile no lo has hecho tu. No te habrías molestado en hacer un makefile tan personalizable para un trabajo de clase.

¿Estás compilando con code::blocks u otro IDE? Si es así la configuración has de establecerla en el IDE, ya que es él el que se encarga de dar las órdenes al compilador.
__________________
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.
  #13 (permalink)  
Antiguo 10/03/2016, 15:00
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 pude con el problema de c++11, lo que tenía que hacer era en propiedades del proyecto, luego a c++ compiler y en c++ standard pongo c++11 y solucionado, sólo q en ManPersonas.h muestra pocos errores:

Código C++:
Ver original
  1. #include <algorithm>
  2. #include <list> // error - In file included from
  3. #include "Persona.h"
  4. #ifndef CONTRPERSONAS_H
  5. #define CONTRPERSONAS_H
  6. using namespace std;    
  7.     std::list<Persona>lista;
  8.     static int maxIdP = 0;
  9.     int getMaxIdP(){
  10.         return ++maxIdP;
  11.     }
  12.     bool check(const Persona& p){
  13.         int num_reg = std::count_if(lista.begin(),lista.end(),[&p](const Persona& p2){
  14.             return p2.nom == p.nom;
  15.         });
  16.         return num_reg > 0;
  17.     }
  18.     Persona* getRow(std::string xnom){
  19.         Persona* toReturn = NULL; // inicialización de puntero nulo
  20.         auto it = std::find_if(lista.begin,lista.end,[&xnom](const Persona& p){
  21.             return p.nom == xnom;
  22.         }); // error - no matching function for call to find_if
  23.         if( it != lista.end())
  24.             toReturn = &(it); // it
  25.         return toReturn;
  26.     }
  27.     Persona* getRow(int xid){
  28.         Persona* toReturn = NULL; // inicialización de puntero nulo
  29.         auto it = std::find_if(lista.begin,lista.end,[&xid](const Persona& p){
  30.             return p.id == xid;
  31.         }); // error - no matching function for call to find_if
  32.         if( it != lista.end())
  33.             toReturn = &(it); // it
  34.         return toReturn;
  35.     }
  36.     bool create(Persona p){
  37.         if(check(p)){            
  38.             return false;
  39.         }
  40.         else{
  41.             lista.push_back(p);
  42.             return true;
  43.         }
  44.     }
  45.     bool update(Persona p){ }
  46.     void remove(Persona p){
  47.         if(check(p)){
  48.             lista.remove(p); // error - in file included from
  49.         }
  50.     }
  51.     std::list<Persona> read(){
  52.         return lista;        
  53.     }  
  54. #endif  /* CONTRPERSONAS_H */

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

Cita:
Iniciado por eferion Ver Mensaje
Prestar atención a los errores

Uno de los errores te está indicando que no se encuentra la sobrecarga del operador de comparación para la clase Persona. En concreto dicho operador se usa aquí:

Código C++:
Ver original
  1. void remove(Persona p){
  2.   if(check(p)){
  3.     lista.remove(p); // <<<--- AQUI!!!!
  4.   }
  5. }

Y se usa porque es la forma en la que remove puede encontrar un elemento equivalente al que le estás pasando como parámetro. Si quieres usar esta función tienes que implementar dicho operador en la clase Persona.

Y con esto el código ya debería compilarte... sigue teniendo algún error más, pero depurando el código deberíais ser capaces de localizarlos.

Un saludo.
Dicho de otra forma, tienes que implementar

Código C++:
Ver original
  1. bool operator==(const Persona& p1, const Persona& p2);

De tal forma que retorne true cuando ambas instancias sean iguales y false en caso contrario.

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.
  #15 (permalink)  
Antiguo 10/03/2016, 17:46
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 usé un remove_if por lo que me dijiste, pero ahora estoy un poco confundido:

Código C++:
Ver original
  1. #include <algorithm>
  2. #include <list>
  3. #include "Persona.h"
  4. #ifndef CONTRPERSONAS_H
  5. #define CONTRPERSONAS_H
  6. using namespace std;    
  7.     std::list<Persona>lista;
  8.     static int maxIdP = 0;
  9.     int getMaxIdP(){
  10.         return ++maxIdP;
  11.     }
  12.     bool check(const Persona& p){
  13.         int num_reg = std::count_if(lista.begin(),lista.end(),[&p](const Persona& p2){
  14.             return p2.nom == p.nom;
  15.         });
  16.         return num_reg > 0;
  17.     }
  18.     Persona* getRow(std::string xnom){
  19.         Persona* toReturn = NULL; // inicialización de puntero nulo
  20.         auto it = std::find_if(lista.begin,lista.end,[&xnom](const Persona& p){
  21.             return p.nom == xnom;
  22.         }); //esta línea da error - no matching function for call to ....
  23.         if( it != lista.end())
  24.             toReturn = &(it); // it
  25.         return toReturn;
  26.     }
  27.     Persona* getRow(int xid){
  28.         Persona* toReturn = NULL; // inicialización de puntero nulo
  29.         auto it = std::find_if(lista.begin,lista.end,[&xid](const Persona& p){
  30.             return p.id == xid;
  31.         }); //esta línea da error - no matching function for call to ....
  32.         if( it != lista.end())
  33.             toReturn = &(it); // it
  34.         return toReturn;
  35.     }
  36.     bool create(Persona p){
  37.         if(check(p)){            
  38.             return false;
  39.         }
  40.         else{
  41.             lista.push_back(p);
  42.             return true;
  43.         }
  44.     }
  45.     bool update(Persona p){ }
  46.     void deleted(Persona p){
  47.         if(check(p)){
  48.             lista.remove_if(lista.begin(),lista.end(),[&p](const Persona& p2){
  49.                 return p.id == p2.id;
  50.             }); //esta línea da error - no matching function for call to ....
  51.         }
  52.     }
  53.     std::list<Persona> read(){
  54.         return lista;        
  55.     }

Lo raro es que da error cuando cierra paréntesis y llave, otra pregunta ¿hay otra forma para obtener elementos que no sea usando punteros?

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

A ver, lo que tienes que hacer es, simple y llanamente, sobrecargar el operador de comparación para que el contenedor sea capaz de comparar elementos de tipo Persona para encontrar el elemento a eliminar.

La función a usar es remove, no remove_if. Sobrecarga el operador (y que funcione correctamente) y el código debería funcionar.

No hagas experimentos raros. Simplemente necesitas decirle a tu programa cómo se comparan dos elementos de tipo Persona.

Por otro lado, sí que es posible devolver elementos sin usar punteros, puedes devolver los objetos tal cual, pero en ese caso tendrías que pensar en algún mecanismo para identificar "objetos no válidos" (por ejemplo si la función tiene que devolverte los datos de "Pedro" pero no hay ningún registro con ese nombre). Una opción puede ser asignar un id negativo o que el nombre esté en blanco... eso ya es decisión tuya.

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.
  #17 (permalink)  
Antiguo 11/03/2016, 17:27
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 ¿cómo estás?, gracias por responder, tenías razón con el remove me costó darme cuenta lo que querías decirme, hice lo que me dijiste y ya no da error el remove

Persona.h

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.     {
  10.         return p.id == id;
  11.     }
  12. };
  13. #endif  /* PERSONA_H */

ManPersonas.h

Código C++:
Ver original
  1. #include <list>
  2. #include "Persona.h"
  3. #ifndef MANPERSONAS_H
  4. #define MANPERSONAS_H
  5. using namespace std;    
  6.     std::list<Persona>lista;
  7.     static int maxIdP = 0;
  8.     int getMaxIdP(){
  9.         return ++maxIdP;
  10.     }
  11.     bool check(Persona p){
  12.         for(Persona per : lista){
  13.             if(per.id == p.id){
  14.                 return true;
  15.             }
  16.         }
  17.         return false;
  18.     }
  19.     Persona getRow(std::string xnom){
  20.         for(Persona p : lista){
  21.             if(p.nom == xnom){
  22.                 return p;
  23.             }
  24.         }
  25.         return NULL; // acá me da error, pero cómo le puedo decir que es nulo cuando no trato con punteros??
  26.     }
  27.     Persona getRow(int xid){
  28.         for(Persona p : lista){
  29.             if(p.id == xid){
  30.                 return p;
  31.             }
  32.         }
  33.         return NULL; // acá me da error, pero cómo le puedo decir que es nulo cuando no trato con punteros??
  34.     }
  35.     bool create(Persona p){
  36.         if(check(p)){            
  37.             return false;
  38.         }
  39.         else{
  40.             lista.push_back(p);
  41.             return true;
  42.         }
  43.     }
  44.     bool update(Persona p){
  45.        
  46.     }
  47.     void deleted(Persona p){
  48.         lista.remove(p);        
  49.     }
  50.     std::list<Persona> read(){
  51.         return lista;        
  52.     }  
  53. #endif  /* MANPERSONAS_H */

Los null me están dando problemas ahora, me queda eso hacer el update para las modificaciones, buscador y paginación, pero los null ahora son mi prioridad.

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

Deberías leerte las respuestas al completo... no solo intuir lo que pone, sino comprender lo que realmente dicen las respuestas.

Cita:
Iniciado por eferion Ver Mensaje
Por otro lado, sí que es posible devolver elementos sin usar punteros, puedes devolver los objetos tal cual, pero en ese caso tendrías que pensar en algún mecanismo para identificar "objetos no válidos" (por ejemplo si la función tiene que devolverte los datos de "Pedro" pero no hay ningún registro con ese nombre). Una opción puede ser asignar un id negativo o que el nombre esté en blanco... eso ya es decisión tuya.
El caso es que tienes que definir una característica que identifique objetos válidos de objetos no válidos y aplicar esa regla en todo tu programa.
__________________
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.
  #19 (permalink)  
Antiguo 12/03/2016, 19:31
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, al final no me da más error con los getRow, lamentablemente tuve que usar los punteros para eso:

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

Pero tengo ahora 2 problemas y es que el checkInt y el addInt no me andan ya q lo que quiero es que me validen de si lo que ingreso es númerico o no:

Código C++:
Ver original
  1. #include <ctime>
  2. #ifndef UTIL_H
  3. #define UTIL_H
  4. using namespace std;
  5. bool checkInt(int s){
  6.     return isdigit(s);
  7. }
  8. bool checkStr(string s){
  9.     for(int i=0; i < s.size(); i++){
  10.         if((s[i] >= 65 and s[i]<= 90) or (s[i] >= 90 and s[i]<= 122)){
  11.             return true;
  12.         }
  13.     }
  14.     return false;
  15. }
  16. void pause(int dur) {
  17.     int temp = time(NULL) + dur;
  18.     while(temp > time(NULL));
  19. }
  20. string addString(string type){
  21.     int intento = 1;
  22.     string nom = "";    
  23.     while(!checkStr(nom)){
  24.         cout << "\n intento nro "<< intento << " Ingrese " << type <<": ";
  25.         cin >> nom;
  26.         intento++;
  27.     }
  28.     return nom;
  29. }
  30. int addInt(string type){
  31.     int intento = 1;
  32.     int nro =0;    
  33.     while(!checkInt(nro)){
  34.         cout << "\n intento nro "<< intento << " Ingrese " << type <<": ";
  35.         cin >> nro;
  36.         intento++;
  37.     }
  38.     return nro;
  39. }
  40. #endif  /* UTIL_H */

Por otro lado cuando quiero agregar un nuevo elemento a mi lista al crear me da el error de: Segmentation Failed.

¿sugerencias?

Espero sus respuestas y saludos
  #20 (permalink)  
Antiguo 13/03/2016, 12:44
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++

Piensa. Que pasa si a create le pasas un puntero invalido?
Cuando se ejecute p->id que crees que suceda?

Por otro lado. Al decidir manejar punteros directamente, aunque uses list tienes que hacerte cargo de devolver la memoria de los objetos. El destructor de list va a destruir los punteros no el contendio. Es una sugerencia.


Saludos
  #21 (permalink)  
Antiguo 13/03/2016, 17: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, resolví el problema pero tuve que instanciar el objeto:

te pongo sólo el código del create del crud

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 = new Persona(); // así me anda
  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. }

pero el check que me asegura de si la persona existe por medio el nombre no funciona:

ManPersonas (parte del check y create)

Código C++:
Ver original
  1. bool check(Persona* p){        
  2.         for(Persona* per : lista){
  3.             if(per->nom == p->nom){
  4.                 return true;
  5.             }
  6.         }
  7.         return false;        
  8.     }
  9. bool create(Persona* p){
  10.         if(check(p)){            
  11.             return false;
  12.         }
  13.         else{
  14.             lista.push_back(p);
  15.             return true;
  16.         }
  17.     }

Pensar que en java y php no tengo los problemas que estoy teniendo en c++ y me da bronca, que sugerencia me das con el check y con la validación de numeros????

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

Código C++:
Ver original
  1. bool check(Persona* p){        
  2.     for(Persona* per : lista){
  3.         if(per->nom == p->nom){
  4.             return true;
  5.         }
  6.     }
  7.     return false;        
  8. }

Si esa función recibe un puntero lo suyo es asegurarse de que el puntero es válido antes de hacer ninguna operación sobre el... salvo que quieras arriesgarte a que tu programa sufra una violación de segmento.

Código C++:
Ver original
  1. bool check(Persona* p){
  2.     if( nullptr != p ){
  3.       for(Persona* per : lista){
  4.           if(per->nom == p->nom){
  5.               return true;
  6.           }
  7.       }
  8.     }
  9.     return false;        
  10. }

Y esta norma es aplicable para toda función que reciba un puntero. Si la función nunca va a recibir un puntero no válido entonces lo suyo es que reciba una referencia o una referencia constante (dependiendo de si el objeto puede ser modificado dentro de la función o no).

Código C++:
Ver original
  1. bool check(Persona& p);
  2.  
  3. bool check(const Persona& p);

Cita:
Iniciado por detective_jd
Pensar que en java y php no tengo los problemas que estoy teniendo en c++ y me da bronca
Java y PHP manejan únicamente punteros solo que en vez de manejarlos con las manos descubiertas usan un recubrimiento especial. El mismo efecto puedes conseguir en C++ si usas smart pointers (shared_ptr, unique_ptr y weak_ptr). En concreto podríamos decir que tanto JAVA como PHP usan un pariente lejano de shared_ptr.

Cita:
Iniciado por detective_jd
que sugerencia me das con el check y con la validación de numeros????
Lo que te comenté anteriormente. Lee una cadena, después verifica que la cadena únicamente contiene números y finalmente convierte dicha cadena en un entero. Si el proceso falla (lo cual únicamente debería pasar en la verificación) entonces le vuelves a pedir el dato al usuario.

No hay que olvidar que C++ es un lenguaje multiusos no especializado en nada en particular. Además nació en una época muy anterior a la de los lenguajes de moda que ya vienen con librerías tremendamente completas. En C++ cosas tan tontas como crear una interfaz mínimamente seria en una consola puede obligarte a hacer más malabares que en el circo... pero gran parte de la culpa la tiene, yo creo, el momento en el que nació (y, por supuesto, que no tiene ninguna gran empresa detrás metiendo pasta como si no hubiera un mañana).

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.
  #23 (permalink)  
Antiguo 13/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++

Hola eferion, funcionó lo que me dijiste:

Con respecto al ManPersonas.h finalmente me anduvo la validación, tuve que limpiar y generar de nuevo el código, estoy teniendo problemas con el update porque no sé cómo cambiar el elemento cambiado a la lista, así me quedó, pongo la parte en lo que respecta al create y update:

Código C++:
Ver original
  1. bool check(Persona* p){
  2.         if(p != nullptr){
  3.             for(Persona* per : lista){
  4.                 if(per->nom == p->nom){
  5.                     return true;
  6.                 }
  7.             }
  8.         }
  9.         return false;        
  10.     }
  11.     Persona* getRow(int xid){
  12.         for(Persona* p : lista){
  13.             if(p->id == xid){
  14.                 return p;
  15.             }
  16.         }
  17.         return NULL;
  18.     }
  19.     bool create(Persona* p){
  20.         if(check(p)){            
  21.             return false;
  22.         }
  23.         else{
  24.             lista.push_back(p);
  25.             return true;
  26.         }
  27.     }
  28.     bool update(Persona* p){
  29.         Persona* per = getRow(p->id);
  30.         if(per->nom != p->nom){
  31.             if(check(p)){
  32.                 return false;
  33.             }
  34.         }
  35.         //pero acá no sé cómo editar el elemento en la lista
  36.         return true;
  37.     }

Por otro lado te hice caso y pude hacer validación con respecto al numero, pero tanto para validar strings como enteros sucede que si ingreso en ambos una letra y un numero no me funciona la validación, no sé q hacer, te pongo el código de los check y add:

Código C++:
Ver original
  1. bool checkInt(string s){
  2.     for(int i=0; i < s.size(); i++){
  3.         if(s[i] >= 48 and s[i]<= 57) {
  4.             return true;
  5.         }
  6.     }
  7.     return false;
  8. }
  9. bool checkStr(string s){
  10.     for(int i=0; i < s.size(); i++){
  11.         if((s[i] >= 65 and s[i]<= 90) or (s[i] >= 90 and s[i]<= 122)){
  12.             return true;
  13.         }
  14.     }
  15.     return false;
  16. }
  17. string addString(string type){
  18.     int intento = 1;
  19.     string nom = "";    
  20.     while(!checkStr(nom)){
  21.         cout << "\n intento nro "<< intento << " Ingrese " << type <<": ";
  22.         cin >> nom;
  23.         intento++;
  24.     }
  25.     return nom;
  26. }
  27.  
  28. int addInt(string type){
  29.     int intento = 1;    
  30.     string numero;
  31.     while(!checkInt(numero)){
  32.         cout << "\n intento nro "<< intento << " Ingrese " << type <<": ";
  33.         cin >> numero;
  34.         intento++;
  35.     }
  36.     return std::stoi(numero);
  37. }

Agradezco tu ayuda y sugerencias, gracias a tí estoy entiendo un poco más c++.

Espero sus respuestas y saludos
  #24 (permalink)  
Antiguo 13/03/2016, 22:41
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++

Debo decir que por un momento me sentí ignorado. Gracias eferion por mencionar la recomendación nuevamente.
Y ahora haciendo eco a su recomendación. En vez de pasar punteros como parámetros, deberías usar referencias. Con esto evitarías algunos problemas.

Aunque ignores la recomendación, la vuelvo a hacer. Piensa en a donde van a parar todas las instancias que creaste con new. Espero que las borres y no estes cultivando un mal hábito (leaks de memoria). Creeme, estas cosas, aunque no lo parezcan, son cruciales a la hora de trabajar en sistemas mayores....
  #25 (permalink)  
Antiguo 14/03/2016, 00:13
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 6 meses
Puntos: 204
Respuesta: headers, carpetas y menúes c++

A este paso nos vais a tener que citar en la memoria de vuestro ejercicio. Deberías también invertir tiempo en investigar por tu cuenta los problemas ya que estamos entrando en una dinámica peligrosa: pruebo lo que me dicen, compilo, falla, reporto los errores y a la cama.

Deberías aprender a usar el depurador de código para localizar errores en tiempo de ejecución. Es una herramienta imprescindible.

Un par de pistas a tu problema:
  • ¿Qué sucede con el ciclo de ejecución de un bucle si aparece un return?
  • Cuando calidad un dato se presupone que la validación no sabes si es correcta hasta que no has hecho TODAS las comprobaciones... Mientras tanto lo máximo que puedes llegar a tener claro es que la validación no es correcta... Tu lo estás intentando hacer al revés.

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.
  #26 (permalink)  
Antiguo 14/03/2016, 13:29
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 ¿cómo están?, gracias por responder, créanme que si no me mareara tanto los punteros y los valores por referencia no pediría ayuda, además hice lo que me dijeron y me dan más errores, cómo dije anteriormente tanto en java como php no tengo este tipo de problemas pero con esto de los punteros y los parámetros por referencia sí, pongo el código:

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

Tampoco es la idea que me hagan la tarea, ya que esto es para mi primo que está haciendo ingeniería en electrotecnia, y me pide ayuda........
Lo de las validaciones lo tendré q ver bien cómo arreglármelas..

Espero sus respuestas y saludos.

Última edición por detective_jd; 14/03/2016 a las 13:46
  #27 (permalink)  
Antiguo 14/03/2016, 14:01
 
Fecha de Ingreso: octubre-2014
Ubicación: Madrid
Mensajes: 1.212
Antigüedad: 9 años, 6 meses
Puntos: 204
Respuesta: headers, carpetas y menúes c++

Cita:
Iniciado por detective_jd Ver Mensaje
Tampoco es la idea que me hagan la tarea, ya que esto es para mi primo que está haciendo ingeniería en electrotecnia, y me pide ayuda..
Lo único que te puedo decir a este respecto es que le haces un flaco favor... Con esto le estás haciendo los deberes... Pero piensa que al examen se va a enfrentar el solito.

Lo suyo en tal caso sería que fuese él el que se pasase por aquí a preguntar dudas y el que se rompiese los cuernos sacando el programa adelante.

Lo que está sucediendo ahora es que tu estás aprendiendo el C++ que él necesita para pasar la asignatura y no tengo muy claro que ese conocimiento se le vaya a trasvasar a él.

Lo mismo estoy equivocado, pero tengo casos más que suficientes para pensar así.

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.
  #28 (permalink)  
Antiguo 14/03/2016, 15:09
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++

Cita:
Iniciado por detective_jd Ver Mensaje
Hola ¿cómo están?, gracias por responder, créanme que si no me mareara tanto los punteros y los valores por referencia no pediría ayuda, además hice lo que me dijeron y me dan más errores, cómo dije anteriormente tanto en java como php no tengo este tipo de problemas pero con esto de los punteros y los parámetros por referencia sí, pongo el código:

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

Tampoco es la idea que me hagan la tarea, ya que esto es para mi primo que está haciendo ingeniería en electrotecnia, y me pide ayuda........
Lo de las validaciones lo tendré q ver bien cómo arreglármelas..

Espero sus respuestas y saludos.
Las referencias técnicamente nunca son nulas. Por lo tanto ese if ya no es necesario, incluso el compilador da error, el cual deberías leer.
Por otro lado, cuando usas referencias, no usas el operador -> que sólo aplica a punteros, usas el operador .(punto).

El push_back te da error porque creaste una lista de punteros, no de objetos. Quitale el * a la lista. Aquí sería interesante que tu o tu primo investigaran un poco sobre las semánticas de copiado y de movido.
También dentro de los for, no obtengas un puntero, obten una referencia al objeto. C++11 hace algo de magia y automáticamente usa semántica de movimiento, lo cual lo hace algo mas eficiente.
Hay un patrón de diseño llamada Null Object (objeto nulo). Revísenlo para ver el caso donde no se encuentre la persona. De hecho eferion ya te dijo masomenos como funciona.
Te recomiendo que uses const en los parametros que no modificas, que me parece son todos. Igual, eso ayuda al compilador a crear mejor código máquina.

Finalmente, ten en cuenta lo que menciona eferion. Es bueno ayudarte (aunque me ignoren ) y que termines tu aprendiendo. Que mal por tu primo, porque el mundo que viene exige soltura con la programación al igual que en el habla. En un futuro no muy lejano, no saber programar lo básica será lo mismo que ser analfabeta.
  #29 (permalink)  
Antiguo 14/03/2016, 20:41
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, con respecto a mi primo ni empezaron a programar en la utu porque recién empezaron las clases, y van a demorar bastante como para empezar a programar.
Por otro lado, estoy en que me rindo Instru hice lo que me dijiste, y hasta me puse a investigar lo de Null Object, y lo que he encontrado es con java, de c++ encontré más o menos esto:

http://stackoverflow.com/questions/2...sult-not-found

Lo malo es que casi todos te dicen el uso de punteros, además con tengo serios problemas con el update, con lo de null tuve que poner excepciones pero cuando ingreso un nombre que no es, termina la app:

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.     static int maxIdP = 0;
  10.     int getMaxIdP(){
  11.         return ++maxIdP;
  12.     }
  13.     bool check(const Persona& p){
  14.         for(Persona per : lista){
  15.             if(per.nom == p.nom){
  16.                 return true;
  17.             }
  18.         }        
  19.         return false;        
  20.     }
  21.     Persona getRow(std::string xnom){
  22.         for(Persona p : lista){
  23.             if(p.nom == xnom){
  24.                 return p;
  25.             }
  26.         }
  27.         throw "no existe";
  28.     }
  29.     Persona getRow(int xid){
  30.         for(Persona p : lista){
  31.             if(p.id == xid){
  32.                 return p;
  33.             }
  34.         }
  35.         throw "no existe";
  36.     }
  37.     bool create(const Persona& p){
  38.         if(check(p)){            
  39.             return false;
  40.         }
  41.         else{
  42.             lista.push_back(p);
  43.             return true;
  44.         }
  45.     }
  46.     bool update(const Persona& p){
  47.         Persona per = getRow(p.id);
  48.         std::list<Persona>::iterator findIter = find(lista.begin(), lista.end(), p);
  49.         if(per.nom != p.nom){
  50.             if(check(p)){
  51.                 return false;
  52.             }
  53.         }
  54.         lista.remove(per);
  55.         lista.insert(findIter,p); //asi con el remove y insert me da este error: Segmentation fault; real time: 21s; user: 0ms; system: 4s
  56.         return true;
  57.     }
  58.     void deleted(const Persona& p){
  59.         lista.remove(p);        
  60.     }
  61.     std::list<Persona> read(){
  62.         return lista;        
  63.     }  
  64. #endif  /* MANPERSONAS_H */

Pero y: ¿ahora que?

espero sus respuestas y saludos
  #30 (permalink)  
Antiguo 14/03/2016, 23:06
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++

Se ve mucho mejor el código.

En el update hay varias cosas.

En C++11 en adelante, puedes usar auto como tipo de variable, siempre y cuando el valor que le asignes identifique claramente el tipo. En este caso te puedes beneficiar:

Código:
auto findIter = find(lista.begin(), lista.end(), p);
Ahora ten en cuenta que si p no esta en la lista, entonces finIter == lista.end().
No te parece que este código no tiene mucho sentido?
Código:
if(per.nom != p.nom){
            if(check(p)){
                return false;
            }
        }
Si nom no es igual, checamos que sea igual??????
Sospecho que te da error, por eso mismo. Al parecer estas intentando asignar algo en lista.end() la cual es una localidad invalida. Revisa esa parte.

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.

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 19:49.