elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.

 

 


Tema destacado: ¿Eres nuevo? ¿Tienes dudas acerca del funcionamiento de la comunidad? Lee las Reglas Generales


  Mostrar Mensajes
Páginas: 1 ... 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 [123] 124 125
1221  Programación / Programación C/C++ / Re: Socket send and recv problema en: 2 Julio 2013, 10:01 am
El tráfico de red se puede optimizar... pero mi consejo es ir por partes... primero haz que funcione y luego lo optimizas.

1222  Programación / Programación C/C++ / Re: error estructura al compilar en: 2 Julio 2013, 09:59 am
Primero me voy a centrar en el estilo de programación:

1. Las clases mejor pasarlas como referencia.

Código
  1. int donde_esta(string nombre,vector<ranking>&v)

Este tipo de definiciones, por defecto, intenta evitarlas... estás pasando string por valor en vez de por referencia, esto implica duplicar la cadena en memoria cada vez que llamas a la función y el rendimiento se puede resentir y muchísimo.

Es mejor pasar una referencia constante, así:

Código
  1. int donde_esta( const string& nombre, vector< ranking >& v )

2. Separa el código con espacios y tabula correctamente

Código
  1. vector<ranking> classificacion(vector<usuario> p)
  2. {
  3.  vector<ranking>v;
  4.  for(int i=0;i<p.size();i++)
  5.  {
  6.    int lugar = donde_esta(p[i].nombre, v);
  7.    v[lugar].total_pruebas = v[lugar].total_pruebas + 1;
  8.    v[lugar].puntos = v[lugar].puntos + p[i].puntos;
  9.    if(p[i].tipo_competicion == 's')
  10.    {
  11.      v[lugar].pruebas_puntuables = v[lugar].pruebas_puntuables + 1;
  12.    }
  13.    else if(p[i].tipo_competicion == 'n'
  14.    {
  15.      v[lugar].pruebas_puntuables = v[lugar].pruebas_puntuables + 0;
  16.    }
  17.  }
  18.  
  19.  return v;
  20. }

Queda algo más claro que

Código
  1. vector<ranking>classificacion(vector<usuario>p){
  2. vector<ranking>v;
  3. for(int i=0;i<p.size();i++){
  4.       int lugar=donde_esta(p[i].nombre,v);
  5.       v[lugar].total_pruebas=v[lugar].total_pruebas+1;
  6.       v[lugar].puntos=v[lugar].puntos+p[i].puntos;
  7.       if(p[i].tipo_competicion=='s'){
  8.                                      v[lugar].pruebas_puntuables=v[lugar].pruebas_puntuables+1;}
  9.  
  10.       else if(p[i].tipo_competicion=='n'){v[lugar].pruebas_puntuables=v[lugar].pruebas_puntuables+0;}
  11.       }
  12.       return v;
  13.       }

Y la claridad es algo que los que te ayudan agradecen, ya que tienden a dejarse menos la vista para comprender tu código ;)

3. Evita líneas absurdas

Como suena, esto

Código
  1. if(p[i].tipo_competicion=='s')
  2. {
  3.  v[lugar].pruebas_puntuables=v[lugar].pruebas_puntuables+1;
  4. }
  5. else if(p[i].tipo_competicion=='n')
  6. {
  7.  v[lugar].pruebas_puntuables=v[lugar].pruebas_puntuables+0;
  8. }

Se puede simplificar tranquilamente y quedar así:

Código
  1. if(p[i].tipo_competicion=='s')
  2. {
  3.  v[lugar].pruebas_puntuables = v[lugar].pruebas_puntuables+1;
  4. }
  5.  

Ya que X + 0 = X... nos podemos ahorrar la comprobación y la suma... porque si no, ya puestos, ¿que pasa cuando tipo_competicion no es ni 's' ni 'n'?

Y esto aún se podría simplificar un poco más, tal que

Código
  1. if(p[i].tipo_competicion=='s')
  2. {
  3.  v[lugar].pruebas_puntuables++;
  4. }

o si prefieres ganar un poco más de rendimiento:

Código
  1. if(p[i].tipo_competicion=='s')
  2. {
  3.  ++v[lugar].pruebas_puntuables;
  4. }


Los preincrementos pueden llegar a ser bastante más eficientes que los postincrementos.

4. Los iteradores son tus amigos

un bucle for te sirve perfectamente para recorrer un array... sin embargo manejar ese array con índices te va a obligar a escribir bastante más texto... con el consecuente incremento de probabilidades de error.

Menos texto, si es con cabeza, suele significar muchas veces código más legible y fácil de mantener.

Además la mayoría de funciones de la stl utilizan los iteradores para manipular los vectores, por lo que aprener a manejarlos te va a permitir usar la stl en muchísimas situaciones.

Código
  1.  
  2. // He puesto postincrementos en vez de preincrementos porque creo que son más fáciles de ver cuando estás aprendiendo.
  3. vector< ranking >::const_iterator it;
  4. for ( it = p.begin( ); it != p.end( ); ++it )
  5. {
  6.  int lugar = donde_esta( it->nombre, v );
  7.  v[ lugar ].total_pruebas++;
  8.  v[ lugar ].puntos += it->puntos;
  9.  if ( it->tipo_competicion == 's' )
  10.  {
  11.    v[ lugar ].pruebas_puntuables++;
  12.  }
  13. }

En vez de

Código
  1. for(int i=0;i<p.size();i++)
  2. {
  3.  int lugar=donde_esta(p[i].nombre,v);
  4.  v[lugar].total_pruebas=v[lugar].total_pruebas+1;
  5.  v[lugar].puntos=v[lugar].puntos+p[i].puntos;
  6.  if(p[i].tipo_competicion=='s')
  7.  {
  8.    v[lugar].pruebas_puntuables=v[lugar].pruebas_puntuables+1;
  9.  }
  10. }

5. Una función, un return.

Cuando aprendas a depurar, te darás cuenta que tener un solo return en una función te facilita mucho la vida. Con un solo breakpoint podrás controlar la salida de la función para saber si es correcta o no. Sin embargo si tienes 20 returns repartidos por la función la tarea se empieza a complicar.

Hay a gente a la que le gusta llenar las funciones de returns... yo solo lo hago si la función con returns queda muchísimo más sencilla y clara que sin ellos.

En el caso de tu función y aplicando esta norma quedaría así:

Código
  1. bool ordenar_pruebas(ranking c1, ranking c2)
  2. {
  3.  bool to_return = true;
  4.  
  5.  if (c1.total_pruebas==c2.total_pruebas)
  6.  {
  7.     if(c1.puntos==c2.puntos)
  8.        to_return = c1.nombre<c2.nombre;
  9.     else
  10.        to_return = c1.puntos>c2.puntos;
  11.  }
  12.  else
  13.    to_return = c1.total_pruebas>c2.total_pruebas;
  14.  
  15.  return to_return;            
  16. }

6. Las clases también son tus amigas

En vez de estructuras, prueba a usar clases y aprovecha sus características. Las clases y las estructuras en c++ son iguales salvo porque, por defecto, las clases tienen sus miembros privados mientras que en las estructuras son públicos.

En cualquier caso, por convención, es más natural usar clases en el código normal de c++ y dejar las estructuras para intercambio de datos vía sockets por ejemplo.

Además, una característica imprescindible de las clases y estructuras en c++ son los constructores, que te permiten inicializar las clases para que tengan valores válidos al crearlas. Esto te evita tener que inicializarlas tu a mano cada vez que instancias una clase.

Si tu pones:

Código
  1. class ranking
  2. {
  3.  public:
  4.    ranking( const string& nombre )
  5.    {
  6.      this->nombre = nombre;
  7.      total_pruebas = 0;
  8.      pruebas_puntuables = 0;
  9.      puntos = 0;
  10.    }
  11.  
  12.    string nombre;
  13.    int total_pruebas;
  14.    int pruebas_puntuables;
  15.    int puntos;
  16. };

entonces:

Código
  1. int donde_esta(string nombre,vector<ranking>&v)
  2. {
  3.  for (int i = 0 ; i < v.size() ; i++)
  4.  {
  5.    if (v[i].nombre == nombre)
  6.      return i;
  7.  }
  8.  
  9.  // Esto que viene ...
  10.  ranking r;
  11.  r.nombre=nombre;
  12.  r.total_pruebas=0;
  13.  r.pruebas_puntuables=0;
  14.  r.puntos=0;
  15.  //  ... se sustituye por ...
  16.  ranking r( nombre );
  17.  // ... una sola linea!!!  
  18. }

También sería interesante que las variables fuesen privadas y creases funciones para acceder y modificar sus valores, pero tampoco me voy a poner a redactar aquí un libro de c++ :D

7. Una función, una tarea

Actualmente, la función donde_esta hace demasiadas cosas. Por un lado busca un elemento en el vector y, si no se encuentra, intenta añadirlo.

Bueno, en primer lugar la función está mal hecha porque no añade nunca el elemento en el vector y, aunque lo hiciese, no devuelve la posición de dicho elemento, estos son los errores que tienes actualmente en el código.

Pero hablando de la función en si, una función que se llama donde_esta, debería centrarse únicamente en localizar un elemento y devolver su posición. Si el elemento no se encuentra debería devolver un índice no válido para poder identificar el error.

Si luego quieres añadir un nuevo elemento y que te de su posición prueba a crear una función nueva que sea nuevo_elemento, por ejemplo.

El que una función haga más cosas de las que debe te genera el problema de que mantener esa función en el futuro va a ser complicado, ya que ahora tienes muy reciente cómo funciona y que hace... pero dentro de 6 meses la memoria no será tan buena y tener una función que se llama, por ejemplo, despertador, y que aparte de sonar la alarma se encarga de preparar el desayuno, levantar las persianas, hacer la cama, encender la caldera, ... complicado de entender.

Dicho esto, una propuesta quizás sería: ( voy a aplicar todos los consejos que te he indicado )

Código
  1. #include<iostream>
  2. #include<vector>
  3. #include<algorithm>
  4.  
  5. using namespace std;
  6.  
  7. class usuario
  8. {
  9.  public:
  10.    string nombre;
  11.    bool tipo_competicion; // su funcion es booleana... o es competicion o no lo es, mejor bool
  12.    int puntos;
  13.  
  14.    // Constructores SIEMPRE para inicializar la memoria.
  15.    // * nombre no hace falta inicializarlo porque es una clase y ya tiene su propia inicializacion,
  16.    //   aunque podria ponerse si quieres.
  17.    usuario( )
  18.      : tipo_competicion( false ),
  19.        puntos( 0 )
  20.    {
  21.    }
  22. };
  23.  
  24. class ranking
  25. {
  26.  public:
  27.    string nombre;
  28.    int total_pruebas;
  29.    int pruebas_puntuables;
  30.    int puntos;
  31.  
  32.    // Esta forma de inicializar las variables es mas optima que la que te he explicado antes.
  33.    // Tambien quizas un poco mas complicada de entender, pero como he dicho, es mejor.
  34.    ranking( const string& nombre_alumno )
  35.      : nombre( nombre_alumno ),
  36.        total_pruebas( 0 ),
  37.        pruebas_puntuables( 0 ),
  38.        puntos( 0 )
  39.    {
  40.    }
  41.  
  42.    // Aprovechando las caracteristicas de las clases, metemos el sumador aqui
  43.    void suma( const usuario& usuario )
  44.    {
  45.      ++total_pruebas;
  46.      puntos+= usuario.puntos;
  47.      if ( usuario.tipo_competicion )
  48.        ++pruebas_puntuables;
  49.    }
  50. };
  51.  
  52. vector< ranking >::iterator donde_esta( const string& nombre,
  53.                                        vector< ranking >& v )
  54. {
  55.  vector< ranking >::iterator it;
  56.  for ( it = v.begin( ); it != v.end( ); ++it )
  57.  {
  58.    if ( it->nombre == nombre )
  59.      break;
  60.  }
  61.  
  62.  return it;
  63. }
  64.  
  65. vector< ranking >::iterator nueva_entrada( const string& nombre,
  66.                                           vector< ranking >& v )
  67. {
  68.  ranking r( nombre );
  69.  v.push_back( r );
  70.  
  71.  return donde_esta( nombre, v );
  72. }
  73.  
  74. vector< ranking > classificacion( const vector< usuario >& p)
  75. {
  76.  vector< ranking > v;
  77.  vector< usuario >::const_iterator it_usuario;
  78.  
  79.  for( it_usuario = p.begin( ); it_usuario != p.end( ); ++it_usuario )
  80.  {
  81.    vector< ranking >::iterator it_ranking = donde_esta( it_usuario->nombre, v );
  82.    if ( it_ranking == v.end( ) )
  83.      it_ranking = nueva_entrada( it_usuario->nombre, v );
  84.  
  85.    it_ranking->suma( *it_usuario );
  86.  }
  87.  
  88.  return v;
  89. }
  90.  
  91. bool ordenar_pruebas( const ranking& c1,
  92.                      const ranking& c2)
  93. {
  94.  bool to_return;
  95.  
  96.  if( c1.total_pruebas == c2.total_pruebas )
  97.  {
  98.    if( c1.puntos == c2.puntos )
  99.      to_return = c1.nombre<c2.nombre;
  100.    else
  101.      to_return = c1.puntos>c2.puntos;
  102.  }
  103.  else
  104.    to_return = c1.total_pruebas>c2.total_pruebas;
  105.  
  106.  return to_return;
  107. }
  108.  
  109. bool ordenar_puntos( const ranking& c1,
  110.                     const ranking& c2)
  111. {
  112.  bool to_return;
  113.  
  114.  if( c1.puntos == c2.puntos )
  115.    to_return = c1.nombre<c2.nombre;
  116.  else
  117.    to_return = c1.puntos>c2.puntos;
  118.  
  119.  return to_return;
  120. }
  121.  
  122. int main()
  123. {
  124.  int n;
  125.  cout << "introduzca el numero de elementos de la estructura" << endl;
  126.  cin >> n;
  127.  vector< usuario > p(n);
  128.  
  129.  cout << ":::::::::::::::::::::::::::::::::::::::::::::::" << endl;
  130.  cout << endl;
  131.  
  132.  for(int i=0;i<n;i++)
  133.  {
  134.    // Para separar un poco mas el texto.
  135.    cout << endl;
  136.  
  137.    // Es mejor guiar al usuario por pasos
  138.    cout << "nombre: ";
  139.    cin >> p[i].nombre;
  140.  
  141.    cout << "competicion (s/n): ";
  142.    char c;
  143.    cin >> c;
  144.    // si no se introduce una s, se interpreta que no es de competicion.
  145.    // si quieres forzar a que el usuario introduzca s o n te toca programarlo
  146.    p[i].tipo_competicion = ( c == 's' );
  147.  
  148.    cout << "puntos: ";
  149.    cin >> p[i].puntos;
  150.  }
  151.  
  152.  vector< ranking > v = classificacion(p);
  153.  cout << "-----------------------" << endl;
  154.  
  155.  sort( v.begin(), v.end(), ordenar_pruebas );
  156.  
  157.  cout << "LISTA" << endl;
  158.  
  159.  vector< ranking >::const_iterator it;
  160.  for( it = v.begin( ); it != v.end( ); ++it )
  161.  {
  162.    cout << it->nombre << " "
  163.         << it->total_pruebas << " "
  164.         << it->pruebas_puntuables << " "
  165.         << it->puntos << endl;
  166.  }
  167.  
  168.  system("pause");
  169.  return 0;
  170. }
1223  Programación / Programación C/C++ / Re: planteamiento de problema en: 2 Julio 2013, 08:38 am
También podrías tratarlo como un vector usando estructuras.
1224  Programación / Programación C/C++ / Re: Duda sobre portabilidad en: 2 Julio 2013, 08:36 am
O bien, si eres más purista y no te gustan los condicionales del compilador en medio del código:

Código
  1. #ifdef _WIN32
  2. char* limpiar_pantalla_cmd = "CLS";
  3. #else
  4. char* limpiar_pantalla_cmd = "clear";
  5. #endif
  6.  
  7. void func( )
  8. {
  9.  
  10.  // ...
  11.  
  12.  system( limpiar_pantalla_cmd );
  13.  
  14.  // ...
  15.  
  16. }
1225  Programación / Programación C/C++ / Re: maximo de una matriz? en: 2 Julio 2013, 00:04 am
Código
  1. for (f = 0; f < 5;f++)
  2. {
  3.   for (c= 1; c < 5;c++)

el primero es un bucle para las filas ( por eso la f por nombre de variable ) que las recorre de la 0 a la 4. El segundo es un bucle para columnas... y las recorre de la 0 a la 4... y eso para cada valor de f.

Dicho esto, si, estarías recorriendo toda la matriz.

Y dicho esto también me permito añadir lo siguiente: si te pierdes con dos bucles y cuatro líneas de código ponte las pilas porque esto no es ni tan siquiera la punta del iceberg. Aprende a usar el depurador de c++ y a seguir la traza de los programas... te ayudará a comprender mejor cómo funciona el código... y haz muuuuchas prácticas :)
1226  Programación / Programación C/C++ / Re: Duda con el envío encadenado a través de cout en C++ en: 1 Julio 2013, 23:59 pm
C++ no necesita limpieza de buffer ni esas bobadas que tenía C

Corrección: no está de más, antes de hacer una lectura del buffer de teclado asegurarse de que el usuario no ha escrito nada antes que pueda afectar a la lectura... como todo buffer almacena información y a no ser que la leas o descartes sigue ahí esperándote cual bomba de relojería.
1227  Programación / Programación C/C++ / Re: Ayuda! Problema de un menu!!! en: 1 Julio 2013, 23:55 pm
Código
  1. struct partidas
  2. {
  3.  char nom_jug[40];
  4.  char ced_jug[8];
  5. };
  6.  
  7. struct partidas partida1, partida2;

Es lo mismo, más claro y con menos código que:

Código
  1. struct partidas1
  2. {
  3.  char nom_jug[40];
  4.  char ced_jug[8];
  5.  
  6. } partidas1[500];
  7.  
  8. struct partidas2
  9. {
  10.  char nom_jug[40];
  11.  char ced_jug[8];
  12. } partidas2[500];

Aunque si lo que quieres es, por ejemplo almacenar los datos de las últimas 10 partidas necesitarías quizas algo así:

Código
  1. struct partidas
  2. {
  3.  char nom_jug[40];
  4.  char ced_jug[8];
  5. };
  6.  
  7. struct partidas partidas[10];

Con eso tendrías un array que te permitiría almacenar hasta 10 partidas.

Ahora la cosa, te lo dejo como tarea porque no voy a resolverte toda la práctica, es almacenar en ese array las diferentes partidas que vayas jugando.

Recuerda que lo primero es inicializar el array para que no muestre basura ( este consejo es gratis ), y luego almacenar los resultados en la posición en que correspondan.
1228  Programación / Programación C/C++ / Re: Problema con apuntadores!!!!!! en: 1 Julio 2013, 21:30 pm
Código
  1.          if(*computadora<*opcion)
  2.                        printf("Mi numero es meno\n");
  3.                else if(*computadora>*opcion)
  4.                        printf("Mi numero es mayor\n");
  5.                else
  6.                        printf("Acertaste");
  7.                        exit(1);

ese exit( 1 ) se va a ejecutar siempre.

Si quieres que un if o un else abarque más de una instrucción tienes que ponerlo entre llaves.

Más cosas... estás almacenando el dato del usuario en opcion y aparte usas esa variable para comprobar que no se pasa de 7 intentos... no va a funcionar.

Y además, personalmente, prefiero no usar exit salvo causas de fuerza mayor... yo lo dejaría así:

Código
  1. int main()
  2. {
  3.  int num,com,i;
  4.  int acertado = 0;
  5.  int *numero,*computadora,*opcion;
  6.  numero = &num;
  7.  computadora = &com;
  8.  opcion = &i;
  9.  printf("Juego que adivina el numero de la computadora<----------\n");
  10.  srand(time(NULL));
  11.  *computadora = (rand()%50)+1;
  12.  printf("Tienes 7 oportunidades para adivinar el numero\n");
  13.  for(*opcion=1;(*opcion<=7) && (acertado == 0);(*opcion)++)
  14.  {
  15.    printf("%d oportunidad---->",*opcion);
  16.    scanf("%d",numero);
  17.    if(*computadora<*numero)
  18.      printf("Mi numero es meno\n");
  19.    else if(*computadora>*numero)
  20.      printf("Mi numero es mayor\n");
  21.    else
  22.    {
  23.      printf("Acertaste");
  24.      acertado = 1;
  25.    }
  26.  }
  27.  
  28.  if ( acertado == 0 )
  29.  {
  30.    printf("Lastima se te acabaron las oportunidades\n");
  31.    printf("%d",*computadora);
  32.  }
  33.  
  34.  return 0;
  35. }

Verás que también he eliminado el uso de ii... ya tienes esa información en la variable *opcion, luego es redundante... aparte de que no incrementabas nunca el valor de dicha variable.

Deberías aprender a usar los depuradores para corregir los errores de tu código.

Un saludo
1229  Programación / Programación C/C++ / Re: Duda con el envío encadenado a través de cout en C++ en: 1 Julio 2013, 20:48 pm
pues usa QtCreator... no hace falta que uses las librerías de Qt, puedes programar también con la stl si quieres... y desde luego funciona muuuuucho mejor que Devcpp
1230  Programación / Programación C/C++ / Re: for y do while en: 1 Julio 2013, 17:26 pm
a y b entiendo que son matrices dinámicas, no?

Código
  1. int** a, b;

o las estás declarando con un tamaño estático y rezas para que el usuario no pida un tamaño superior al que has definido ??

Lo pregunto porque las soluciones serían ligeramente diferentes.

es que tambien me parece demasiado repetitivo el codigo, ingresarle para una matriz, luego ingresarle para otra.. seria bueno hacerlo con una funcion como dijo eferion???

Yo solo hice una apreciación y es que aprender a dividir el código en funciones no es siempre una tarea fácil... practicarlo con ejemplos sencillos ayuda luego a desenvolverse con códigos más complejos... pero no deja de ser una decisión tuya si pones funciones o todo junto.

El código puede funcionar igual de bien... otra cosa es lo que tu practiques y, en consecuencia, aprendas, al hacer estas prácticas.
Páginas: 1 ... 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 [123] 124 125
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines