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

 

 


Tema destacado: Entrar al Canal Oficial Telegram de elhacker.net


  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 25 26 27 ... 45
111  Programación / Programación C/C++ / Re: [C] (Aporte) Estructura de pila y cola con memoria dinámica en: 23 Agosto 2016, 04:56 am
¡Claro! Podrías poner un puntero void * que guarde datos genéricos, e incluso hacer que la función haga una copia de esos datos para que así hacer que el que programa no tenga que preocuparse por liberar o no la memoria almacenada en la pila!
112  Foros Generales / Foro Libre / Re: juguemos a ser el genio en: 22 Agosto 2016, 22:01 pm
Concedido, pero un par de agentes de negro harán que tengas un "accidente"
Deseo tener conocimiento ilimitado
113  Programación / Programación C/C++ / [C] (Aporte) Estructura de pila y cola con memoria dinámica en: 22 Agosto 2016, 21:01 pm
Hola, muy buenas. Dado un tema reciente decidí implementar en C una estructura que funcione como cola y otra como pila (estructuras FIFO y LIFO respectivamente). Bueno, parece que son muchas líneas, pero entre comentarios, y saltos de líneas "innecesarios", el código no es tan largo. Aquí se los dejo.

NOTA: Ya sé que ya se ha subido la implementación de estas estructuras, pero eso fue en C++, no en C.

Código
  1. #include <stdlib.h>
  2. #include <stdio.h>
  3.  
  4. // Para generalizar, uso un tipo de datos predefinido, así puedo
  5. // cambiar entre int y el tipo de datos que quiera
  6. typedef int tipo;
  7.  
  8. typedef struct ElementoLista{
  9. tipo dato;
  10. struct ElementoLista *siguiente;
  11. } Elemento;
  12.  
  13. // En la estructura de una pila, solo necesitamos la referencia al
  14. // último elemento agregado
  15. typedef struct {
  16. Elemento *ultimo;
  17. unsigned int num_elementos;
  18. } Pila;
  19.  
  20. // Pero en la estructura de una cola, también necesitaremos la
  21. // referencia del primer elemento
  22. typedef struct {
  23. Elemento *primero;
  24. Elemento *ultimo;
  25. unsigned int num_elementos;
  26. } Cola;
  27.  
  28. // Si alguna de estas dos funciones retorna 0, significa que
  29. // ha ocurrido un error, de lo contrario, retornará un valor
  30. // diferente de 0
  31. int agregar_a_pila(Pila *pila, tipo dato);
  32. int agregar_a_cola(Cola *cola, tipo dato);
  33.  
  34. // Destruye el último elemento y retorna los datos almacenados en el
  35. tipo quitar_a_pila(Pila *pila);
  36. tipo quitar_a_cola(Cola *cola);
  37.  
  38. // Para demostrar el uso de 'quitar_a_pila' y 'quitar_a_cola'
  39. // estas funciones destruyen la pila y la cola respectivamente
  40. // al mostrarlas
  41. void mostrar_pila(Pila *pila);
  42. void mostrar_cola(Cola *cola);
  43.  
  44. int main() {
  45. // No hay que olvidarse de inicializar, porque si no,
  46. // no hay manera de determinar si un puntero a memoria
  47. // dinámica es válido o no...
  48. Pila pila = {NULL, 0};
  49. Cola cola = {NULL, NULL, 0};
  50. tipo dato;
  51.  
  52. // Para probar que todo funciona perfectamente, hacemos que el
  53. // usuario introduzca enteros para almacenarlos tanto en una cola
  54. // como en una pila.
  55. fprintf(stdout, "Introduzca una serie de numeros (0 para acabar): ");
  56. fscanf(stdin, "%d", &dato);
  57. while(0 != dato) {
  58. agregar_a_pila(&pila, dato);
  59. agregar_a_cola(&cola, dato);
  60. fscanf(stdin, "%d", &dato);
  61. }
  62.  
  63. // Mostramos la pila y la cola (destruyendo a su vez los datos
  64. // de las mismas)
  65. mostrar_pila(&pila);
  66. fputc('\n', stdout);
  67. mostrar_cola(&cola);
  68.  
  69. return 0;
  70. }
  71.  
  72. int agregar_a_pila(Pila *pila, tipo dato) {
  73. Elemento *elemento;
  74.  
  75. // Creamos elemento y guardamos datos...
  76. elemento = malloc(sizeof(Elemento));
  77. if(NULL == elemento)
  78. return 0;
  79.  
  80. elemento->dato = dato;
  81.  
  82. // Reconfiguramos pila...
  83. if(NULL == pila->ultimo) {
  84. elemento->siguiente = NULL;
  85. pila->num_elementos = 1;
  86. pila->ultimo = elemento;
  87. } else {
  88. elemento->siguiente = pila->ultimo;
  89. pila->num_elementos += 1;
  90. pila->ultimo = elemento;
  91. }
  92.  
  93. return 1;
  94. }
  95.  
  96. int agregar_a_cola(Cola *cola, tipo dato) {
  97. Elemento *elemento;
  98.  
  99. // Creamos elemento y guardamos datos...
  100. elemento = malloc(sizeof(Elemento));
  101. if(NULL == elemento)
  102. return 0;
  103.  
  104. elemento->dato = dato;
  105. elemento->siguiente = NULL;
  106.  
  107. // Reconfiguramos cola...
  108. if(NULL == cola->primero) {
  109. cola->num_elementos = 1;
  110. cola->primero = elemento;
  111. cola->ultimo = elemento;
  112. } else {
  113. cola->ultimo->siguiente = elemento;
  114. cola->num_elementos += 1;
  115. cola->ultimo = elemento;
  116. }
  117.  
  118. return 1;
  119. }
  120.  
  121. tipo quitar_a_pila(Pila *pila) {
  122. Elemento *temp;
  123. tipo dato;
  124.  
  125. if(NULL != pila->ultimo) {
  126. dato = pila->ultimo->dato;
  127. temp = pila->ultimo;
  128. pila->ultimo = pila->ultimo->siguiente;
  129. pila->num_elementos -= 1;
  130. free(temp);
  131. } else {
  132. dato = -1;
  133. }
  134.  
  135. return dato;
  136. }
  137.  
  138. tipo quitar_a_cola(Cola *cola) {
  139. Elemento *temp;
  140. tipo dato;
  141.  
  142. // Hacemos esta asignación, porque si el primer elemento de la cola y
  143. // el último son iguales, destruiremos el primer elemento, dejando al último
  144. // sin memoria asignada, por lo que directamente al último elemento le
  145. // asignamos NULL para que no haya errores
  146. if(cola->primero == cola->ultimo)
  147. cola->ultimo = NULL;
  148.  
  149. if(NULL != cola->primero) {
  150. dato = cola->primero->dato;
  151. temp = cola->primero;
  152. cola->primero = cola->primero->siguiente;
  153. cola->num_elementos -= 1;
  154. free(temp);
  155. } else {
  156. dato = -1;
  157. }
  158.  
  159. return dato;
  160. }
  161.  
  162. void mostrar_pila(Pila *pila) {
  163. tipo dato;
  164.  
  165. while(NULL != pila->ultimo) {
  166. dato = quitar_a_pila(pila);
  167. fprintf(stdout, "%d ", dato);
  168. }
  169. }
  170.  
  171. void mostrar_cola(Cola *cola) {
  172. tipo dato;
  173.  
  174. while(NULL != cola->primero) {
  175. dato = quitar_a_cola(cola);
  176. fprintf(stdout, "%d ", dato);
  177. }
  178. }
114  Programación / Programación C/C++ / Re: Dudas con cola e INT_MAX lenguaje C. en: 22 Agosto 2016, 17:20 pm
Para liberar la memoria, no basta con asignarle un NULL, primero tienes que liberar la memoria con la función free, donde su único parámetro es el puntero que apunta a un bloque de memoria dinámica (un bloque creado con malloc, calloc o realloc).

Además, si solo hay un elemento, al liberar la memoria, tendrías que hacer que tanto 'inicio' como 'final' también sean nulos.

En el caso de que haya más de un elemento, yo haría esto:
Código
  1. Elemento *temp = inicio;
  2. inicio = inicio->siguiente;
  3. free(temp);
115  Programación / Programación C/C++ / Re: Duda con cola en lenguaje C. en: 22 Agosto 2016, 00:10 am
ATENCIÓN, RESPUESTA LARGA

Primero, para que entiendas mejor, voy a explicar algo necesario. Para entender lo que voy a explicar, tendrás que dominar un poco la base binaria y cómo pasar entre decimal y binario.

Procedo a explicar cómo se puede almacenar un entero con signo

Imaginemos que queremos guardar el número -123 como un entero sin signo. Para hacerlo lo que tenemos que hacer es restar a 2^31 - 1 (2 elevado a 31 menos 1) con 123 (he puesto 31 porque un entero suele ocupar 32 bits, y hay que restar 1 porque el último bit se usa para "saber si el número es positivo o negativo"). El resultado de esa operación es 2147483524. Ahora convertimos ese número a binario:

1111111111111111111111110000100

Aquí hay 31 bits. Por último, tenemos que poner el último bit como 1, para indicar que el número es negativo (lo ponemos a la derecha):

11111111111111111111111110000100

CONCLUSIONES IMPORTANTES DE ESTE PROCESO:
  • Si el último bit vale 1, entonces seguro que el número es negativo, de lo contrario, el número es positivo

(En realidad, la CPU hace otro proceso más simple, pero que es un poco más difícil de ver a simple vista, por eso lo expliqué así).
_____________________________________________________________________

Una vez sabido esto, procedamos a explicar tu duda:
estoy desconcertado con esto, yo había intentado unas cuantas veces y siempre seguía en el bucle si el ingreso era mayor que el permitido por INT_MAX, ahora resulta que en ciertos casos también me falla y pone un número distinto al ingresado y sale del bucle, debo suponer que esto no tiene solución, soy muy exigente con las validaciones de ingreso de datos. -

Vamos a enumerar lo que hace la función scanf:

scanf lee el entero, y lo convierte a binario hasta que se acaben los dígitos introducidos. Una vez obtenido el número, guarda los primeros 32 bits en la variable.

Ahora imagina que has introducido 2147483650 (que es INT_MAX + 1). Vamos a convertir ese número a binario:

10000000000000000000000000000001

Aquí, scanf ya tiene directamente los 32 bits, por lo que los copia sin fijarse en la variable y dice que todo ha ido bien. Entonces, una vez que la variable tiene esos bits, vamos a convertir ese número binario a entero con signo.


  • Primero, el bit número 32 es 1, por lo que el número va a ser negativo.
  • Segundo, teniendo en cuenta lo que expliqué al principio de esta respuesta, convertimos los 31 primeros bits a decimal. Resultado: 1.
  • Tercero, realizamos la operación inversa a lo del principio de la respuesta: 2^31 - 1 - valor = 1. Despejamos la ecuación... valor = 2^31 - 2 = 2147483646

Por lo tanto, si por la consola introducimos INT_MAX + 1, lo que en realidad almacenaremos en la variable entera con signo es -2147483646.
____________
Ahora bien, ¿por qué a veces si que da como resultado un número positivo?

Eso es sencillo, lo que pasa es que el número resultante tenía como último bit un 0, por lo que como ya hemos dicho, eso significa que la variable será positiva.

EJEMPLO RÁPIDO:
Introducimos por consola 4294967336 (mayor a INT_MAX)
Este número en binario es 100000000000000000000000000101000
Copiamos los 32 primeros bits a la variable: 00000000000000000000000000101000
El bit número 32 de la variable vale 0 (puedes contarlo tu mismo).

Como el bit nº 32 vale 0, entonces la variable será positiva, pero valdrá 40 (esto lo sacas de convertir 00000000000000000000000000101000 a binario).
116  Programación / Programación C/C++ / Re: Duda con cola en lenguaje C. en: 21 Agosto 2016, 23:03 pm
Cita de: NOB2014
No estoy de acuerdo, si se ingresa un dato mayor a INT_MAX no se sale del bucle, en cambio, si no pongo esta condición el compilador lo transforma a un número negativo o algo por el estilo, no recuerdo.  

Lo que digo es 100% verdad, y te lo demuestro. Un entero, en informática, se almacena en binario con una cierta cantidad de bits. En C, con ordenadores actuales, se suelen almacenar con 32 bits. Entonces, dado que hay un espacio limitado en la que poder almacenar el entero, es imposible pasar ese límite, porque el tamaño de un entero en C es fijo.

Entonces, ¿por qué no sale del bucle? Imaginemos que introduces el valor INT_MAX + 1. ¿Qué es lo que va a pasar? Que scanf va a transformar lo introducido a binario, por lo que obtendremos lo siguiente:

1000000000000000000000000000000

Aquí hay un 1 y 31 0s. Eso, interpretado para un entero con signo, da como resultado un número negativo, por lo que 'ok' valdrá 0 (ya que no se cumple que sea mayor que 0). Entonces, el while se ejecuta de nuevo, y por lo tanto, te pide otro número, entonces por eso parece que si introduces un número superior a INT_MAX, entonces el bucle se repite hasta que introduzcas otro número. A modo de experimento, mira qué pasa si introduces el 4294967298, un número claramente superior a INT_MAX
117  Programación / Programación C/C++ / Re: Duda con cola en lenguaje C. en: 21 Agosto 2016, 21:53 pm
A ver, si, técnicamente yo lo veo bien, pero en mi opinión, está mal estructurado. Lo que yo haría es la siguiente estructura:

Código
  1. typedef struct ElementoLista{
  2.    int dato;
  3.    struct ElementoLista *siguiente;
  4. } Elemento;
  5.  
  6. typedef struct {
  7.    Elemento *ultimo;
  8.    unsigned int num_elementos;
  9. } Pila;
  10.  
  11. typedef struct {
  12.    Elemento *primero;
  13.    unsigned int num_elementos;
  14. } Cola;
  15.  
  16. // Si se retorna 0 por alguna de las dos funciones siguientes, ha habido error. De lo contrario, todo ha ido correctamente
  17. int agregar_a_pila(pila *pila);
  18. int agregar_a_cola(cola *cola);
  19.  
  20. int quitar_a_pila(pila *pila);
  21. int quitar_a_cola(cola *cola);
  22.  
  23. void mostrar_pila(const pila *pila);
  24. void mostrar_cola(const cola *cola);

Pequeño detalle a tener en cuenta:
Código
  1. ok = scanf( "%d", &dto ) == 1 && dto >0 && dto <= INT_MAX;

Un entero JAMÁS va a ser mayor que INT_MAX (si eso sucediera, sería un bug del compilador), así que es una tontería poner la condición 'dto <= INT_MAX'
118  Foros Generales / Dudas Generales / Re: Como guarda x detrás la información un hd en: 21 Agosto 2016, 03:54 am
Lo que se emplea para almacenar la información en base binaria es usar un código. Lo que se hace es codificar un audio. Por ejemplo, para codificar los caracteres comúnmente se usa el código ASCII. Aquí tienes una página con una codificación ASCII extendida:

http://www.elcodigoascii.com.ar/

Como ves, a cada carácter se le asigna un número, donde cada número puede convertirse fácilmente a código binario. Por ejemplo, el 0 en binario es 0, el 1 es 1, el 2 es 10, el tres es 11, el cuatro es 100... Si quieres saber cómo convertir un número en base decimal a binario, puedes mirar el siguiente enlace:

http://recursostic.educacion.es/secundaria/edad/4esotecnologia/quincena5/4q2_contenidos_2c.htm#
119  Programación / Java / Re: game engine en java? en: 21 Agosto 2016, 03:45 am
LWJGL no es un motor gráfico como tal, simplemente te da acceso al aceleramiento por hardware mediante OpenGL y otros hardware (internamente usa GLFW para crear el sistema de ventanas, OpenAL para el audio...)
120  Foros Generales / Foro Libre / Re: juguemos a ser el genio en: 20 Agosto 2016, 20:45 pm
Concedido, pero tu no arderás junto a el y tendrás que vivir sin comida (estará quemada)
Deseo energía infinita
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 25 26 27 ... 45
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines