Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - K-YreX

#131
Lo primero de todo: el código debe estar publicado entre etiquetas de Código GeSHi. Ya te hemos corregido los mensajes anteriores pero lo suyo es que lo hagas tú a partir de ahora. Si no sabes cómo hacerlo, encima del cuadro de texto hay un desplegable que dice "Código GeSHi". Ahí tienes que seleccionar el lenguaje correspondiente y aparecerán en el cuadro de texto dos etiquetas code. Tu código debe ir entre esas dos etiquetas. Las etiquetas también las puedes escribir a mano sin usar el desplegable.



Los problemas que veo a simple vista son:
  • Línea 15 -> El for() debe empezar por el final e ir hacia el principio por lo que tienes que revisar tanto la condición como la actualización (los dos últimos campos del for()).
  • Línea 87 -> En C/C++ los arrays empiezan en la posición 0. Por lo tanto un array de longitud 5 tendrá como último elemento el 4 {0, 1, 2, 3, 4}. Esto es importante al trabajar con los índices de los arrays. Tienes que corregir eso pues no muestras el elemento 0 (porque empiezas en 1) y muestras el elemento cont (que ya está fuera del límite).
  • Línea 57 -> Por el mismo motivo que el punto anterior, debes empezar en 0.
  • Línea 61 -> Por el mismo motivo otras vez, no puedes repetir el bucle si (cont == k) porque estarás accediendo fuera del límite. Tienes que corregir la condición.


    Otras cosas que puedes mejorar son:
  • Líneas 59 y 65 -> La variable <a_insertar> no es necesaria. Puedes utilizar directamente <vector>.
    • Líneas 67 - 77 -> El if-else no es necesario. No tienes que tratar el primer caso diferente pues la función InsertarOrdenado() funciona correctamente para todos los casos.
#132
No veo cuál es el problema que comentas. No tienes que guardar 3 valores (2 strings y 1 int) pues estos están encapsulados dentro de una clase. Lo que tú vas a guardar es el objeto de esa clase únicamente. Sería algo así el esquema general:
Código (cpp) [Seleccionar]

class Insumo {
  private:
    std::string nombreIQ;
    std::string unidadMedida;
    int stock;
  //...
};

class Consumo {
  private:
    std::string nombreIQ;
    int cantidadConsumida;
    int fecha; // o el tipo de dato que sea
  //...
};

class Produccion {
  private:
    std::map<std::string, std::vector<Insumo>> insumos;
    std::map<std::string, Consumo> consumos;
  //...
};


No sé si esto te sirve pero por lo que veo estabas intentando meter los atributos por separado en el map en vez de crear una clase como te dice en el enunciado. Al final esto es lo que viene siendo el paradigma de programación orientada a objetos (POO): utilizar clases para encapsular información de una entidad y poder utilizar esa clase para instanciar objetos de ese tipo.
#133
Cuando hay que implementar algoritmos que requieren usar un poco el coco ayuda bastante crear funciones y separar así el código. Esto ayuda a entender mejor el funcionamiento y en caso de error es más fácil saber a qué función dirigirse para corregirlo.

La parte de los valores de entrada lo obviaré pues no será ningún problema. Entonces empezamos con un array <vector> lleno de números y otro <mayores> vacío donde hay que introducir los <numMayores> primeros valores de <vector> que sean mayores que <valorMinimo> ordenados.

insertados := 0 // numero de elementos insertados en mayores
indice := 0
MIENTRAS indice < vector.size AND insertados < numMayores HACER
  SI vector[indice] >= valorMinimo ENTONCES
    insertarOrdenado(vector[indice], mayores) // Inserta el valor indicado en el array de forma ordenada
    insertados := insertados + 1 // incrementa el numero de insertados en el array
  FIN SI
FIN MIENTRAS

Ya está como ves queda muy muy sencillo. Ahora obviamente hay que entrar en lo que sería la función insertarOrdenados() y ver cómo hacerla, pero ya vamos dividiendo el trabajo.

En la función insertarOrdenado() tienes que ver qué índice le correspondería al valor a insertar. Si ese índice no es la primera posición libre, tendrás que mover todos los valores a la derecha de este. Necesitas conocer también el número de elementos actuales del array por lo que tendrás que pasarlo por parámetro también. Además recomiendo pasar la longitud máxima del array para comprobar que hay huecos (aunque en este caso ya lo hemos comprobado antes con: insertados < numMayores por lo que no es obligatorio)

Función insertarOrdenado (valor : entero, v : array, size : entero, maxSize : entero)
INICIO
  SI size < maxSize ENTONCES // comprobar que hay huecos. Se puede omitir en este caso pero mejor no. Asi la funcion es mas reutilizable y evita errores
    indiceInsercion := 0 // indice que le corresponde al elemento
    MIENTRAS indiceInsercion < size AND v[indiceInsercion] < valor HACER
      indiceInsercion := indiceInsercion + 1
    FIN MIENTRAS
    SI indiceInsercion != size ENTONCES // si no se inserta al final, hay que mover elementos
      moverDerecha(v, indiceInsercion, size+1) // Mueve una posicion a la derecha desde el indiceInsercion para hacer el hueco. Los detalles los explico mas adelante
    FIN SI
    v[indiceInsercion] = valor
  FIN SI
FIN


Ahora vamos a la última función que nos falta: moverDerecha(). Esta función mueve una posición a la derecha desde el índice indicado hasta el final. Realmente hay que hacerlo en sentido inverso, es decir, empezar por el final e ir guardando en cada posición el valor de la anterior (para no sobreescribir datos y que falle). El último parámetro que he pasado (size+1) indica la longitud del array. Hay que entender que ahora ya trabajamos con un elemento más (aunque de momento haya un hueco) por lo que si ponemos size, tendremos problemas con el último valor. El pseudocódigo de esta sería:

Funcion MoverDerecha (v: array, inicio : entero, longitud : entero)
INICIO
  PARA i := longitud - 1 HASTA inicio + 1 HACER // Desde el final hasta el indice del hueco mover los elementos. En inicio ya no hace falta pues lo vamos a sobreescribir
    v[i] = v[i-1]
  FIN PARA
FIN


Y con esto ya estaría terminado. Si implementas cada una de las funciones que te he comentado y las juntas, funcionará correctamente. Si tienes algún problema postea tus avances para ir guiándote o corregirte los errores. Suerte :-X
#134
1. El tema debería ir en el foro específico de Programación C/C++.
2. El código debe ir entre etiquetas de código GeSHi. Además como te han dicho debe estar bien tabulado para facilitar la lectura a los demás.
3. Ese programa que pones tiene varios errores además de cosas mejorables. Tomarlo como ejemplo me parece un error.
4. Claro que te ayudamos pero no te vamos a hacer la tarea. Pon lo que lleves hecho del programa (no del ejemplo sino del que tienes que hacer) y los problemas que tengas.
#135
Cita de: Filantropo en  6 Diciembre 2020, 02:18 AM
el problema es que el SP_CLIENTE_BUSCAR devuelve registros duplicados y en orden inverso durante la paginacion, ademas que se omite 4 o 5 de los 12 registros.
Lo que me devuelve el sp_cliente_buscar:

paginacion se realiza por cada 5 registros:

PAGINA1:
1 maria    2020-12-05  17:31:19
2 julio    2020-12-05  17:31:19
3 antonio  2020-12-05  17:31:19
4 marlon   2020-12-05  17:31:19
5 mariela  2020-12-05  17:31:19

PAGINA2:
6 carmen   2020-12-05  17:31:19
7 ramiro   2020-12-05  17:31:19
5 mariela  2020-12-05  17:31:19
4 marlon   2020-12-05  17:31:19
3 antonio  2020-12-05  17:31:19
2 julio    2020-12-05  17:31:19

PAGINA 03:
2 julio    2020-12-05  17:31:19
1 maria    2020-12-05  17:31:19

La bd esta en un servidor de hosting, el gestor es phpMyAdmin.
Alguien sabra por que ocurre esto, esta mal mi codigo o esta fallando el servidor?

No tengo demasiada experiencia en bases de datos pero creo que sería una buena idea incluir con qué argumentos se está llamando al procedimiento.
Además veo que dices que la paginación se hace por cada 5 registros pero la Página 2 tiene 6 registros. Esto te ocurre así o ha sido un error al escribirlo aquí??
#136
A grandes rasgos el programa está bastante bien:
  • Uso de constantes para hacerlo fácilmente escalable.
  • Nombres de variables/funciones significativos.
  • Bien estructurado.
    ...

    Sin embargo, hay algunas cosas corregibles y algunos consejos siempre se pueden dar:

    ALGUNOS ERRORES O COSAS IMPORTANTES:
  • En la función main() mezclas el uso de <orden> y <menu>. Guardas el valor en <orden> pero utilizas el switch con <menu>. Dudo que esto te esté funcionando por lo que supongo que será un error de formateo.
  • El programa finaliza al crear todos los drones. ¿Una vez que los he almacenado todos ya no puedo consultarlos? Es mejor que la condición de (numDrones < MAX_DRONES) se ponga dentro del case para crear un dron. Que no permita crear más pero que sí permita seguir consultando los creados.
  • Además la condición de (menu != 0) nunca llega a usarse. El <return 0> de la línea 77 hace que acabe el programa sin que llegue a comprobarse la condición. Es mejor que elimines el <case 0:>. Cuando sea 0 no hagas nada especial y ya se encarga el do-while() de hacer que el bucle acabe.
  • En la línea 94 vas a tener problemas si se introduce una cadena demasiado larga. La forma correcta y recomendada de leer cadenas de caracteres en C es mediante fgets(). Además después de cada scanf() (o al menos justo antes de usar fgets()) tendrás que limpiar el buffer para que funcione correctamente.

    #define SIZE 100
    char cadena[SIZE];
    // Guarda como mucho SIZE-1 caracteres de la entrada estandar (stdin) en el array (cadena)
    // La ultima posicion se reserva para el caracter de fin de cadena: \0
    fgets(cadena, SIZE, stdin);
    // El Enter que introduzcas al final tambien se guardara (si hay espacio) entonces:
    if(cadena[strlen(cadena)-1] == '\n') cadena[strlen(cadena)-1] = '\0'; // Si se ha guardado lo eliminamos
    else while(getchar() != '\n'); // sino, es que quedan caracteres en el buffer. Asi se limpia el buffer de entrada


  • En la función mostrarDatosDron(), qué pasa si el número de serie no existe?? Muestras el último. Si yo busco el dron 123 quiero ver el dron 123 o un aviso de que ese dron no existe, no que el programa me enseñe los datos del 321. Supongo que se entiende, no? Además es mejor asignar siempre un valor a todas las variables de forma explícita y en tu caso contador no tiene un valor inicial explícito.


    ALGUNOS CONSEJOS:
  • Puedes utilizar typedef para no tener que repetir la palabra struct.

    // Para hacer referencia a Persona hay que escribir siempre: struct Persona
    struct Persona {
      char *nombre;
      int edad;
    };
    struct Persona miPersona;

    // En este otro caso basta con utilizar solo el nombre de la struct: Persona
    typedef struct {
      char *nombre;
      int edad;
    } Persona;
    Persona miPersona;


  • Yo no usaría la palabra tipo en cada struct. Da a entender que hace referencia al tipo de fecha, de coordenada o de Dron. Piensa que en C no están definidos los tipos primitivos como: tipoInt, tipoFloat,... Es mejor usar solo: Fecha, Coordenada, Dron,...

  • El modelo del Dron puedes definirlo como un puntero y utilizar memoria dinámica. Así cada array ocupará lo estrictamente necesario y no más. Esto complica un poco el programa pues tratar con memoria dinámica no siempre es muy sencillo.

  • En los parámetros de las funciones no es necesario especificar el tamaño de la primera dimensión del array. Puedes ahorrar texto y además imagina que en un momento dado le pasas un array con una longitud diferente. Y cuando no se utilizan parámetros no es necesario especificar "void" (se puede y se suele dejar vacío). De igual manera las funciones con retorno void tampoco suelen especificar el return (se añade implícitamente siempre al final de una función).

  • En las definiciones de las funciones no es necesario especificar tampoco el nombre. El nombre solo hay que especificarlo en la implementación y así si lo cambias no tendrás que cambiarlo en 2 sitios, sino solo en 1. Resultado:

    //Declaraciones de funciones
    void  mostrarDronesARevisar(Dron[], int numDrones);
    void mostrarDatosDron (Dron[], int numDrones);
    struct tipoDron leerDatosDron();
    void mostrarFlota(Dron[],int numDrones);
    void mostrarDronesEnReparto(Dron[], int numDrones);


  • También puedes utilizar la palabra const en parámetros para especificar que estos no pueden ser modificados durante la ejecución de la función. Aunque es típico pensar "qué más dará usar const si yo no voy a cambiar el valor?" En códigos grandes es posible que sin querer o queriendo lo cambies llegado un punto y no lo tengas en cuenta. Así evitas este posible problema.

  • La línea 138 es demasiado enrebuscada. No digo que esté mal pero se puede simplificar. Recuerdo en el colegio cuando me decían "antes de operar hay que convertir todo a la misma unidad". Pues eso es lo que hay que hacer, convertir la fecha a meses ¿quedará algo más sencillo no?:
    (year * 12 + mes) > (dron.year * 12 + dron.mes)

  • Una mejor manera para buscar un dron (o cualquier elemento en un array) es con un flag de salida por ejemplo. Aprovecha al máximo cada variable:

    int dronBuscado = -1; // Suponemos que no existe
    for(int i = 0; i < numDrones && dronBuscado == -1; ++i){
      if(dron[i].numSerie == numSerie) dronBuscado = i;
    }
    // Ya tienes la posicion del dron buscado o -1 si no existe
    if(dronBuscado != -1){
      // ...
    } else printf("El dron %d no existe\n", numSerie);


  • Además la eficiencia del algoritmo para buscar un dron es lineal O(n). Puedes modificar el programa para guardar siempre los drones en orden según el numSerie y así tener una eficiencia de búsqueda mejor O(log n).

  • En la función mostrarFlota() quitaría la parte final de mostrar un dron. Imagina que automatizas un programa para que muestre 200 arrays diferentes de drones y tienes que tener a una persona ahí pulsando una tecla cada vez que terminas de mostrar un array. La función tiene que hacer lo que tiene que hacer: mostrar los drones. Luego cuando llames a esta función desde fuera tú sabrás si quieres añadir lo otro o no pero que esto no se añada siempre.

    Creo que esto es todo. Al menos todas las cosas que yo cambiaría o que se podrían cambiar para mejorarlo.
#137
Personalmente lo desconozco pero una rápida búsqueda por Google y...
#138
Programación C/C++ / Re: ayudaa con pr0grama en c
5 Diciembre 2020, 00:27 AM
El error era un poco rebuscado. Y aunque lo que voy a decir no tiene importancia en este caso, cuando se tienen problemas y sobre todo cuando no se sabe de dónde provienen, es preferible copiar y pegar el código tal cual. Muchas veces hay errores tontos que al volver a escribir el programa en el mensaje no se cometen.

En este caso el error está en la función rellenar_lista(). Recibes un puntero a la lista (*l) por lo que llamas a esta función con &l como argumento. Ahora llamas a insertar() que recibe un puntero a la lista pero le pasas como argumento: &l (teniendo en cuenta que l ya es &l), es decir no le estás pasando el puntero a la lista sino la propia dirección de memoria en la que está el puntero, equivaldría a (&&l).
Es por esto que falla. Aunque me parece raro que lo hayas compilado y ejecutado sin problemas ya que a mí me ha saltado un warning al compilar y el programa se ha cerrado en la primera inserción.

Algunos otros consejos:
  • Puedes asignar el valor de evaluar una condición directamente a un int. Así ahorras líneas de if-else:

    int insertado = (l->tam < N);
    int acabar = (f.dia == 0 && f.mes == 0 && f.año == 0);

    Esto asignará un 1 si la condición es cierta y un 0 si es falsa.
  • En la función insertar_lista() creas una variable Fecha que luego pasas a insertar donde la deshaces para insertarla valor por valor. Puedes asignar la variable completa:

    int insertar(struct Lista *l, struct Fecha f){
      int insertado = (l->tam < N);
      if(insertado){
        l->vectorFechas[l->tam] = f;
        l->tam++;
      }
      return insertado;
    }
#139
Programación C/C++ / Re: ayudaa con pr0grama en c
4 Diciembre 2020, 12:54 PM
Especifica qué problemas tienes para poder ayudarte.
#140
Problemas que le veo a ese programa:
  • Los nombres de las variables no ayudan a entender el código.
  • Siempre hay que suponer que un usuario se puede equivocar por lo que cuantas menos veces dependamos de él mejor. Con esto quiero decir que las líneas 21-29 es mejor evitarlas. Es un cálculo que puedes hacer internamente sin necesidad del usuario.
  • La condición de la línea 38 se puede simplificar: (n >= 5) && (n >= 10) es lo mismo que: (n >= 10). Siempre que la segunda condición sea cierta, la primera también lo será y es imposible que la segunda sea cierta sin serlo la primera también. De todas formas este bloque de if-else no tiene mucho sentido tal y como está planteado.
  • En la línea 40 utilizas 4 en vez de n4.

    No sé mucho de resistencias (recuerdo un poco de cuando estudiaba física o tecnología) y mirando por Internet veo que hay diferentes tablas de medida sobre todo para el porcentaje final.
    Por lo tanto es importante que especifiques las necesidades que tiene que suplir tu código.

    De momento te puedo ayudar en lo siguiente, si quieres hacer el programa válido para un número diferente de bandas, haz lo siguiente:
    Código (cpp) [Seleccionar]

    // Definimos una constante para el maximo de bandas:
    const int MAX_BANDAS = 6;

    int main(){
      // Creamos un array para guardar el valor de cada banda:
      int bandas[MAX_BANDAS]; // Pueden sobrar espacios pero la solucion mas correcta requiere de memoria dinamica y es mas avanzado
      int numeroBandas;
      // Con este do-while evitas que el usuario pueda introducir numeros fuera del rango indicado en el while() -> [4, 6]
      do {
        cout << "Introduce el numero de bandas de la resistencia: ";
        cin >> numeroBandas;
      } while(numeroBandas < 4 || numeroBandas > 6);
      // la ultima banda es diferente pero las demas son iguales por lo que repetimos lo de preguntar color numeroBandas-1 veces:
      // AQUI muestras los colores como lo haces ahora...
      for(int i = 0; i < numeroBandas - 1; ++i){
        // Con este do-while evitas que introduzcan valores no validos
        // PD: He estado revisando algunas tablas y el negro corresponde al 0, no al 1
        do {
          cout << "Introduce el valor numerico de la banda " << (i+1) << ": ";
          cin >> bandas[i];
        } while(bandas[i] < 0 || bandas[i] > 9);
      }
      // Una vez que llegas aqui ya tienes todos los colores menos el ultimo
      // Este tendras que hacerlo por separado segun los colores que consideres validos
      // El ultimo lo guardas en bandas[numeroBandas-1] que es la ultima posicion valida del array

      // Ahora toca calcular el valor:
      int resistencia = 0;
      for(int i = 0; i < numeroBandas - 1; ++i){
        resistencia = bandas[i] * pow(10, i); // Para usar pow() tienes que incluir la biblioteca cmath al principio: #include <cmath>
        // La funcion pow() en este caso es innecesaria pero es para que veas la operacion
        // Tambien puedes usar un multiplicador que empiece en 1 y en cada vuelta se multiplique por 10 <- Mas eficiente, intentalo
      }

      // Ahora toca calcular el minimo y maximo del rango segun el porcentaje de la ultima banda:
      // Esto lo puedes hacer con un switch-case o guardando todos los valores posibles en otro array: porcentajes
      // Suponiendo la segunda opcion, utilizas el valor del array guardado en la posicion elegida por el usuario al mostrarle las opciones
      float variacion = resistencia * porcentajes[bandas[numeroBandas-1]];
      float resistenciaMinima = resistencia - variacion;
      float resistenciaMaxima = resistencia + variacion;
    }


    Aunque el código parece bastante grande, hay muchos comentarios y fragmentos que tienes que completar tú.
    Si tienes algún problema, coméntalo teniendo en cuenta los comentarios que he ido haciendo a lo largo del código.