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

#41
No se hacen tareas.
Así es como se aprende que estas cosas hay que empezar a hacerlas con tiempo y no dejarlas para el final.

#42
Un programa cuando se ejecuta puede recibir una serie de argumentos.
Esto se suele obviar porque normalmente ejecutamos los programas mediante un doble clic en el .exe.

Imagina que tienes tu programa en C/C++ y lo compilas. Ahora tienes como resultado tu ejecutable: programa.exe.
Para ejecutarlo puedes buscarlo y hacer doble clic o puedes acceder a la ruta mediante la Consola (cmd/Powershell de Windows) o Terminal (de Linux) mediante:
cd ruta_a_tu_ejecutable
Y ahora ejecutar el programa con o sin argumentos:

./programa.exe
./programa.exe cada palabra extra es un argumento

En el segundo caso "cada palabra extra es un argumento" son los argumentos que recibe el programa.
Para manejar estos argumentos en el propio programa están argc y argv:
- argc contiene el número de argumentos recibidos. Siempre es >= 1.
- argv es un array de char[] donde cada uno es una de las palabras

argc = 7
argv[0] = "./programa.exe"
argv[1] = "cada"
argv[2] = "palabra"
...
argv[6] = "argumento"

#43
Como ya te ha comentado @fzp, esa no es la manera correcta de hacer un filtro. La forma estándar es:
Código (cpp) [Seleccionar]

const int MIN_NUM_TERMINOS = 0; // Constante para el numero minimo de terminos permitido
const int MAX_NUM_TERMINOS = 15; // Constante para el numero maximo de terminos permitido

int main() {
  int terminos;
  do {
    cout << "Introduce el numero de terminos [" << MIN_NUM_TERMINOS << " - " << MAX_NUM_TERMINOS << "]: ";
    cin >> terminos;
  } while(terminos < MIN_NUM_TERMINOS || terminos > MAX_NUM_TERMINOS);

  // Cuando llegues a esta linea ya tendras un valor dentro del rango permitido
}



Breve paréntesis: No es buena práctica crear un if() vacío para incluir código en la parte del else.
Código (cpp) [Seleccionar]

// Esto:
if(numero > 0 && numero < 15);
else {
  ...
}
// Se puede sustituir por esto:
if(numero <= 0 || numero >= 15) {
  ...
}

Fin del paréntesis.


Además tienes otro problema importante y es que tienes variables sin inicializar. Estas variables dependiendo del ámbito en el que estén (local/global) tendrán un valor nulo (0 en caso de números) o basura (cualquier número). Siempre tienes que controlar que no pase esto en tus programas.

Teniendo en cuenta la sumatoria que quieres calcular:

[latex]$\displaystyle \sum_{k=1}^n (-1)^k \times \frac{1}{(2k)!} \times {x^{4k}}$[/latex]

deberías entender lo que estás haciendo y no copiar la fórmula lo más parecida posible...

El primer elemento de la serie sería: [latex]$\displaystyle e_1 = (-1)^1 \times \frac{1}{(2\times1)!} \times {x^{(4\times1)}} = -1 \times \frac{1}{2!} \times {x^4}$[/latex]

El segundo elemento de la serie sería: [latex]$\displaystyle e_2 = (-1)^2 \times \frac{1}{(2\times2)!} \times {x^{(4\times2)}} = 1 \times \frac{1}{4!} \times {x^8}$[/latex]

Viendo los primeros elementos de la serie puedes ver la relación que sigue. Por ejemplo:
  • La primera parte únicamente cambia el signo del elemento. Cuando k es par, el signo es positivo y cuando k es impar el signo es negativo.
  • La segunda parte tiene un factorial que puede resultar costoso de calcular. Sin embargo, si en la primera iteración tienes calculado 2!, basta multiplicar por 3 y por 4 para tener 4! y así sucesivamente sin tener que repetir cálculos.
  • La tercera parte tiene x^4 en el primer elemento y x^8 en el segundo. En el tercero sería x^12, o lo que es lo mismo en cada iteración se multiplica por x^4. x^4 * x^4 = x^(4+4) = x^8 (propiedades de las potencias)

    Sabiendo todo esto:
    Código (cpp) [Seleccionar]

    int main() {
      // Inicializamos el resultado a 0 para poder acumular correctamente
      double resultado = 0;

      // Las variables n y x no hace falta inicializarlas porque se van a pedir por teclado
      int n;
      double x;

      // Inicializamos las variables para k = 1
      int signo = -1; // (-1)^1 = -1
      double factorial = 2; // (2 * 1)! = 2! = 2
      double elemento3 = pow(x, 4); // x^(4 * 1) = x^4. AVISO: Primero hay que pedir x

      for(int i = 1; i <= n; ++i) {
        // Sumamos el elemento i
        resultado += signo * 1/factorial * elemento3;
        // Actualizamos cada uno de los elementos
        signo *= -1; // Asi cambiamos de signo en cada iteracion
        factorial = ...;
        elemento3 = ...;
      }
    }
#44
Programación C/C++ / Re: While y do while
12 Mayo 2021, 21:16 PM
La diferencia principal es:

  • Un bloque while() primero comprueba la condición y si esta es cierta entonces ejecuta lo que hay dentro de forma cíclica mientras la condición siga siendo cierta.
Código (cpp) [Seleccionar]

while(condicion) {
  // lo que sea
}

  • Un bloque do-while() primero ejecuta lo que hay dentro, después comprueba la condición y si es cierta repite lo que hay dentro de forma cíclica mientras la condición siga siendo cierta.
Código (cpp) [Seleccionar]

do {
  // lo que sea
} while(condicion);


* Un bloque do-while() siempre va a ejecutar lo que tenga dentro al menos una vez (aunque la condición sea falsa desde el principio).
#45
Cita de: MrEliott en 12 Mayo 2021, 06:28 AM
Hola a todoss, he intentado borrar mi historial de comandos del terminal en kali linux y no he podido, he buscado y encontrado que el comando es " history -c " pero por alguna razon no me funciona... agradezco la ayuda  :-X
Linux tiene digamos como dos historiales: uno en memoria y otro en un fichero (el fichero que ha mencionado el-brujo). Mediante el comando:
history -c
eliminas el historial en memoria pero no modificas el fichero. Entonces cuando cierras esa consola y abres otra, se carga de nuevo el historial del fichero.
Otra alternativa es:
history -c && history -w
así consigues eliminar el historial en memoria y guardarlo en el fichero por lo que quedará vacío el fichero del historial.


Cita de: MrEliott en 12 Mayo 2021, 19:07 PM
>> Gracias funciono perfecto  ;D , una ultima pregunta, hay alguna forma para que nunca se guarden los comandos en el historial?? Gracias de antemano
Hasta donde yo sé (desconozco si esto es igual en todas las distros), si añades un espacio antes de un comando, éste no se guarda en el historial.
#46
El código publicado en un mensaje debe estar entre etiquetas de Código GeSHi. Puedes seleccionarlas desde el desplegable que dice Código GeSHi (eligiendo el lenguaje adecuado) o escribiendo directamente:
[code=c]
Tu código aquí
[/code]


Tienes 3 problemas:
  • Al no estar utilizando typedef como indiqué en el primer mensaje, debes utilizar la palabra struct obligatoriamente cada vez que quieras hacer referencia a un struct (struct receta, struct ingredientes,...). Además no utilices el mismo nombre para la struct que para la variable, no es nada recomendable.
  • Al momento de utilizar la función (línea 53) no tienes que indicar el tipo sino una variable que se corresponda con ese tipo.
    res = procesarReceta(r[0], tiposIngredientes, numTiposIngredientes);
  • Te has limitado a copiar casi literalmente mi pseudocódigo (y el pseudocódigo es una forma más o menos flexible de diseñar un algoritmo utilizando sintaxis que no tiene que ser de ningún lenguaje concreto). En C las asignaciones no se hacen con := por lo que esa sintaxis no existe. Además hay un par de líneas que te has medio inventado (79-81) y te he indicado en el comentario anterior que tendrías que hacer ciertos cambios que tampoco veo.
    Todos esos errores son muy básicos y cualquier compilador que utilices para compilar tu programa seguro que te indicará la línea del error y el motivo.

    Si te limitas a copiar la solución sin entenderla, no vas a conseguir nada. El segundo problema demuestra que intentas utilizar una función sin entender su funcionamiento y en general todo demuestra que no quieres entenderlo, sólo conseguir que funcione. Y eso va a ser tu mayor problema.

    Igual de fácil que me es a mí saber todo eso sólo viendo tu código, le será a tu profesor/a o a quien tengas que entregar ese programa. Y una simple búsqueda por Internet le servirá para ver de dónde has sacado la solución... :rolleyes: :rolleyes: Intentando engañar a los demás, sólo te engañas a ti mismo.
#47
Cita de: JoaquinVT312 en  9 Mayo 2021, 14:04 PM
Primero decir que es verdad que me expliqué mal acerca del ejercicio. El programa devolvería 1 de ser totalmente vegetariana la receta y 0 de encontrar algún alimento animal, pero siempre prevalecería el encontrar un ingrediente desconocido, es decir, de encontrar uno devolvería -1, independientemente ya de que sea vegetal o animal la receta.
En el algoritmo anterior he intercambiado el significado del 1 y el 0 pero puedes corregir eso sin mayor problema.
También deberás cambiar un poco el código para que busque todos los ingredientes por si alguno es desconocido.

Cita de: JoaquinVT312 en  9 Mayo 2021, 14:04 PM
Tengo dudas sobre la llamada a la función:
// LLamada a función procesaReceta. Pruebe diferentes recetas anteriores: r[0], r[1] o r[2]
res = procesarReceta(Receta receta, Ingredientes ingredientes[],  numIngredientes);
Eso me da error y no me deja compilar, por lo que me quedo ahí atascado y no puedo compilar e ir probando s editar el código de la función para ver si va funcionando correctamente o no.
Gracias de nuevo por la atención.
Te dará error de compilación porque el prototipo de la función tiene que ser igual que la implementación y no lo habrás cambiado en ambas partes del código.
Si el problema no es ese, añade el prototipo de la función, la implementación y la llamada para ver cómo la utilizas.
#48
El código está bastante bien estructurado (que no es poco decir).
Sin embargo, la función procesarReceta() sí que tiene algunos errores: utilizas dos tipos al mismo tiempo (int y struct...).


Antes de empezar con el problema concreto voy a mencionar un par de consejos para utilizarlos yo mismo a partir de aquí:
Cuando se define una estructura, puedes utilizar la palabra typedef para crear un nuevo tipo y no tener que utilizar siempre la palabra struct.
Los nombres de los structs es mejor que empiecen por mayúscula.

typedef struct {
  char nombre[TAMCAD];
  int numIngredientes;
  int id[MAXING];
  int cantidad[MAXING];
} Receta;
// Ahora puedes utilizar el tipo Receta asi:
Receta miReceta;
// en vez de asi:
struct Receta miReceta;



En primer lugar, tal y como dices en la explicación, la función debe devolver {1, 0, -1} por lo que el tipo de valor de retorno deberá ser int, mejor que float.
Ahora vamos a ver los parámetros... Si tú quieres ver si una receta tiene ingredientes de origen animal necesitarás, para empezar, la receta. ¿Cuántas? 1, la que quieres procesar. No todas las recetas. Por lo que de momento:
int procesarReceta(Receta receta, ...);
Ahora esa receta tiene una lista de ingredientes (concretamente un array con los ids de los ingredientes). Entonces necesitarás recibir una lista con todos los ingredientes para poder buscar según su id. Por lo tanto:
int procesarReceta(Receta receta, Ingrediente ingredientes[], int numeroIngredientes, ...);
* En C/C++, cuando se pasa un array como parámetro suele ser necesario en la mayoría de los casos pasar un parámetro adicional para saber la longitud de ese array.
** En vez de llamar a la struct "Ingredientes" (en plural), la llamaría "Ingrediente" (en singular). Porque cada instancia será un ingrediente y no varios. A diferencia de "Propiedades" que cada instancia engloba varias propiedades.

Y con esos parámetros ya podemos implementar la función, por lo que quedaría así:

int procesarReceta(Receta receta, Ingrediente ingredientes[], int numeroIngredientes) {
  // tu codigo aqui
}



Ahora el algoritmo de tu función:
Teniendo la receta que quieres comprobar, tienes que recorrer todos sus ingredientes mientras que no hayas encontrado uno que sea animal y mientras no se acaben los ingredientes. Por cada uno de esos ingredientes, debes recorrer el array de ingredientes para encontrar el que coincide según su id y mirar si es de tipo animal.
Hay un pequeño detalle que no está bien definido en la explicación: si una receta tiene un ingrediente de origen animal y otro desconocido, qué se debe devolver? 1 o -1? Eso quedará a decisión tuya.
En pseudocódigo sería algo así:

i := 0 // Indica el indice del ingrediente actual de la receta
resultado := 0 // Indica: 0 (no animal) | 1 (animal) | -1 (desconocido)
MIENTRAS i < receta.numIngredientes && resultado == 0 HACER
  j := 0 // Indica el indice del ingrediente actual entre todos los ingredientes
  MIENTRAS j < numIngredientes && ingredientes[j].id != receta.ingredientes[i] HACER
    j := j +1
  FIN MIENTRAS
  // Aqui llegamos si hemos encontrado el ingrediente correspondiente segun el id o si no existe
  SI j < numIngredientes ENTONCES // lo hemos encontrado en la posicion j
    resultado := (ingredientes[j].tipo == 'A') // Esto sera 1 si la comparacion es true o 0 si es false
  SINO // no lo hemos encontrado
    resultado := -1
  FIN SI
  i := i + 1
FIN MIENTRAS
RETURN resultado

* Este algoritmo devuelve 1 o -1 en función de lo primero que encuentre. Y 0 si no encuentra ninguno de los otros dos casos.
Conviértelo a C (es muy sencillo) y pruébalo. A partir de ahí puedes hacer los cambios que consideres.
#49
Programación C/C++ / Re: switch
5 Mayo 2021, 19:33 PM
La sentencia switch(), como bien dices, es una manera de simplificar un tipo concreto de if(). Un switch() sirve para evaluar una expresión de tipo int o char y dependiendo del valor hacer una cosa u otra.
Código utilizando if():

int mes;
printf("Introduce un numero del 1 al 12: ");
scanf("%d", &mes);
if(mes == 1) printf("Enero\n");
else if(mes == 2) printf("Febrero\n");
else if(mes == 3) printf("Marzo\n");
...
else printf("No has introducido un numero entre 1 y 12\n");


Mismo código utilizando switch():

int mes;
printf("Introduce un numero del 1 al 12: ");
scanf("%d", &mes);
switch(mes) { // Segun el valor de <mes>...
  case 1:  // ...si es 1...
    printf("Enero\n"); // ...haces esto...
    break; // ...y sales del switch

  case 2: // ...si es 2...
    printf("Febrero\n"); // ...haces esto...
    break; // ...y sales del switch

  ...

default: // ...si no era ninguno de los anteriores...
    printf("No has introducido un numero entre 1 y 12\n");
    break; // (este break es opcional porque no hay mas casos)
}


El switch permite hacer comparaciones de igualdad teniendo que escribir menos en la condición. El break es necesario para salir del switch y no ejecutar todos. Si no se pusiera el break, el programa entraría en el primer case que cumpla la condición y ejecutaría el código de todos hasta encontrar un break o hasta terminar. Esto también se puede aprovechar para algo como esto:

char letra = ...;
switch(letra) {
  case 'a': case 'e': case 'i': case 'o': case 'u':
    printf("La letra %c es una vocal minuscula\n", letra);
    break;

  case 'A': case 'E': case 'I': case 'O': case 'U':
    printf("La letra %c es una vocal mayuscula\n", letra);
    break;

  default:
    printf("La letra %c es una consonante\n", letra);
}


* La claúsula <default> es opcional y siempre debe ir al final porque sino cualquier case que vaya después que <default> no se va a ejecutar nunca (a no ser que no haya breaks).
#50
Aunque está el tema solucionado, ya que se ha mencionado... Agrego unos últimos consejos para el código mostrado:
  • Agregar todas las librerías al principio del fichero. Esto facilita verlas todas de un único vistazo y tenerlas disponibles para todo el código.
  • Eliminar la librería <conio.h>. Esta librería no es estándar por lo que algunos compiladores darán error en esa línea. Su uso más visto sobre todo en personas que están empezando es para poder utilizar la función getch(). Esta función se puede sustituir por getchar() que cumple el mismo propósito y pertenece a <stdio.h>.
  • <bing> y <bong> no son los nombres más descriptivos para esas variables. Cuanto más ayude el nombre de una variable a identificar su función, mejor. Aunque hay que reconocer que tiene su gracia decir sus nombres... :xD
  • La semilla de los números aleatorios srand(...) se suele llamar una única vez en el main() aunque luego se utilice la función rand() en otras partes.
  • Las funciones que utilizas no son muy escalables digamos. Lo bueno de una función es declararla una vez y poder utilizarla múltiples veces. Ahora vamos a analizar la función que genera un número aleatorio:

    int RandomMin1Max10() {
        srand(time(NULL));
        int valor;
        valor = (rand()%(10+1-1)+1); // Al ser numero fijos no tiene mucho sentido dejar esas operaciones
        return valor;
    }

    Una función que genera un número aleatorio entre 1 y 10. Está bien, funciona bien pero... ¿no sería mejor poder decidir tú el límite cada vez que la llamas? Así la función será más reutilizable.

    int generarNumeroAleatorio(int minimo, int maximo) {
      return minimo + rand() % (maximo - minimo + 1);
    }


    Esto mismo con la función CargaNum(). ¿Y si puedes pasar el mensaje que quieras en cada ocasión?
    Además puedes dejar el buffer de entrada limpio siempre (lo que te ahorrará muchos quebraderos de cabeza cuando empieces a usar fgets() para pedir cadenas de texto al usuario, espero que os enseñen esta función en vez de gets()  :silbar: :silbar:)

    int pedirEntero(char *mensaje) {
      int numero;
      printf(mensaje);
      scanf("%d", &numero);
      while(getchar() != '\n'); // limpiar el buffer de entrada
      return numero;
    }


    Y con esto ya podemos dar el tema por cerrado para no desviarnos más del tema principal. :-X