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

 

 


Tema destacado: Curso de javascript por TickTack


  Mostrar Mensajes
Páginas: 1 2 3 4 5 6 7 8 [9] 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ... 102
81  Programación / Programación C/C++ / Re: CODEBLOCKS : Mensaje de error en: 3 Diciembre 2021, 18:49 pm
Tal y como dices, los ficheros .o son normales. Estos son ficheros intermedios que genera el compilador antes de crear el ejecutable final y se suelen crear en el directorio obj/ de tu proyecto. No se les suele prestar mucha atención cuando se trabaja con IDEs, por eso igual te parecen extraños. Tendrás alguna opción de limpiar proyecto o similar que te los borrará.

Cuándo y dónde te aparece el error que comentas??
Este problema lo tienes desde que empezaste a usar Codeblocks??
Has instalado algo (relacionado con Codeblocks) o cambiado alguna configuración poco antes de que te empezase a aparecer este error??
82  Programación / Programación C/C++ / Re: Buenas, necesito ayuda URGENTE!! en un ejercicio, y es que siempre me da Violacion de segmento en: 3 Diciembre 2021, 18:40 pm
Fíjate en los comentarios de MOD que tienes en el mensaje anterior.  :rolleyes:


Piensa cada uno de los filtros por separado y luego tan solo tienes que juntarlos.
Obviamente tendrás que pasar los parámetros a la función para poder usarlos.

Para filtrar por tipo, lo único que tienes que hacer es comprobar que el tipo. Si el tipo es el que buscas, muestras la ruta y en caso contrario lo ignoras.
Para filtrar por profundidad con recursividad tienes que definir una condición de salida para dejar de aplicar la recursividad. En pseudocódigo sería algo así:
Código:
mostrarFiltrado := function(path, type, max_depth, current_depth)
INICIO
  dir := abrirDirectorio(path)
  current_path := obtenerSiguienteElemento(dir)
  MIENTRAS EXISTE current_path HACER
    SI current_path.type == type ENTONCES // Parte del codigo para el filtro por tipo
      MOSTRAR current_path
    FIN SI // Parte del codigo para el filtro por tipo
    SI current_path.type == directorio AND current_depth < max_depth ENTONCES // Parte del codigo para el filtro por profundidad
      mostrarFiltrado(current_path, type, max_depth, current_depth + 1)
    FIN SI // Parte del codigo para el filtro por profundidad
    current_path := obtenerSiguienteElemento(dir)
  FIN MIENTRAS
FIN

PD: Si sabes aprovechar el current_depth para establecer una tabulación al mostrar las rutas, la salida te quedará mucho más profesional.
83  Programación / Programación C/C++ / Re: Código que se repite dos veces y no sé porqué en: 3 Diciembre 2021, 18:01 pm
El programa no tiene nada que ver en esto, es un programa de lo más normal y no influye para nada en otros.
El problema debe de estar en el propio IDE. Alguna configuración que hayas modificado o algo por el estilo.

PD: Ya que está:
  • Las variables es recomendable declararlas locales, dentro de la función main().
  • Este es el escenario típico para usar un for() en vez de un while(). Además es mejor usar las funciones length() o size() antes que sizeof().
Código
  1. for(int i = 0; i < cadena.length(); ++i) {
  2. //...
  3. }
  • No es recomendable usar system("pause"). Utiliza cin.get() en su lugar.
  • Puedes acortar las asignaciones.
Código
  1. // Las dos lineas obtienen el mismo resultado. Esto se puede hacer con otros operadores y otros tipos de variables
  2. numeros = numeros + loquesea;
  3. numeros += loquesea;
84  Programación / Programación C/C++ / Re: Buenas, necesito ayuda URGENTE!! en un ejercicio, y es que siempre me da Violacion de segmento en: 3 Diciembre 2021, 17:20 pm
Además de lo comentado por @BloodSharp, veo más errores en el código:
  • Todos los (i == args) del for() no se van a cumplir nunca. El bucle no se va a repetir nunca con i = args, el último valor de i dentro del bucle será args-1 porque cuando i sea igual a args, la condición del for() no será true y no llegará a entrar en su interior.
  • El <case 2> del <switch> tiene otro error. Si pones "f" o "d" te dará un error porque una de las dos comprobaciones no se va a cumplir, mientras que si pones cualquier otro carácter te dará 2 errores seguidos. Tienes que cambiar eso.
  • Estás haciendo las asignaciones de cadenas con el operador =. En este caso no estás aprovechando la reserva de memoria que haces pues no estás copiando el contenido de una cadena en otra. Tan solo estás haciendo que el puntero que tú has creado apunte al comienzo de la cadena original. Para copiar el contenido debes usar la función strncpy() y es entonces cuando tienes que reservar memoria.

Comprueba que la función readdir() devuelve un puntero.
Si después de todo, no se resuelve tu problema, agrega un ejemplo de ejecución para tener más información y no ir a ciegas.

PD: Sobre la duda de la línea 69, está bien. Si fuese argv estarías preguntando por el valor del primer argumento (que es una cadena), no por el índice del argumento.
85  Programación / Programación C/C++ / Re: Codigo en CODEBLOCKS ( tampoco en DEV C ++ ) no se actualiza si cambio un valor en: 2 Diciembre 2021, 00:10 am
sólo en el caso de que defina otra variable global, valiéndome de un mismo puntero // no haciendo falta definir otro // direccionador para ambas variables, obtendré, ahora sí, dos Direcciones de Memoria Física diferentes ( lo constato más aún si a a ambas variables les asigno el mismo Valor )
Sólo aclarar que la variable da igual que sea global que local.

Para entendernos, cuando tú le dices al programa "crea una variable", el programa reserva un espacio para esa variable. Cada variable podríamos decir que tiene 2 partes:
  • Por un lado un identificador de esa variable. Un valor que representa unívocamente la variable -> Su dirección de memoria. No puede variar durante la ejecución.
  • Por otro lado el contenido almacenado en ese espacio. El valor que se guarda en esa variable. Puede variar durante la ejecución.

Un ejemplo que puede ser un poco más complejo pero que si le das una vuelta y lo entiendes creo que habrás avanzado mucho. PD: Me inventaré las direcciones de memoria por simplificarlas y porque es imposible adivinar qué dirección de memoria se va a asignar a cada variable en cada ejecución. Eso no depende de nosotros.

Antes del ejemplo, varios puntos que hay que tener claros:
  • Puntero: Variable que su contenido es siempre una dirección de memoria. Al ser así los punteros tienen 2 direcciones de memoria: una de ellas es su identificador y la otra es su contenido.
  • Operador * (asterisco): Desreferencia un puntero. Hace que el puntero no devuelva la dirección de memoria que tiene almacenada en su contenido sino que devuelve el contenido de esa dirección de memoria. Excepción: En la línea en que se define el puntero, el operador * no desreferencia, sólo indica que se está declarando un puntero.
    Código:
    Suponemos que la posición de memoria 0x1234 contiene el valor 8
    Puntero p = 0x1234 -> Un puntero siempre contiene direcciones de memoria
    Mostrar p -> Muestra (el contenido de p): 0x1234
    Mostrar *p -> Muestra (el contenido de la dirección de memoria 0x1234): 8
  • Operador & (ampersand): Se puede aplicar a cualquier variable. Obtiene la dirección de memoria de esa variable (su identificador único e invariable) en vez de su contenido.

    Código
    1. int main() {
    2.  int a = 5; // El programa reserva la posicion 0x1 de la memoria (para a) y guarda en su interior el valor 1. Lo representare a partir de ahora como -> 0x1(5)
    3.  
    4.  int *p = &a; // El programa reserva la posicion 0x2 de la memoria (para p) y guarda en su interior la direccion de memoria de a (0x1) -> 0x2(0x1)
    5.  
    6.  cout << "El valor de a es: " << a << " y su direccion de memoria es: " << &a << endl; // Muestra: "El valor de a es: 5 y su direccion de memoria es: 0x1"
    7.  cout << "El valor de p es: " << p << " y su direccion de memoria es: " << &p << endl; // Muestra: "El valor de p es: 0x1 y su direccion de memoria es: 0x2"
    8.  cout << "Desreferenciamos p: " << *p << endl; // Muestra: "Desreferenciamos p: 5"
    9.  
    10.  // Ahora vamos a probar a cambiar valores a ver que pasa
    11.  int b = 8; // El programa reserva la posicion 0x3 de la memoria (para b) y guarda en su interior el valor 8 -> 0x3(8)
    12.  *p = b; // Que pasa aqui? No se cambia la direccion de memoria que contiene p (0x1). Se cambia el valor que hay dentro de 0x1 (5). 0x1 es la direccion de memoria que identifica a la variable a -> 0x1(8)
    13.  cout << "El valor de a es: " << a << " y su direccion de memoria es: " << &a << endl; // Muestra: "El valor de a es: 8 y su direccion de memoria es: 0x1"
    14.  // Hemos cambiado el contenido de a (5 -> 8) pero su direccion de memoria no varia, sigue siendo 0x1
    15.  cout << "El valor de p es: " << p << " y su direccion de memoria es: " << &p << endl; // Muestra: "El valor de p es: 0x1 y su direccion de memoria es: 0x2" -> Como vemos esto no ha cambiado nada
    16.  cout << "Desreferenciamos p: " << *p << endl; // Muestra: "Desreferenciamos p: 8" -> Esto si ha cambiado porque el contenido de 0x1 ahora es 8, no 5
    17.  
    18.  // Hasta aqui todo bien supongo. Asequible, pero... y ahora que?
    19.  int **pp = &p; // El programa reserva la posicion 0x4 de la memoria (para pp) y guarda en su interior la direccion de memoria de p (0x2) -> 0x4(0x2)
    20.  // Al usar ** estamos declarando un puntero a puntero. Un puntero que guarda como valor la direccion de memoria de otro puntero
    21.  // Ahora vamos a comprobar que se sigue cumpliendo lo que decimos:
    22.  cout << "El valor de pp es: " << pp << " y su direccion de memoria es: " << &pp << endl; // Muestra: "El valor de pp es: 0x2 y su direccion de memoria es: 0x4"
    23.  cout << "Desreferenciamos pp: " << *pp << endl; // Muestra: "Desreferenciamos pp: 0x1"
    24.  // Aclaremos la linea anterior: Al desreferenciar un puntero no mostramos la direccion de memoria que contiene sino el contenido de esa direccion de memoria
    25.  // pp contiene 0x2 -> Al desreferenciar obtenemos el valor que se guarda dentro de la direccion 0x2 y si vamos a la linea de p vemos que el valor que guarda la direccion 0x2 es: 0x1  &#8203;
    26.  
    27.  // Ahora entonces como *p devuelve una direccion de memoria (un puntero), podemos ver que contiene esa direccion de memoria (podemos desferenciarlo de nuevo):
    28.  cout << "Desreferenciamos *pp: " << **pp << endl; // Muestra: "Desreferenciamos *pp: 8" -> Si *pp devuelve 0x1, el contenido de la direccion 0x1 es: 8
    29. }

    Se acabó el programa y la tabla de direcciones de memoria y contenido es:
    Código:
    Variable a -> Direccion de memoria: 0x1 -> Contenido: 8
    Variable p -> Direccion de memoria: 0x2 -> Contenido: 0x1
    Variable b -> Direccion de memoria: 0x3 -> Contenido: 8
    Variable pp -> Direccion de memoria: 0x4 -> Contenido: 0x2

    RESUMEN
    -------------------
    - Todas las variables están formadas por una dirección de memoria y un contenido.
    - Las direcciones de memoria de cada variable las asigna el sistema operativo y no se pueden modificar.
    - El contenido de las variables puede ser un valor o una dirección de memoria (en el caso de los punteros). El contenido lo asignamos nosotros y se puede modificar.


    PD: Se me ha podido pasar algún error en el código. De ser así no dudéis en avisarme para corregirlo pues es un tema en el que la exactitud es muy importante.
    PD2: El código hay que estudiarlo sin prisa, hacer las pruebas que consideréis y preguntar cualquier duda que os pueda quedar.
86  Programación / Programación C/C++ / Re: como divido 3 divido dos y me de 1.5? en: 20 Noviembre 2021, 16:57 pm
ya verás con lós numeros  "long long" hazlo siempre en coma flotante convierte lo que no sean y muestra el resultado.



no enfrentes a un entero con un flotante, antes conviértelo (float)

redondear no te hace falta, pasa sólo al pasarlo a entero (int). En esas operaciones han de entrar con los participantes flotantes. (float)x dividido por (float)y es igual a (int)z


Imagino que el tema principal de este hilo está cerrado ya que el usuario que lo empezó no ha vuelto a contestar.
Sin embargo, respecto a este comentario hay cosas no muy claras:
no enfrentes a un entero con un flotante, antes conviértelo (float)
No es necesario, operar un int con un float ya da como resultado un float. Lo importante es guardarlo en una variable de tipo float y no int.

redondear no te hace falta, pasa sólo al pasarlo a entero (int)
Cuando se convierte un float en int no se redondea, se trunca.
87  Programación / Java / Re: Eliminar datos de una clase insertados en un arraylist en: 7 Noviembre 2021, 19:38 pm
Por un lado, no puedes utilizar el signo "=" para comparar. Este signo es el operador de asignación (da un valor), no de comparación. El signo de comparación para comparar datos primitivos o direcciones de memoria es "==".

Por otro lado, en tu caso no quieres comparar ni un dato primitivo (int, float, char, ...) ni una dirección de memoria sino el contenido de un objeto (String). Para ello necesitas utilizar el método equals().
88  Programación / Programación C/C++ / Re: Duda de un programa en: 3 Noviembre 2021, 21:15 pm
Yo diría que tu algoritmo no es correcto.  :silbar: :silbar:
Un número omirp es un número primo no capicúa cuyo palíndromo también es primo. Por ejemplo: 13 - 31 | 17 - 71 | ...

Al ejecutar tu programa el resultado que obtengo es:
Código:
2 1/1
3 2/2
4 3/3
5 5/5
6 7/7
7 10/1
...
Con sólo estos resultados ya podemos ver que:
  • Los números {1, 2, 3, 5 y 7} no son considerados números omirp porque son capicúa (sus palíndromos son ellos mismos).
  • El 10 no es primo (y realmente el 1 tampoco)

Es decir que de todos esos resultados no hay ninguno válido.
89  Programación / Programación C/C++ / Re: como divido 3 divido dos y me de 1.5? en: 3 Noviembre 2021, 06:44 am
Al realizar una operación entre 2 datos, el tipo del resultado es el mismo que el tipo de datos más grande de entre los dos operandos. Por ejemplo:
Operar 2 ints -> Resultado: int.
Operar int y float -> Resultado: float.
Operar int y short -> Resultado: int.
... Y así con cualquier tipo.

Si realizas una operación entre dos enteros, el resultado será un entero. Entonces:
Código
  1. int a = 3;
  2. int b = 2;
  3. printf("Resultado %d/%d = %d", a, b, a/b); // Resultado 3/2 = 1

Para obtener el resultado con decimales debes hacer una conversión de cualquiera de los datos a algún tipo decimal (float/double).
Código
  1. int a = 3;
  2. int b = 2;
  3. printf("Resultado %d/%d = %.1f", a, b, (float)a/b); // Resultado 3/2 = 1.5

PD: Para mostrar un número decimal hay que utilizar "%f". El ".1" indica que muestre el número con un solo dígito decimal.
90  Programación / Programación C/C++ / Re: Ayuda con un ejercicio en C. tema Struct en: 26 Octubre 2021, 01:43 am
Bueno... A ver a ver. Parece que hay mucho trabajo por delante así que vamos a ir punto por punto:

  • Las funciones no siguen las normas básicas de las funciones:
    Una función debe realizar una función completa y autónoma. Una función es un fragmento de código que puedes reutilizar muchas veces. Para ello tiene que hacer una tarea muy bien definida y genérica. Por ejemplo: calcularMedia(...), mostrarMatriz(...), buscarMaximo(...), ... Si te fijas es muy sencillo saber qué hacen esas funciones, en cambio dos funciones que se llaman lista_de_personas_M() y lista_de_personas_F() no se sabe qué hacen a simple vista. Y además no hacen una tarea concreta sino que tienen dentro todo el programa en sí.

  • El nombre del struct no es del todo preciso. La estructura define una persona, no una lista de personas. Además estás definiendo en la línea 20 un array de struct global (no recomendable). Y cada vez que quieras usar el struct debes poner la palabra struct: en la línea 25 te falta el nombre de la variable. Poner: 'struct lista_de_personas;' es como poner: 'int;' Falta el nombre de la variable, sólo estás indicando el tipo que va a tener pero no cómo se llama. Seguramente este sea el primer error que te da al compilar.
    Otra cosa importante es que estás usando un char para guardar el nombre y otro para el apellido. Es decir, un único carácter para cada cosa, no una cadena.

    Una recomendación es usar 'typedef' para no tener que usar la palabra 'struct' todo el tiempo.
Código
  1. // Consejo EXTRA: Utiliza constantes para la longitud de los arrays estaticos
  2. #define MAX_LONGITUD_NOMBRE 20
  3. #define MAX_LONGITUD_APELLIDO 50
  4.  
  5. typedef struct {
  6.  char nombre[MAX_LONGITUD_NOMBRE];
  7.  char apellido[MAX_LONGITUD_APELLIDO];
  8.  // El DNI lo guardaria como un char[] y no como un int
  9.  //...
  10. } Encuestado;
  11.  
  12. int main() {
  13.  // Ahora para declarar un array de encuestados no hace falta hacer:
  14.  struct Encuestado encuestados[];
  15.  // Tan solo tienes que hacer:
  16.  Encuestado encuestados[];
  17. }

  • El main() de un programa de este estilo debería dar una visión general de lo que hace el programa (no cómo lo hace pero sí qué hace). En este caso si lees el main() te quedas más o menos así:  :huh:
    Yo apostaría por algo más de este estilo:
Código
  1. #define NUM_ENCUESTADOS 10
  2. #define NUM_CANCIONES 5
  3. //...
  4.  
  5. int main() {
  6.  Encuestado encuestados[NUM_ENCUESTADOS];
  7.  
  8.  for(int i = 0; i < NUM_ENCUESTADOS; ++i) {
  9.    printf("Introduce el nombre del encuestado %d: ", (i+1));
  10.    // Consejo EXTRA: Las cadenas de texto se leen con fgets() no con scanf(). Volveremos a esto mas adelante
  11.    fgets(personas[i].nombre, MAX_LONGITUD_NOMBRE, stdin);
  12.  
  13.    printf("Introduce la edad del encuestado %d: ", (i+1));
  14.    scanf("%d", &personas[i].edad);
  15.  
  16.    //...
  17.  }
  18.  // Tambien puedes hacer una funcion que sea pedirDatosEncuestado(Encuestado encuestado) y dentro poner todos los mensajes pidiendo datos y guardando la entrada del teclado...
  19.  
  20.  // Aqui ya puedes usar las funciones que quieras en base a lo que necesites
  21.  for(int i = 0; i < NUM_ENCUESTADOS; ++i) {
  22.    printf("***** DATOS DEL ENCUESTADO %d *****\n", (i+1));
  23.    // En el main() no necesito saber como va a mostrar los datos pero se lo que va a hacer. Para los detalles siempre puedes mirar dentro de la funcion
  24.    mostrarDatosEncuestado(encuestados[i]);
  25.    printf("\n");
  26.  }
  27. }

  • Entrada de datos: La función fflush() no debe usarse para limpiar el buffer de entrada (stdin). El fin de esta función (mal utilizada) es eliminar los saltos de línea '\n' que se insertan en el buffer de entrada al pulsar Enter. Aquí pueden darse 2 casos:
    • Lectura de cadenas de caracteres. La forma correcta/segura es mediante la función fgets(). Aquí pueden darse 2 casos también:
      • Se introducen más caracteres de los que se pueden almacenar en el array -> En el buffer quedarán todos los caracteres que no caben en el array y al final el salto de línea '\n'. Todo esto que queda en el buffer tiene que limpiarse.
      • Se introducen menos caracteres de los que se pueden almacenar en el array -> Se guardan todos los caracteres (incluido el salto de línea) y el buffer queda vacío.
      Para ambos casos se puede usar el siguiente código:
    Código
    1. char cadena[MAX_SIZE]; // La longitud maxima es indiferente
    2. printf("Introduce una cadena: ");
    3. fgets(cadena, MAX_SIZE, stdin);
    4. if(cadena[strlen(cadena) - 1] == '\n') // Si el ultimo caracter guardado es el salto de linea -> El buffer esta limpio
    5.  cadena[strlen(cadena) - 1] = '\0'; // Eliminamos el salto de linea que es muy molesto
    6. else // En caso de que el ultimo caracter no sea un salto de linea, significa que quedan restos en el buffer de entrada -> Hay que limpiar todo
    7.  while(getchar() != '\n'); // Elimina los caracteres que quedan en el buffer hasta encontrar el salto de linea (que es el ultimo caracter del buffer)
    • Lectura de datos que no sean cadenas de caracteres. Para este caso la función más común a utilizar es scanf(). Esta función nunca incluye el salto de línea dentro de la variable por lo que siempre quedará en el buffer. En este caso tan solo hay que limpiar todo el buffer justo después de un scanf() para asegurarnos de que siempre estará limpio.
    Código
    1. printf("Introduce un numero: ");
    2. scanf("%d", &numero);
    3. while(getchar() != '\n'); // Con el bucle podremos limpiar cualquier resto si se introduce un dato no valido ademas del salto de linea

      Y con esto creo que tienes ya recomendaciones para rato. Cualquier duda de estos temas tienes temas en este foro más antiguos donde se explican, puedes usar el botón de "Buscar" para encontrarlos.
      PD: Cuidado con los tipos de datos, tienes por ahí un %s para guardar un int...  :rolleyes: :rolleyes:
      PD2: Mencionas el método burbuja pero eso es un algoritmo de ordenación y hasta donde yo he entendido no necesitas ordenar nada en este programa... :huh:
      Páginas: 1 2 3 4 5 6 7 8 [9] 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 ... 102
      WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines