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

 

 


Tema destacado: Estamos en la red social de Mastodon


  Mostrar Mensajes
Páginas: 1 2 3 [4] 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ... 26
31  Programación / Programación C/C++ / Re: Duda bucle do while en: 11 Enero 2015, 01:46 am
Con las correcciones propuestas por engelx, creo que quedaría así

Código
  1. int lector_de_opciones(int valor_maximo)
  2. {
  3.    int valor_elegido=0;
  4.    cout << " Introduce un numero entre 1 y " << valor_maximo;
  5.    valor_elegido = lector_de_enteros();
  6.  
  7.    while ( valor_elegido <=1 && valor_elegido >= valor_maximo ) {
  8.    {
  9.        cout << "Vuelve a introducir un numero que este dentro del rango, por favor:\n";
  10.        valor_elegido = lector_de_enteros();     // <-- correccion
  11.    }
  12.  
  13.    return valor_elegido;
  14. }
32  Programación / Programación C/C++ / Re: Algoritmo de Dijkstra paso a paso en: 11 Enero 2015, 01:40 am
Entiendo el planteamiento al respecto del algoritmo de Floyd, investigaré y posiblemente publique un post al respecto.

Por los momentos estoy terminando algunos detalles que faltaban al programa inicial, pues sabes, un trabajo no está completo hasta que está completo, jejeje

Y sobre todo ayudar a un par de lectores que tenían dudas de este tema en particular, espero que este aporte les disipe al respecto.
33  Programación / Programación C/C++ / Re: Puntero a funcion como argumento en: 10 Enero 2015, 16:25 pm
Sólo como un comentario, que me parece muy interesante el tema, una manera muy práctica de manejar menús.

Y por supuesto, la sugerencia de ivancea es la apropiada  ;D para el problema planteado, es lo que se hace para manejar funciones con número variable de argumentos.
34  Programación / Programación C/C++ / Re: Algoritmo de Dijkstra paso a paso en: 10 Enero 2015, 16:22 pm
Ahora sí que sí, ya lo pude terminar jajaja  ;D

El inicio de estre post me referí a un programa que emplea el algoritmo de Dijkstra para calcular la ruta más económica entre dos puntos de un grafo no dirigido. La versión inicialmente publicada fue en C++. Ahora voy con una vesión completamente en C, que además implementa una cola de prioridad para seleccionar más eficientemente el nodo objetivo a analizar en cada ciclo del algoritmo.

El principio es sencillo. Inicialmente la cola contiene únicamente al nodo inicial del grafo. Seguidamente se analizan todos los sucesores (no marcados) del nodo objetivo, y se evalúa o re-evalua su coste, y se coloca ordenadamente como corresponda en la cola de prioridad. La cola siempre permanece ordenada según el coste del nodo, de menor a mayor, puesto que cuando se inserta un nuevo elemento se lo hace en el lugar que corresponde según su valor.

En el caso que un nodo al ser re-evaluado disminuye o mejora su coste, entonces debe ser reubicado en la cola. Para ello, lo que hacemos es retirarlo de la cola y luego reinsertarlo en la posición adecuada.

Luego de ésto, el nodo objetivo es "marcado" y por lo tanto sacado de la cola puesto que no volverá a ser analizado en ejecuciones posteriores del algoritmo.

La versión a C se logró simplemente cambiando algunos "cout" a "printf()", y reemplazando el típico new/delete de C++ por el malloc()/free() de C. Lo que fue un poquito más complicado fue tener que implementar "manualmente" una cola de prioridad en C, porque no podemos usar la clase stack de la STL de C++.

A continuación el programa como quedó, y advierto que ahora si creció un poco superando las 300 líneas por eso lo voy a dividir por partes. Recomiendo leer con atención la función insert() que se ocupa de agregar un elemento a la cola según el coste del número de nodo indicado.

Espero con esto haber disipado las dudas de algunos de los lectores de mi tema, y cualquier sugerencia o recomendación no duden en escribir :)

Bibliotecas y prototipos

Código
  1. /* Programa que utiliza el algoritmo de Dijsktra para encontrar el
  2.  * camino más corto o económico entre dos puntos de un grafo
  3.  * no dirigido.
  4.  */
  5.  
  6. #include <stdlib.h>
  7. #include <stdio.h>
  8.  
  9. /* Definiendo la estructura etiqueta de nodo. Sus campos incluyen
  10.  * el n'umero de nodo, el coste total del nodo, y su precedente. */
  11. struct label {
  12. int nro; /* numero del nodo */
  13. int prev; /* nodo precedente (-1 para el nodo inicial )*/
  14. int peso; /* peso o coste total de la trayectoria que
  15. * conduce al nodo, i.e., el coste total desde
  16. * el nodo inicial hasta el actual. Un valor
  17. * de -1 denota el infinito */
  18. int marca; /* si el nodo ha sido marcado o no */
  19. };
  20. typedef struct label label_t;
  21.  
  22. /* Cola de Prioridad de n'umeros de nodo */
  23. struct node {
  24. int data;
  25. struct node * nextPtr; /* apuntador al siguiente nodo de la cola */
  26. };
  27. typedef struct node node_t;
  28.  
  29. int isEmpty( node_t * ); /* decide si cola es vac'ia */
  30. int insert( node_t **, int, label_t * ); /* agrega un nodo ordenadamente a la cola */
  31. void quit( node_t **, int ); /* retira un nodo espec'ifico de la cola */
  32. int pop( node_t ** ); /* retira el primer nodo de la cola */
  33. void printQueue( node_t * ); /* imprimir los valores almacenados en la cola */
  34.  
  35. /* Funci'on que calcula la distancia m'inima de cualquiera de los
  36.  * nodos al primero */
  37. void dijkstra( int, int **, int, int );

Función MAIN , simplemente crea la matriz de adyacencia y llama al Dijkstra

Código
  1. int main () {
  2.  
  3. int i, j;
  4.  
  5. /* cantidad total de nodos */
  6. int numNodos = 8;
  7.  
  8. /* Definiendo la matriz de adyacencia */
  9. int **A;
  10. if ( ( A = (int **) malloc( numNodos * sizeof(int *) ) ) == NULL ) return 1;
  11. for ( i = 0; i < numNodos; i++ )
  12. if ( ( A[i] = (int *) malloc( numNodos * sizeof(int) ) ) == NULL ) return 1;
  13.  
  14. for ( i = 0; i < 8; i++ )
  15. for ( j = 0; j < 8; j++ )
  16. A[i][j] = 0;
  17.  
  18. /* por simplicidad, completamos solo los pares de nodos conectados */
  19. A[0][1] = 16;
  20. A[0][2] = 10;
  21. A[0][3] = 5;
  22.  
  23. A[1][0] = 16;
  24. A[1][2] = 2;
  25. A[1][5] = 4;
  26. A[1][6] = 6;
  27.  
  28. A[2][0] = 10;
  29. A[2][1] = 2;
  30. A[2][3] = 4;
  31. A[2][4] = 10;
  32. A[2][5] = 12;
  33.  
  34. A[3][0] = 5;
  35. A[3][2] = 4;
  36. A[3][4] = 15;
  37.  
  38. A[4][2] = 10;
  39. A[4][3] = 15;
  40. A[4][5] = 3;
  41. A[4][7] = 5;
  42.  
  43. A[5][1] = 4;
  44. A[5][2] = 12;
  45. A[5][4] = 3;
  46. A[5][6] = 8;
  47. A[5][7] = 16;
  48.  
  49. A[6][1] = 6;
  50. A[6][5] = 8;
  51. A[6][7] = 7;
  52.  
  53. A[7][4] = 5;
  54. A[7][5] = 16;
  55. A[7][6] = 7;
  56.  
  57. /* Imprimir la matriz de adyacencia */
  58. printf( "Matriz de adyacencia:\n\n" );
  59. for ( i = 0; i < 8; i++ ) {
  60. for ( j = 0; j < 8; j++ )
  61. printf( "%2d  ", A[i][j] );
  62. printf( "\n" );
  63. }
  64. printf( "\n" );
  65.  
  66. /* calcular dijkstra a partir del nodo 0, a partir del nofo 7 */
  67. dijkstra( numNodos, A, 0, 7 );
  68.  
  69. /* liberar memoria */
  70. for ( i = 0; i < numNodos; i++ )
  71. free( A[i] );
  72. free( A );
  73.  
  74. return 0;
  75. }

Algoritmo de Dijsktra

Código
  1. /* Calcula el coste m'inimo de alcanzar un nodo final 'b'
  2.  * grafo no dirigido con N nodos, a partir del nodo inicial 'a',
  3.  * dada su matriz de adyacencia A */
  4. void dijkstra( int N, int **A, int a, int b ) {
  5.  
  6. label_t *Labels;
  7. int i, i0, j, peso;
  8. int *ruta; /* array de nodos de la ruta minima */
  9.  
  10. node_t *Cola = NULL; /* cola de prioridad */
  11.  
  12. /* Crea din'amicamente el arreglo de etiquetas de nodo */
  13. if ( ( Labels = malloc( N * sizeof( label_t ) ) ) == NULL ) return;
  14.  
  15. /* nodo inicial 'a' entre 0 y N - 1 */
  16. if ( a < 0 || a > N - 1 ) return;
  17. /* nodo final 'a' entre 0 y N - 1 */
  18. if ( b < 0 || b > N - 1 ) return;
  19.  
  20. /* inicializar las etiquetas de nodo */
  21. for ( i = 0; i < N; i++ ) {
  22. Labels[i].nro = i;
  23. if ( i != a ) {
  24. Labels[i].prev = -1; /* a'un no se ha definido predecesor */
  25. Labels[i].peso = -1; /* infinito */
  26. Labels[i].marca = 0;
  27. }
  28. else {
  29. Labels[i].prev = -1; /* a'un no se ha definido predecesor */
  30. Labels[i].peso = 0; /* coste del nodo inicial a s'i mismo es cero */
  31. Labels[i].marca = 0;
  32. }
  33. }
  34.  
  35. /* agregamos el nodo inicial como primer elemento de la cola */
  36. insert( &Cola, a, Labels );
  37.  
  38. /* continuamos este ciclo mientras existan nodos en la cola */
  39. while ( !isEmpty( Cola ) ) {
  40.  
  41. /* toma como objetivo el primer elemento de la cola de prioridad */
  42. i0 = pop( &Cola );
  43.  
  44. printf( "*** Analizando nodo %d ***\n", i0 );
  45.  
  46. /* actualiza el peso de todos los sucesores no marcados (si los hay) del nodo
  47. * encontrado y luego se~nala dicho nodo como marcado */
  48. for ( i = 0; i < N; i++ ) {
  49. if ( A[i0][i] > 0 && Labels[i].marca == 0 ) {
  50. /* si el coste es infinito, actualizar y añadir a la cola */
  51. if ( Labels[i].peso == -1 ) {
  52. Labels[i].peso = Labels[i0].peso + A[i0][i];
  53. insert( &Cola, i, Labels );
  54. }
  55. /* si el coste acumulado sumado al coste del enlace del nodo i0 al nodo i
  56. * es menor al coste del nodo i, actualizar al valor del costo menor y
  57. * reubicar en la cola */
  58. else if ( Labels[i0].peso + A[i0][i] < Labels[i].peso ) {
  59. printf( "   * advertencia: mejorando coste de nodo %d\n", i );
  60. Labels[i].peso = Labels[i0].peso + A[i0][i];
  61. quit( &Cola, i ); /* para reubicar, quitamos y luego a~nadimos el nodo */
  62. insert( &Cola, i, Labels );
  63. }
  64. Labels[i].prev = i0;
  65. printf( "   coste de nodo %d desde nodo %d: %d\n", i, i0, Labels[i].peso );
  66. }
  67. }
  68. Labels[i0].marca = 1;
  69. printf( "   * nodo %d marcado\n", i0 );
  70.  
  71. /* para verificar, imprime los costes calculados hasta el momento */
  72. for ( i = 0; i < N; i++ ) {
  73. printf( "%d: [", i);
  74. if ( Labels[i].peso == -1 ) printf( "Inf" ); else printf( "%d", Labels[i].peso);
  75. printf( ", %d", Labels[i].prev );
  76. if ( Labels[i].marca == 1 ) printf( ", x]\n" ); else printf( "]\n" );
  77. }
  78.  
  79. /* imprimir cola prioridad de nodos */
  80. printf( "cola de nodos en orden de prioridad es:\n" );
  81. printQueue( Cola );
  82.  
  83. /* pausa (opcional) */
  84. printf( "\npresione ENTER para continuar ..." );
  85. getchar();
  86. }
  87. printf( "Ya no quedan nodos por analizar.\n" ); /* mensaje final */
  88.  
  89. /* Ruta desde el nodo 'a' hasta el nodo 'b' */
  90. int longitud = 2;
  91. i = b;
  92. while ( ( i = Labels[i].prev ) != a ) longitud++; /* primero estimamos la longitud de la ruta */
  93. if ( ( ruta = malloc( longitud * sizeof(int) ) ) == NULL ) return;
  94.  
  95. ruta[longitud - 1] = b; /* luego rellenamos */
  96. i = b;
  97. j = 0;
  98. for ( j = 1; j < longitud; j++ ) {
  99. i = Labels[i].prev;
  100. ruta[longitud - j - 1] = i;
  101. }
  102.  
  103. printf( "================================================================\n" );
  104. printf( "\nRuta mas economica entre nodo %d y nodo %d:\n\n", a, b );
  105. for ( i = 0; i < longitud; i++ ) {
  106. printf( "%d", ruta[i]);
  107. if ( i < longitud - 1 ) printf( " - " );
  108. }
  109. printf( "\n\nCosto total: %d\n\n", Labels[b].peso );
  110.  
  111. free( ruta );
  112. free( Labels );
  113. }

Métodos asociados a la cola de prioridad

Código
  1. /* Devuelve 1 si la cola está vacía, 0 si no lo está. */
  2. int isEmpty( node_t * head ) {
  3.  
  4. return head == NULL;
  5. }
  6.  
  7. /* Insertar ordenadamente en la cola.
  8.  * Devuelve 0 si terminó con éxito, y 1 si ocurrió un error
  9.  * de asignación de memoria. */
  10. int insert( node_t ** frontPtr, int nodeNumber, label_t * Labels ) {
  11.  
  12. node_t *newPtr, *currentPtr, *prevPtr;
  13.  
  14. if ( ( newPtr = malloc( sizeof( node_t ) ) ) == NULL ) return 1;
  15.  
  16. /* busca el último nodo menor al que se quiere insertar */
  17. currentPtr = *frontPtr;
  18. prevPtr = NULL;
  19. while ( currentPtr != NULL && Labels[currentPtr->data].peso < Labels[nodeNumber].peso ) {
  20. prevPtr = currentPtr;
  21. currentPtr = currentPtr->nextPtr;
  22. }
  23.  
  24. /* inserta el nuevo nodo */
  25. newPtr->data = nodeNumber;
  26. if ( currentPtr != NULL )
  27. newPtr->nextPtr = currentPtr;
  28. else
  29. newPtr->nextPtr = NULL;
  30.  
  31. if ( prevPtr != NULL )
  32. prevPtr->nextPtr = newPtr;
  33. else
  34. *frontPtr = newPtr;
  35.  
  36. return 0;
  37. }
  38.  
  39. /* Remover de la cola el nodo con el valor específico, si lo encuentra */
  40. void quit( node_t ** frontPtr, int data ) {
  41.  
  42. node_t *prevPtr = NULL, *currPtr = *frontPtr;
  43.  
  44. /* busca el nodo con el valor espec'ifico */
  45. while ( currPtr != NULL && currPtr->data != data ) {
  46. prevPtr = currPtr;
  47. currPtr = currPtr->nextPtr;
  48. }
  49. if ( currPtr == NULL ) return; /* y termina si no encuentra */
  50.  
  51. /* si encuentra el nodo, lo remueve */
  52. if ( prevPtr != NULL )
  53. prevPtr->nextPtr = currPtr->nextPtr;
  54. else
  55. *frontPtr = currPtr->nextPtr;
  56.  
  57. free( currPtr );
  58. }
  59.  
  60. /* Retirar el primer elemento de la cola.
  61.  * Precaución: Devuelve cero si la cola est'a vacía.
  62.  */
  63. int pop( node_t **frontPtr ) {
  64.  
  65. node_t *auxPtr;
  66. int data;
  67.  
  68. if ( *frontPtr != NULL ) {
  69. auxPtr = *frontPtr;
  70. *frontPtr = (*frontPtr)->nextPtr;
  71. data = auxPtr->data;
  72. free( auxPtr );
  73. return data;
  74. }
  75. else
  76. return 0;
  77. }
  78.  
  79. void printQueue( node_t *queue ) {
  80.  
  81. node_t *currPtr = queue;
  82.  
  83. if ( currPtr == NULL ) {
  84. printf( "(vacio)\n" );
  85. return;
  86. }
  87.  
  88. while ( currPtr != NULL ) {
  89. printf( "%d", currPtr->data );
  90. if ( currPtr->nextPtr != NULL ) printf( " -> " );
  91. currPtr = currPtr->nextPtr;
  92. }
  93. printf( "\n" );
  94. }
35  Programación / Programación C/C++ / Re: [Ayuda] separar cadena en partes en: 9 Enero 2015, 00:46 am
Hola sabee

Las cadenas en C son arrays, es decir, arreglos, vectores, de elementos del tipo char. Es decir, las cadenas como tal no existen como tipo de dato básico de C, lo que existen son los caracteres, y las cadenas son arreglos o vectores de caracteres.

Para declarar una cadena en C puedes usar cualquiera de las formas:
Código
  1. char str[];
  2. char *str;

donde la primera declara un arreglo de char, y la segunda declara un apuntador a tipo char, ya que en C los arreglos son también apuntadores, pero es otro tema de discusión ...

También se pueden hacer declaraciones donde se inicialice directamente el contenido:
Código:
char str[] = "hola mundo";
en la que automáticamente el compilador calcula la cantidad de espacio necesario en el array para albergar la cadena respectiva.

Ten en cuenta que toda cadena en C debe estar terminada por un carácter especial llamado "nulo", simbolizado por '\0'. Esto demarca el fin de la cadena, y por lo tanto la cantidad de espacio de memoria asignado a la cadena. De otro modo, si no se encontrara el fin de cadena, la misma abarcaría consecutivamente todos los bytes de memoria hasta invadir un área prohibida de la misma e incurriendo en lo que se llama violación de segmento.

Por esta razón siempre debes sumar un byte adicional al reservar espacio para tu cadena. Por ejemplo la cadena "hola" ocupa físicamente 5 bytes de la memoria, es decir 4 bytes más el nulo de terminación:
Código:
'h'  'o'  'l'  'a'  '\0' 

Igualmente,  si una cadena tendrá n caracteres de longitud, debes declarar un arreglo de longitud n+1. Si la cadena msg deberá contener 100 caracteres como máximo entonces se declara:
Código:
char msg[101];
y así sucesivamente.

==================================================================
Dos funciones útiles de la biblioteca estándar de C para manipulación de cadenas (<string.h>) son strlen() y strcpy(). La primera calcula la longitud de la cadena, y la segunda copia el contenido de una cadena en otra (suponiendo que la cadena destino posee el espacio disponible suficiente). Ejemplos:

Código
  1. char str1[21];
  2. char str2[22];
  3.  
  4. strcpy( str1, "soy una cadena");
  5. printf( "str1 es: %s\n", str1 );
  6. printf( "longitud de str1 es: %d", (int) strlen(str1) );
  7. strcpy( str2, "soy otra cadena" );
  8. printf( "str2 es: %s\n", str2 );
  9. strcpy( str1, str2 );        /* copia str2 en str1 */
  10. printf( "ahora str1 es: %s\n", str1 );


=========================
Espero haberte ayudado en una introducción al tema, cualquier cosa preguntas  ;)

36  Programación / Programación C/C++ / Re: Algoritmo de Dijkstra paso a paso en: 8 Enero 2015, 17:14 pm
Voy a trabajar pronto en una versión completamente en C, que implemente cola de prioridad
37  Programación / Programación C/C++ / Re: EJERCICIO en: 6 Enero 2015, 18:27 pm
Te puedo ayudar, pero escríbeme por favor un txt a mano con la apariencia EXACTA que quieres lograr. Puede ser con sólo tres meses a manera de modelo a seguir. Lo subes a drobpox o algún sitio similar y así lo podemos ver y analizar.

Es difícil darte una pista más específica de cómo seguir sin tener claro el resultado exacto que producir.

Saludos, y espero por tu respuesta.
38  Programación / Programación C/C++ / Re: [Solucionado] Parametros desde consola en: 6 Enero 2015, 18:24 pm
Mmmm, se parece al programa que tiene el gobierno de Venezuela (mi país) con equipos llamados "Canaima", y un SO que dicen propio pero me parece más un clon de Ubuntu y encima sin dar los créditos, ......., en fin así son los políticos.

Sí, trato de ayudar a los que puedo y sería un honor recibir el título de Colaborador, aunque no conozco los requisitos necesarios para ello.

Y aunque no lo parezca, ayudando también se gana, he aprendido mucho respondiendo las preguntas aquí en el foro  :)

Saludos!
39  Programación / Programación C/C++ / Re: Ayuda: Programación con arreglos en: 6 Enero 2015, 02:18 am
Hola furciorita

La idea sería más o menos seguir los siguientes pasos

1.) Recibir a, b, c, d, m, n del teclado. ( Si m > n dar mensaje de error ).
2.) Inicializar r = m. Calcular f(m) e inicializar p = f(m).
3.) Inicializar s = m. Inicializar q = f(m) (ya calculado en el anterior)
4.) Luego en un ciclo, desde x = m + 1 hasta x = n:
     4.1  Si f(x) > p, hacer p = f(x), y hacer también r = x
     4.2  Si f(x) < q, hacer q = f(x), y hacer también s = x

La idea es que p conserve el valor máximo y q el mínimo de los valores evaluados. Si hallas un f(x) mayor que el valor actual de p, entonces p se actualiza a este nuevo valor máximo. Similar lógica respecto al mínimo q.

Luego de recorrer desde x = m + 1 hasta x = n, tendrás los valores p, q, r, s como se pide.

Ah, y recuerda que en C los arreglos comienzan con el índice 0, no el índice 1.

=================================================
Por cierto, la función eval() que defines pareciera querer implementar el llamado "método de Horner" para evaluación de polinomios. Supongo que a[0] representa el coeficiente de menor grado, mientras que a[3] es el de mayor. Pero creo que en este caso está mal implementado, debería ser como:
Código
  1. int eval( int a[], int x ) {
  2.    int aux = 1;      /* no aux = 0 !!! */
  3.    int i;
  4.  
  5.    for ( i = 3; i > 0; i-- )
  6.        aux  = a[i] * aux + a[i-1];
  7.  
  8.    return aux;
  9. }

Recuerda que en C los arreglos comienzan con el índice 0, por lo tanto el recorrido del vector es desde i=0 hasta i=3, no desde i=1 hasta i=4.

Con todo esto creo que ya puedes terminar tu programa, o al menos encaminarte a ello.
40  Programación / Programación C/C++ / Re: Algoritmo de Dijkstra paso a paso en: 6 Enero 2015, 01:48 am
Bueno marrison, si es para C la verdad es que no tienes mucho que cambiar. Tuve cuidado al elaborar el código de modo que fuera en su mayor parte compatible con C.

Lo único que tendrías que adaptar en la gestión dinámica de memoria para los arreglos que se crean en tiempo de ejecución. O sea, el uso de malloc(), realloc() y free(), en lugar de la combinación new y delete de C++.

De todos modos voy a ver si en estos días tengo un tiempo y versiono el código completamente a C.

Y un detalle, en el algoritmo que propuse falta implementar una "cola de prioridad", que puede optimizar la ejecución. En esta cola se van guardando los nodos en función de su peso, colocando de primero los de menor coste. De esta manera no hay que calcular el mínimo con cada ciclo, puesto que dicho nodo más económico siempre de está de primero en la cola y sólo hay que cogerlo de allí.

Un saludo ...
Páginas: 1 2 3 [4] 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 ... 26
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines