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

 

 


Tema destacado: Usando Git para manipular el directorio de trabajo, el índice y commits (segunda parte)


  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 ... 26
51  Programación / Programación C/C++ / Algoritmo de Dijkstra paso a paso en: 2 Enero 2015, 23:00 pm
Recientemente vi una pregunta de un usuario del foro sobre grafos no dirigidos y distancia mínima entre nodos del mismo. Me puse a invetigar el tema, el cual me pareció realmente interesante y decidí escribir un post al respecto.

El algoritmo de Dijkstra permite encontrar la distancia mínima entre un vértice dado de un grafo no dirigido, y cualquiera otro de sus vértices. No funciona sin embargo si la ponderación entre dos elementos es negativa, es sólo para grafos donde el coste de unir dos nodos cualesquiera es siempre mayor o igual que cero.

http://es.wikipedia.org/wiki/Algoritmo_de_Dijkstra
http://es.wikipedia.org/wiki/Anexo:Ejemplo_de_Algoritmo_de_Dijkstra

Un video de youtube que nos explica este tema de una manera excelente es:



A modo de ejemplo, consideremos el grafo (me disculpan la presentación simplemente me puse a escribir sobre una hoja de papel y le tomé fotografías)


En esta imagen, los valores sobre las aristas representan los pesos o costes de transitar los caminos que unen un nodo con el otro. El algoritmo comienza eligiendo un nodo inicial, en este caso digamos que el nodo 0.

Etiquetado de los nodos

Junto con cada nodo asociaremos una etiqueta o label que se compone de un par de valores:

( peso_acumulado, antecesor )

esto es, como primer elemento el peso total acumulado del nodo actual (la suma de los pesos de las aristas recorridas para llegar desde el nodo inicial hasta el nodo actual), y como segundo elemento denotamos el nodo previo al nodo actual. Esto último es importante para reconstruir la ruta seguida para llegar al nodo.

El nodo inicial tiene un peso de 0 (la distancia que lo separa de sí mismo es lógicamente cero), y no tiene antecesor, por lo que se asigna el par compuesto de un "cero" seguido de una "rayita": (0, -)


Vale decir que los restantes nodos comienzan con un peso o coste "infinito", pues aún no hemos calculado su coste.

Cálculo del coste hasta los nodos sucesivos

El siguiente paso es observar todos los nodos que están directamente conectados con este nodo inicial. En nuestro caso, los nodos 1, 2 y 3. El coste de cada nodo será el coste acumulado de su nodo antecesor, sumado al coste del camino que une al antecesor con el nodo actual:

Código:
coste de nodo 1: (coste acumulado nodo 0) + (coste camino que une nodos 0 y 1) = 0 + 16 = 16
coste de nodo 2: (coste acumulado nodo 0) + (coste camino que une nodos 0 y 2) = 0 + 10 = 10
coste de nodo 3: (coste acumulado nodo 0) + (coste camino que une nodos 0 y 3) = 0 + 5 = 5

por lo tanto etiquetamos estos nodos sucesores del nodo 0 de la siguiente manera:

Código:
nodo 1 ---> ( 16, 0 )     [ pues, su coste acumulado es 16, y procede del nodo 0 ]
nodo 2 ---> ( 10, 0 )     [ ídem ]
nodo 2 ---> ( 5, 0 )     [ ídem ]

Seguidamente, "tachamos" o "marcamos" el nodo 0 como definitivo, y con ellos hemos terminado el primer ciclio de la ejecución de nuestro algoritmo. Queda resaltar que un nodo "tachado" es un nodo que no se vuelve a revisar. El algoritmo terminará cuando todos los nodos estén "tachados".
Hasta ahora vamos así:


Continuación del algoritmo

El algoritmo continúa inspeccionando entre todos los nodos que no han sido tachados o marcados como definiitivos, pero tienen un peso total ya calculado menor a infinito. Esto es, los nodos 1, 2 y 3. De ellos, seleccionamos el de menor coste, que sería el nodo 3 y repetimos el proceso considerándolo como nodo inicial.

Al nodo 3 le suceden, exceptuando el propio nodo 0 que ya fue tachado (repito, los nodos tachados no se vuelven a revisar), los nodos 2 y 4. Sus costes totales se calcularían como:

Código:
coste de nodo 2: (coste acumulado nodo 3) + (coste camino que une nodos 3 y 2) = 5 + 4 = 9
coste de nodo 4: (coste acumulado nodo 3) + (coste camino que une nodos 3 y 4) = 5 + 15 = 20

por lo tanto etiquetamos estos nodos sucesores del nodo 3 de la siguiente manera:

Código:
nodo 2 ---> ( 9,  3 )     [ costo 9, procediendo del nodo 3 ]
nodo 4 ---> ( 20, 3 )     [ costo 20, procediendo del nodo 3 ]

Mejoramiento del coste

Obsérvese en la última etapa que hasta ahora llevamos del algoritmo, que el coste del nodo 2 mejoró de un valor 10 a un valor 9, al cambiar su antecesor y por lo tanto la ruta seguida.

Para ser más claros, el coste del nodo 2 al tomar la ruta que procede directamente desde el nodo 0 fue de 10. Pero al considerar la ruta que alcanza el nodo 2 desde el nodo 3, o sea la ruta 0-3-2, el coste total acumulado fue 5+4=9. Cuando esto ocurre tachamos la anterior etiqueta del nodo 2 que era (10,0), y la cambiamos por la etiqueta (9,3). Y esto lo debemos hacer cada vez que alcancemos un nodo que habíamos computado, pero esta vez desde una nueva ruta y con un costo menor.

El grafo nos va quedando así, y nótese como se mejora el coste del nodo 2. También nótese que tachamos el nodo 3, es decir lo marcamos como definitivo por eso no lo volveremos a revisar.


Siguiente paso

Revisamos ahora todos los nodos que tienen un coste calculado menor a infinito, en este caso los nodos 1,2  y 4. El de menor coste es el nodo 2, por lo tanto es el nodo que vamos a tomar como inicial.

Los sucesores del nodo 2 son los nodos 1, 4 y 5. Calculamos sus costes:

Código:
nodo 1, a partir de 2: 9 + 2 = 11   (mejora el coste)
nodo 5, a partir de 2: 9 + 12 = 21
nodo 4, a partir de 2: 9 + 10 = 19 (mejora el coste)

Marcamos el nodo 2 como definitivo, y continuamos.


Siguiente paso

De los nodos no definitivos que quedan (1, 4 y 5) el de menor coste es el 1. Inspeccionamos sus sucesores, los nodos 5 y 6, al calcular los costes de estos resulta:

Código:
nodo 5, a partir de 1: 11 + 4 = 15   (mejora el coste)
nodo 6, a partir de 1: 11 + 6 = 17

Tachamos el nodo 1 y continuamos.


b] Siguiente paso [/b]

De los nodos no definitivos que quedan (4, 5 y 6) el de menor coste es el 5. Inspeccionamos sus sucesores, los nodos 6, 7 y 4, al calcular los costes de estos resulta:

Código:
nodo 6, a partir de 5: 15 + 8 = 23   (empeora el coste)
nodo 7, a partir de 5: 15 + 16 = 31
nodo 7, a partir de 5: 15 + 3 = 18

Nótese que al recalcular el nodo 6 desde el nodo 5 se obtiene más bien un costo peor, por lo cual se mantiene su costo anterior que era 17, desde el nodo 1.

Tachamos el nodo 5 y continuamos, nos debe quedar así:


Pasos finales

El algoritmo se continúa repitiendo los pasos anteriores, hasta que no queden nodos sin tachar, es decir, hasta que todos queden como definitivos.



Reconstrucción de la ruta más económica

Una vez terminado, podemos calcular la ruta del coste mínimo desde el nodo inicial 0, hasta cualquiera otro de nuestros nodos. Por ejemplo, desde el nodo 0 hasta el nodo 7, vemos que el coste total es 23 y la ruta se forma regresivamente de la siguiente manera

Código:
el nodo 7, procede del nodo 4
el nodo 4, procede del nodo 5
el nodo 5, procede del nodo 1
el nodo 1, procede del nodo 2

etcétera, hasta llegar al nodo inicial. La ruta por lo tanto sería:

0 - 3 - 2 - 1 - 5 - 4 - 7

===================================================================
   PROGRAMA EN C++ PARA EL CALCULO DE LA RUTA MINIMA


Este es un pequeño programa que hice en C++ para computar el grafo anteriormente explicado usando el algoritmo de Dijkstra. Al cambiar la matriz de adyacencia por otra, se puede modificar el programa para trabajar con un grafo diferente. Claro, está un poco rudimentario, lo ideal sería poder pedir al usuario la matriz de adyacencia del grafo de forma interactica a través del teclado, pero hasta ahí no llegué por hoy jeje.

Codifiqué algunos "cout" para que el programa fuese imprimiendo los resultados de las distintas etapas del análisis, de modo que sea más explicativo o pedagógico. Por supuesto, el programa está dado a mejorar ya que esta es una versión muy básica pero es completamente funcional, sólo compilar y probar.

Para nuestro caso la salida final es (luego de imprimir información etapas previas del análisis, jeje)
Código:
================================================================

Ruta mas economica entre nodo 0 y nodo 7:

0 - 3 - 2 - 1 - 5 - 4 - 7

Costo total: 23

Por otra parte, creo que el programa no está mal, no es demasiado extenso porque la parte que calcula el Dijkstra sólo llevó 113 líneas de código, el resto del código es inicializando la matriz, declarando los structs, etc.

Código
  1. #include <iostream>
  2. #include <iomanip>
  3. #include <list>
  4.  
  5. /* Definiendo la estructura etiqueta de nodo. Sus campos incluyen
  6.  * el número de nodo, el coste total del nodo, y su precedente. */
  7. struct label {
  8.   int nro; /* numero del nodo */
  9.   int prev; /* nodo precedente (-1 para el nodo inicial )*/
  10.   int peso; /* peso o coste total de la trayectoria que
  11. * conduce al nodo, i.e., el coste total desde
  12. * el nodo inicial hasta el actual. Un valor
  13. * de -1 denota el infinito */
  14.   int marca; /* si el nodo ha sido marcado o no */
  15. };
  16. typedef struct label label_t;
  17.  
  18. using namespace std;
  19.  
  20. void dijkstra( int, int **, int, int );
  21.  
  22. int main () {
  23.  
  24.   /* cantidad total de nodos */
  25.   int numNodos = 8;
  26.  
  27.   /* Definiendo la matriz de adyacencia */
  28.   int i, j, **A;
  29.  
  30.   if ( ( A = new int*[numNodos] ) == NULL ) return 1;
  31.   for ( i = 0; i < numNodos; i++ )
  32.      if ( ( A[i] = new int[numNodos] ) == NULL ) return 1;
  33.  
  34.   for ( i = 0; i < 8; i++ )
  35.      for ( j = 0; j < 8; j++ )
  36.         A[i][j] = 0;
  37.  
  38.   /* por simplicidad, completamos solo los pares de nodos conectados */
  39.   A[0][1] = 16;
  40.   A[0][2] = 10;
  41.   A[0][3] = 5;
  42.  
  43.   A[1][0] = 16;
  44.   A[1][2] = 2;
  45.   A[1][5] = 4;
  46.   A[1][6] = 6;
  47.  
  48.   A[2][0] = 10;
  49.   A[2][1] = 2;
  50.   A[2][3] = 4;
  51.   A[2][4] = 10;
  52.   A[2][5] = 12;
  53.  
  54.   A[3][0] = 5;
  55.   A[3][2] = 4;
  56.   A[3][4] = 15;
  57.  
  58.   A[4][2] = 10;
  59.   A[4][3] = 15;
  60.   A[4][5] = 3;
  61.   A[4][7] = 5;
  62.  
  63.   A[5][1] = 4;
  64.   A[5][2] = 12;
  65.   A[5][4] = 3;
  66.   A[5][6] = 8;
  67.   A[5][7] = 16;
  68.  
  69.   A[6][1] = 6;
  70.   A[6][5] = 8;
  71.   A[6][7] = 7;
  72.  
  73.   A[7][4] = 5;
  74.   A[7][5] = 16;
  75.   A[7][6] = 7;
  76.  
  77.   /* Imprimir la matriz de adyacencia */
  78.   cout << "Matriz de adyacencia:" << endl << endl;
  79.   for ( i = 0; i < 8; i++ ) {
  80.      for ( j = 0; j < 8; j++ )
  81.         cout << setw(2) << A[i][j] << "  ";
  82.      cout << endl;
  83.   }
  84.   cout << endl;
  85.  
  86.   /* calcular dijkstra a partir del nodo 0, a partir del nofo 7 */
  87.   dijkstra( numNodos, A, 0, 7 );
  88.  
  89.   /* liberar memoria */
  90.   delete [] A;
  91.   for ( i = 0; i < numNodos; i++ )
  92.      delete A[i];
  93.  
  94.   return 0;
  95. }
  96.  
  97. /* Calcula el coste minimo de alcanzar un nodo final 'b'
  98.  * grafo no dirigido con N nodos, a partir del nodo inicial 'a',
  99.  * dada su matriz de adyacencia A */
  100. void dijkstra( int N, int **A, int a, int b ) {
  101.  
  102.   label_t *Labels;
  103.   int i, i0, j, peso;
  104.   int *ruta; /* array de nodos de la ruta minima */
  105.  
  106.   /* Crea din'amicamente el arreglo de etiquetas de nodo */
  107.   if ( ( Labels = new label_t[N] ) == NULL ) return;
  108.  
  109.   /* nodo inicial 'a' entre 0 y N - 1 */
  110.   if ( a < 0 || a > N - 1 ) return;
  111.   /* nodo final 'a' entre 0 y N - 1 */
  112.   if ( b < 0 || b > N - 1 ) return;
  113.  
  114.   /* inicializar las etiquetas de nodo */
  115.   for ( i = 0; i < N; i++ ) {
  116.      Labels[i].nro = i;
  117.      if ( i != a ) {
  118.         Labels[i].prev = -1; /* a'un no se ha definido predecesor */
  119.         Labels[i].peso = -1; /* infinito */
  120.         Labels[i].marca = 0;
  121.      }
  122.      else {
  123.         Labels[i].prev = -1; /* a'un no se ha definido predecesor */
  124.         Labels[i].peso = 0; /* coste del nodo inicial a s'i mismo es cero */
  125.         Labels[i].marca = 0;
  126.      }
  127.   }
  128.  
  129.   /* continuamos este ciclo mientras existan nodos no marcados */
  130.   while ( 1 ) {
  131.      /* busca entre todos los nodos no marcados el de menor peso, descartando los
  132.        * de peso infinito (-1) */
  133.      peso = -1;
  134.      i0 = -1;
  135.      for ( i = 0; i < N; i++ ) {
  136.         if ( Labels[i].marca == 0 && Labels[i].peso >= 0 )
  137.            if ( peso == -1 ) {
  138.               peso = Labels[i].peso;
  139.               i0 = i;
  140.            }
  141.            else if ( Labels[i].peso <= peso ) {
  142.               peso = Labels[i].peso;
  143.               i0 = i;
  144.            }
  145.      }
  146.      if ( i0 == -1 ) { /* termina si no encuentra */
  147.         cout << "Ya no quedan nodos por analizar." << endl;
  148.         break;
  149.      }
  150.  
  151.      cout << "*** Analizando nodo " << i0 << " ***" << endl;
  152.  
  153.      /* actualiza el peso de todos los sucesores (si los hay) del nodo
  154.        * encontrado y luego se~nala dicho nodo como marcado */
  155.      for ( i = 0; i < N; i++ ) {
  156.         if ( A[i0][i] > 0 ) {
  157.            /* si el coste acumulado sumado al coste del enlace del nodo i0 al nodo i
  158.              * es menor al coste del nodo i (o si el coste del nodo i es infinito),
  159.              * debemos actualizar */
  160.            if ( Labels[i].peso == -1 || Labels[i0].peso + A[i0][i] < Labels[i].peso ) {
  161.               if ( Labels[i0].peso + A[i0][i] < Labels[i].peso )
  162.                  cout << "   [ mejorando coste de nodo " << i << " ]" << endl;
  163.               Labels[i].peso = Labels[i0].peso + A[i0][i];
  164.               Labels[i].prev = i0;
  165.               cout << "   coste de nodo " << i << " desde nodo " << i0 << ": " << Labels[i].peso << endl;
  166.            }
  167.         }
  168.      }
  169.      Labels[i0].marca = 1;
  170.      cout << "   [ nodo " << i0 << " marcado ]" << endl;
  171.  
  172.      /* para verificar, imprime los costes calculados hasta el momento */
  173.      for ( i = 0; i < N; i++ ) {
  174.         cout << i << ": [";
  175.         if ( Labels[i].peso == -1 ) cout << "Inf";
  176.         else cout << Labels[i].peso;
  177.         cout << ", " << Labels[i].prev ;
  178.         if ( Labels[i].marca == 1 ) cout <<  ", x]" << endl;
  179.         else cout << "]" << endl;
  180.      }
  181.      cout << endl;
  182.  
  183.      /* pausa (opcional) */
  184.      cout << "presione ENTER para continuar ...";
  185.      cin.get();
  186.   }
  187.  
  188.   /* Ruta desde el nodo 'a' hasta el nodo 'b' */
  189.   int longitud = 2;
  190.   i = b;
  191.   while ( ( i = Labels[i].prev ) != a ) longitud++; /* primero estimamos la longitud de la ruta */
  192.   if ( ( ruta = new int[longitud] ) == NULL ) return;
  193.  
  194.   ruta[longitud - 1] = b; /* luego rellenamos */
  195.   i = b;
  196.   j = 0;
  197.   for ( j = 1; j < longitud; j++ ) {
  198.      i = Labels[i].prev;
  199.      ruta[longitud - j - 1] = i;
  200.   }
  201.  
  202.   cout << "================================================================" << endl;
  203.   cout << endl << "Ruta mas economica entre nodo " << a << " y nodo " << b << ":" << endl << endl;
  204.   for ( i = 0; i < longitud; i++ ) {
  205.      cout << ruta[i];
  206.      if ( i < longitud - 1 ) cout << " - ";
  207.   }
  208.   cout << endl << endl << "Costo total: " << Labels[b].peso << endl << endl;
  209.  
  210.   delete ruta;
  211.   delete [] Labels;
  212. }
52  Programación / Programación C/C++ / Re: EJERCICIO en: 2 Enero 2015, 17:04 pm
Defines un array char auxiliar. Luego con sprintf() imprimes el número entero formateado en una cadena, y luego pasas esa cadena a la posición que le corresponda en la matriz char.
Código
  1. char str[101];
  2. int numero = 2014;
  3.  
  4. sprintf( str, "%04d", numero );

ahora la cadena str contendrá "2014". Ten en cuenta que se añade un carácter nulo de terminación '\0' al final de str.  Lo demás sería copiar los caracteres no nulos de str a la parte que corresponda dentro de la matriz char.

P.D. El formato "%04d" es para que la cadena impresa obligatoriamente consuma 4 dígitos, en caso de por ejemplo 631 escribirá 0631.
53  Programación / Programación C/C++ / Re: [Ayuda] Parametros desde consola en: 2 Enero 2015, 15:30 pm
Ya va no entiendo bien, quieres que el "parámetro externo" sea el password que introduce el usuario, o sea el password correcto o consigna con el cual debe cotejarse el que introduzca el usuario.

Si es lo segundo, (intuyo que quieres llamar a este programa desde otro programa, que le indique cuál es la clave correcta a considerar) quedaría como:
Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. int main( int argc, char **argv)
  6. {
  7.  
  8.   char clave[21];             /* espacio para 20 caracteres, pues 5 es muy poco */
  9.   char clave2[21]; /* clave del usuario */
  10.   if ( argc < 3 ) { /* salir si hay menos de tres argumentos */
  11.      printf("faltan argumentos\n");
  12.      return 1;
  13.   }
  14.  
  15.   if ( !strcmp( argv[1], "-pass" ) ) {
  16.      strncpy( clave, argv[2], 20 );
  17.      clave[21] = '\0';
  18.   }
  19.   else
  20.      return 1;
  21.  
  22.   printf("Escriba su clave: ");
  23.   scanf("%s", clave2);
  24.   while ( getchar() != '\n' ) ;
  25.  
  26.   if ( !strcmp(clave, clave2) ) /* <-- ve aqui */
  27.   {
  28.      printf("sencillo a ejecutar\n");
  29.   }
  30.   else
  31.   {
  32.      printf("Clave no valida\n");
  33.   }
  34.  
  35.   return 0;
  36. }

Con te explicó engel, la declaración
Código
  1. int main(int argc, char** argv)
se usa para leer argumentos de main por consola. El primer argumento argc corresponde al número de argumentos leidos, en este caso 3. Pues el propio nombre de tu programa se considera como un argumento. El segundo argv es un arreglo de cadenas, donde cada cadena corresponde a uno de los argumentos pasados al programa. Ejemplo:
Código:
myprograma -pass xyz
entonces, argc vale 3, y los elementos del array argv serán:
Código:
en argv[0], la cadena "my programa"
en argv[1], la cadena "-pass"
en argv[2], la cadena "xyz"

Ya con esta explicación creo que se entiende el resto del código fuente que te suministré. Al compilar y probarlo verás:

./test -pass xyz
Escriba su clave: xyz
sencillo a ejecutar

pues, se pide cotejar con la clave "xyz". Si introduce una clave distinta a la esperada:

./test -pass xyz
Escriba su clave: abc
Clave no valida


Pequeñas observaciones:
  • Como uso Linux, antecedo el nombre de programa a ejecutar con "./", pero tú no lo necesitas en Windows.
  • La longitud de clave es muy pequeña, la cambié a 21, o sea 20 caracteres más el NULO de terminación. Nunca se te olvide sumar el NULO de terminación.
  • strcpy() requiere la cabecera <string.h>
  • ¿¿¿Para qué haces: system("echo sencillo a ejecutar")??? ... Es lo mismo que printf("sencillo de ejecutar\n"), y no se si has leído que se debe evitar en lo posible el uso de la orden system por ser muy dependiente del SO.

54  Programación / Programación C/C++ / Re: Juego del Pong en C en: 2 Enero 2015, 14:36 pm
Hola Almer

Utilidades gráficas de interacción con el usuario como movimiento del cursor en la pantalla, o peor aún la visualización del ratón, no son parte del estándar de C. Estas funciones son dependientes de tu máquina particular (pc, tablet, movil, etc) y del Sistema Operativo, por lo que deber utilizar funciones bibliotecas específicas para tu SO. Por ejemplo <conio.h> o <windows.h> para Windows, <ncurses> para Linux, etc.

En estas bibliotecas tendrás las funciones necesarias para producir el desplazamiento del cursor en la pantalla. Como soy usuario de Linux y no tanto de Windows, si trabajas con este último SO sería bueno que otro usuario de la comunidad pueda ayudarte y aportarte más detalles (¿Leosansan por ejemplo ?)
55  Programación / Programación C/C++ / Re: Ayuda con grafos en c en: 2 Enero 2015, 14:29 pm
Hola Marrison, estuve leyendo sobre el tema del algortimo Dijkstra y me pareció muy interesante. Voy a publicar hoy un post sobre el tema y te invitaré a consultarlo.
56  Programación / Programación C/C++ / Re: [C] Llamar a un array de punteros a caracteres en un bucle. en: 1 Enero 2015, 21:48 pm
Bueno,..... estuve revisando y convertir de C++ a C encierra unos detalles no tan mínimos  :-\

Debes cambiar los cout a printf, el cin a scanf. Ahora, como C no admite la clase string (C no admite clases), hay que declarar e inicializar el array de mensajes "manualmente". Puede quedar así:

Código
  1. #include <stdio.h>
  2. #include <ctype.h>
  3.  
  4. int (*func[])(int) = {islower,isupper,isdigit};
  5. char *mensaje1 = "una letra minuscula";
  6. char *mensaje2 = "una letra mayuscula";
  7. char *mensaje3 = "un numero";
  8. char *mensaje[3];
  9.  
  10. int main() {
  11.  
  12.    char ch;
  13.    int i;
  14.  
  15.    /* inicializa los mensajes */
  16.    mensaje[0] = mensaje1;
  17.    mensaje[1] = mensaje2;
  18.    mensaje[2] = mensaje3;
  19.  
  20.    printf("ingrese un caracter: ");
  21.    scanf ( "%c", &ch);
  22.    while ( getchar() != '\n' ) ; /* limpiar el bufer de entrada */
  23.  
  24.    for (i=0; i<3; i++) {
  25.        if ((*func[i])(ch)) {
  26.            printf( "ingreso %s\n", mensaje[i] );
  27.            break;
  28.        }
  29.  
  30.    }
  31.  
  32.    //getchar(); /* pausa antes de salir */
  33.    return 0;
  34. }
57  Sistemas Operativos / GNU/Linux / Re: Error al instalar LaTex en: 1 Enero 2015, 18:36 pm
Una sugerencia, prueba la suite texmaker, nunca me ha dado problemas, ni con Debian ni con Ubuntu:
Código:
audo apt-get install texmaker
58  Sistemas Operativos / GNU/Linux / Re: "Error al montar media/sda1" en: 1 Enero 2015, 18:34 pm
Antes de sugerirte una solución al problema con el montaje de la unidad, prueba hacer el siguiente diagnóstico.

Abre una terminal, y teclea

sudo fdisk -l

lo cual mostrará una lista de todos los discos hallados en tu sistema. Te pedirá tu contraseña de administrador. Lo que te muestre por pantalla luego de teclear ese comando, copialo y pégalo aquí como respuesta.

Otra cosa que querríamos ver es tu fichero fstab. Teclea en la terminal

cat /etc/fstab

y danos el resultado que muestra.

59  Programación / Programación C/C++ / Re: [Ayuda] variable dentro de char en: 24 Diciembre 2014, 20:24 pm
Bueno ........... primero que nada creo que no es necesario que cites todos mis mensajes anteriores, pues ellos de todos modos aparecen en el foro al principio del hilo.

Por otra parte, para lo que quieras hacer estoy a la orden. Realmente tu ejemplo me parece muy curioso y entretenido, aunque yo haría simplemente un script de batch, lo ejecutaría en consola y ya.

Tu ejemplo es un "programa que escribe programas", lo cual es una herramienta poderosa y con un potencial mucho más grande para explotar.

Éxito!!
60  Programación / Programación C/C++ / Re: Buscar una cadena en un archivo. en: 24 Diciembre 2014, 20:18 pm
Te voy a explicar con más cuidado lo del avance de línea, gets() y fgets().

En C una cadena no es más que un arreglo (vector) de caracteres, donde el último elemento debe ser un carácter '\0' llamado carácter nulo. Ahora, considera este código:
Código
  1. int main() {
  2.    char * str1[100];
  3.    char * str2[100];
  4.  
  5.    fgets( str1, 100, sdtin );
  6.    gets( str2 );
  7.  
  8.    return 0;
  9. }

¿Cuál es la diferencia? Pues, si corres el programa y escribes en el teclado "hola", la cadena str1 contendrá los caracteres

h - o - l - a - \n - \0

('\n' es el ENTER o avance de línea, y '\0' es el nulo de terminación) mientras str2 será:

h - o - l - a - \0

Por eso rir7376 te dice que fgtes() lee y almacena el avance de línea, mientra gets() lee y descarta.

¿Qué problemas se pueden ocasionar? Pues si usas gets(), el carácter '\n' NO es pasado a la cadena y por lo tanto permanece en el búfer de lectura del teclado. Debes limpiarlo y para ello se usa la clásica sentencia
Código
  1. while ( getchar() != '\n' ) ;
con el punto y coma al final. Si no limpias el búfer, corres el riesgo que de que este carácter '\n que quedó "flotando" por ahí se introduzca en forma indeseada con la próxima orden de lectura del teclado. Ese es el problema .... :-\

Por otra parte si usaste fgets(), el carácter '\n' es pasado a la cadena pero ahora tienes una cadena terminada en '\n', o sea 'h' - 'o' - 'l'- 'a' - '\n', y no 'h' - 'o' - 'l'  'a' como quizá esperabas. Lo puedes eliminar de varias maneras aunque no se si es propósito de discusión ese tema aquí.

En cualquier caso, fgets() es más seguro que gets() por lo que deberías preferirla. Y de cualquier modo, debes usar siempre una o siempre la otra, pero no mezclándolas.

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