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

 

 


Tema destacado: Trabajando con las ramas de git (tercera parte)


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  Problema leyendo cadenas con memoria dinamica [solucionado]
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Problema leyendo cadenas con memoria dinamica [solucionado]  (Leído 6,798 veces)
dato000


Desconectado Desconectado

Mensajes: 3.034



Ver Perfil
Problema leyendo cadenas con memoria dinamica [solucionado]
« en: 20 Enero 2014, 23:46 pm »

Buenas gente, necesito una mano, ayudenme con este problema

Poco a poco avanzo con memoria dinamica, me gusta más usar calloc  :xD :xD

ahora mi problema es que en el problema me estan pidiendo un arreglo multidimensional, tratando de leer multiples cadenas dependiendo de cuantas cadenas quiere el usuario, y ahi es donde me quedo corto a la hora de crear la reserva de la memoria.

No creo que sea tan dificil, pero realmente los ejercicios que estoy consultando estan un poco enredados y más que ayudarme, me confunden mucho más porque estan mezclando elementos de cadenas con estruturas y cosas así, necesito una aclaración de uds compañeros.

Código
  1. /*
  2.     Escribir un programa para leer n cadenas de caracteres. Cada cadena tiene una longitud variable
  3.     y esta formada por cualquier carácter. La memoria que ocupa cada cadena se ha de ajustar al
  4.     tamaño que tiene. Una vez leidas las cadenas se debe realizar un proceso que consiste en eliminar
  5.     todos los blancos, siempre manteniendo el espacio ocupado ajustado al número de caracteres.
  6.  
  7.     El programa debe mostrar las cadenas leídas y las cadenas transformadas.
  8. */
  9.  
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #define longitud 100
  14.  
  15. int main()
  16. {
  17.    char *cadena;
  18.    int contador=0;
  19.    int i;
  20.    cadena = (char*) calloc(longitud, sizeof(char));
  21.  
  22.    if(cadena == NULL)
  23.    {
  24.        printf("\n\t  Error de asignación de memoria, adios!!");
  25.        exit(-1);
  26.    }
  27.  
  28.    printf("Digite la cadena:  ");
  29.    fgets(cadena, longitud, stdin);
  30.  
  31.  
  32.  
  33.    for(i=0; i<strlen(cadena); i++)
  34.    {
  35.        if(cadena[i] == ' ')
  36.        {
  37.            cadena[i] = cadena[i+1];
  38.            contador++;
  39.        }
  40.    }
  41.  
  42.    printf("\n\n\t La cadena es: %s", cadena);
  43.    printf("\t Cantidad de espacios:  %d", contador);
  44.    printf("\n\t longitud: %d  -- strlen(cadena):  %d", longitud, strlen(cadena));
  45.  
  46.    free(cadena);
  47.    return 0;
  48. }
  49.  

Les agradezco cualquier pista

slds


« Última modificación: 22 Enero 2014, 01:30 am por dato000 » En línea


rir3760


Desconectado Desconectado

Mensajes: 1.639


Ver Perfil
Re: Problema leyendo cadenas con memoria dinamica
« Respuesta #1 en: 21 Enero 2014, 02:25 am »

Debes reservar un bloque para cada una de las cadenas, con esto no debes tener problemas. Ademas la dirección donde se almacena cada una ellas la debes almacenar en otro bloque.

Un ejemplo básico sin reajuste ni validaciones:
Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. #define MAX_CHARS  4096
  5.  
  6. int main(void)
  7. {
  8.   char **linea;
  9.   int num_lineas;
  10.   int ch;
  11.   int i;
  12.  
  13.   printf("Numero de lineas: ");
  14.   fflush(stdout);
  15.   scanf("%d", &num_lineas);
  16.   while ((ch = getchar()) != EOF && ch != '\n')
  17.      ;
  18.  
  19.   /* Reserva del bloque de memoria principal */
  20.   linea = malloc(num_lineas * sizeof *linea);
  21.  
  22.   /* Lectura de cada una de las lineas */
  23.   for (i = 0; i < num_lineas; i++){
  24.      /* Reserva del bloque de memoria inicial para cada linea */
  25.      linea[i] = malloc(MAX_CHARS);
  26.  
  27.      printf("Introduce la linea no %d:\n", i + 1);
  28.      fgets(linea[i], MAX_CHARS, stdin);
  29.   }
  30.  
  31.   /* Impresion de cada una de las lineas */
  32.   for (i = 0; i < num_lineas; i++)
  33.      printf("%2d: %s", i + 1, linea[i]);
  34.  
  35.   /* Primero se libera la memoria de cada linea ... */
  36.   for (i = 0; i < num_lineas; i++)
  37.      free(linea[i]);
  38.   /* ... a continuacion el bloque de memoria principal */
  39.   free(linea);
  40.  
  41.   return EXIT_SUCCESS;
  42. }
Se deben agregar las validaciones de las funciones de reserva de memoria así como E/S y también se debe agregar la lógica necesaria en el caso de una linea que rebase el limite (reajuste mediante realloc).

Un saludo


En línea

C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language
do-while


Desconectado Desconectado

Mensajes: 1.276


¿Habra que sacarla de paseo?


Ver Perfil
Re: Problema leyendo cadenas con memoria dinamica
« Respuesta #2 en: 21 Enero 2014, 15:34 pm »

¡Buenas!

Lo que no debes hacer es asignar una cantidad de memoria predeterminada a una cadena, lo hagas asignando esa memoria de forma dinamica o estatica, ya que si defines, por ejemplo, una longitud de 1000 caracteres puedes estar desaprobechando memoria si se introduce una cadena de menor longitud o puedes estar perdiendo informacion si tiene mayor longitud.

Lo que tienes que hacer es leer caracteres con una cadena de un tamaño determinado (por ejemplo 10 caracteres) y mediante realloc añadirlos a la linea que introduzcas. ¿Como sabras cuando has terminado de leer una linea? utiliza fgets, deja de leer cuando detecta un '\n' y lo almacena en la cadena:

Código:
hacer
{
    leer_cadena(lector);

    si(reasignar_memoria(linea, longitud(linea) + longitud(lector) + 1)
    {
        concatenar(linea,lector);
    }
}
mientras(lector[longitud(lector) - 1] != '\n');

linea[longitud(linea) - 1] = '\0';

Creo que es la unica manera que tienes de leer el contenido de una linea sin saber de antemano cual es la longitud maxima que puede tener.

¡Saludos!
En línea

- Doctor, confundo los números y los colores.
- Vaya marrón.
- ¿Marrón? ¡Por el culo te la hinco!
dato000


Desconectado Desconectado

Mensajes: 3.034



Ver Perfil
Re: Problema leyendo cadenas con memoria dinamica [solucionado]
« Respuesta #3 en: 22 Enero 2014, 01:02 am »

Muchas gracias por la ayuda, me sirvio bastante las pistas, pues aún no se como implementar bien lo de realloc, pero ya voy entendiendo como trabaja esto, finalmente pude sacarlo como queria, dejo el código, pero pues, como podría adaptarse la parte realloc sin tener un máximo constante para el número de caracteres que debe reservarse en memoria sin que se desperdicie??

Código
  1. /*
  2.     Escribir un programa para leer n cadenas de caracteres. Cada cadena tiene una longitud variable
  3.     y esta formada por cualquier carácter. La memoria que ocupa cada cadena se ha de ajustar al
  4.     tamaño que tiene. Una vez leidas las cadenas se debe realizar un proceso que consiste en eliminar
  5.     todos los blancos, siempre manteniendo el espacio ocupado ajustado al número de caracteres.
  6.  
  7.     El programa debe mostrar las cadenas leídas y las cadenas transformadas.
  8. */
  9.  
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #define longitud 100
  14.  
  15. int main()
  16. {
  17.    char **cadena;
  18.    int num_cadenas;
  19.    int contador=0;
  20.    int i,j;
  21.  
  22.    do
  23.    {
  24.        printf("Digite el numero de cadenas:  ");
  25.        scanf("%d%c", &num_cadenas);
  26.    }while(num_cadenas < 1);
  27.  
  28.    cadena = (char**) calloc(num_cadenas, sizeof(char*));
  29.  
  30.    if(cadena == NULL)
  31.    {
  32.        printf("\n\t  Error de asignación de memoria, adios!!");
  33.        exit(-1);
  34.    }
  35.  
  36.    // leyendo cada linea en memoria
  37.    for(i=0; i<num_cadenas; i++)
  38.    {
  39.        // Reservando el bloque de memoria para cada linea
  40.        cadena[i] = (char*) calloc(longitud, sizeof(char)); // +1 por '\n'
  41.        printf("Digite la cadena # %d:  ", i+1);
  42.        fgets(cadena[i], longitud, stdin);
  43.  
  44.  
  45.    }
  46.  
  47.    for(i=0; i<num_cadenas; i++)
  48.    {
  49.        for(j=0; j<strlen(cadena[i]); j++ )
  50.        {
  51.            if(cadena[i][j] == ' ')
  52.            {
  53.                cadena[i][j] = cadena[i][j+1];
  54.            }
  55.        }
  56.    }
  57.  
  58.  
  59.    for (i = 0; i < num_cadenas; i++)
  60.        printf("cadena # %2d: %s", i + 1, cadena[i]);
  61.  
  62.  
  63.    /* Primero se libera la memoria de cada linea ... */
  64.    for (i = 0; i < num_cadenas; i++)
  65.        free(cadena[i]);
  66.  
  67.    /* ... a continuacion el bloque de memoria principal */
  68.    free(cadena);
  69.    return 0;
  70. }
  71.  
En línea


amchacon


Desconectado Desconectado

Mensajes: 1.211



Ver Perfil
Re: Problema leyendo cadenas con memoria dinamica [solucionado]
« Respuesta #4 en: 22 Enero 2014, 14:03 pm »

Ten en cuenta que hoy en día importa más la eficiencia que la memoria, hoy en día nadie se preocupa por 6-7 bytes de más pero sí un progama tarda menos o no. El realloc es una operación costosa (creas un nuevo vector, copias el contenido al nuevo vector byte a byte y borras el antiguo).

No obstante, te presento una versión con realloc "amortiguado":
Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. void LeerLinea(char** Linea)
  6. {
  7.    const int Incremento = 5;
  8.    int tam = 0;
  9.    int max = Incremento;
  10.    int ch;
  11.  
  12.    (*Linea) = (char*) calloc(max,sizeof(char));
  13.  
  14.    while((ch = getchar()) != '\n' && ch != EOF)
  15.    {
  16.        (*Linea)[tam++] = ch;
  17.  
  18.        if (tam == max)
  19.        {
  20.            max += Incremento;
  21.            (*Linea) = (char*)realloc (*Linea,max);
  22.  
  23.            if (*Linea == NULL)
  24.            {
  25.                 printf("\n\t  Error de asignación de memoria, adios!!");
  26.                 exit(-1);
  27.            }
  28.        }
  29.    }
  30.  
  31.    (*Linea)[tam] = 0; // caracter nulo
  32. }
  33.  
  34. int main()
  35. {
  36.    char **cadena;
  37.    int num_cadenas;
  38.    int contador=0;
  39.    int i,j;
  40.  
  41.    do
  42.    {
  43.        printf("Digite el numero de cadenas:  ");
  44.        scanf("%d", &num_cadenas);
  45.    }
  46.    while(num_cadenas < 1);
  47.  
  48.    getchar();
  49.  
  50.    cadena = (char**) calloc(num_cadenas, sizeof(char*));
  51.  
  52.    if(cadena == NULL)
  53.    {
  54.        printf("\n\t  Error de asignación de memoria, adios!!");
  55.        exit(-1);
  56.    }
  57.  
  58.    // leyendo cada linea en memoria
  59.    for(i=0; i<num_cadenas; i++)
  60.    {
  61.        LeerLinea(&cadena[i]);
  62.    }
  63.  
  64.    for(i=0; i<num_cadenas; i++)
  65.    {
  66.        for(j=0;cadena[i]; j++ )
  67.        {
  68.            if(cadena[i][j] == ' ')
  69.            {
  70.                cadena[i][j] = cadena[i][j+1];
  71.            }
  72.        }
  73.    }
  74.  
  75.  
  76.    for (i = 0; i < num_cadenas; i++)
  77.        printf("cadena # %2d: %s\n", i + 1, cadena[i]);
  78.  
  79.  
  80.    /* Primero se libera la memoria de cada linea ... */
  81.    for (i = 0; i < num_cadenas; i++)
  82.        free(cadena[i]);
  83.  
  84.    /* ... a continuacion el bloque de memoria principal */
  85.    free(cadena);
  86.    return 0;
  87. }

Es "realloc amortiguado" porque aumento la memoria de 5 en 5 en vez de 1 en 1. Así hago mucho menos reallocs y como mucho desperdicio 4 bytes.
En línea

Por favor, no me manden MP con dudas. Usen el foro, gracias.

¡Visita mi programa estrella!

Rar File Missing: Esteganografía en un Rar
dato000


Desconectado Desconectado

Mensajes: 3.034



Ver Perfil
Re: Problema leyendo cadenas con memoria dinamica [solucionado]
« Respuesta #5 en: 22 Enero 2014, 15:22 pm »

Cierto es, pero a modo de laboratorio me ayudo bastante, muchas gracias.
En línea


rir3760


Desconectado Desconectado

Mensajes: 1.639


Ver Perfil
Re: Problema leyendo cadenas con memoria dinamica [solucionado]
« Respuesta #6 en: 24 Enero 2014, 17:55 pm »

Un comentario: en este momento los caracteres ' ' no se eliminan correctamente (solo se sobrescriben con el siguiente carácter). Para eliminarlos de la cadena hay que utilizar un bucle mas o menos así:
Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. int main(void)
  5. {
  6.   char a[] = "Esta es alguna cadena con espacios";
  7.   int i;
  8.   int j;
  9.  
  10.   printf("\"%s\"\n", a);
  11.  
  12.   i = j = 0;
  13.   do {
  14.      if (a[i] != ' ')
  15.         a[j++] = a[i];
  16.   }while (a[i++] != '\0');
  17.  
  18.   /*
  19.    ** En tu programa el bloque debe reajustarse, el
  20.    ** numero de bytes esta dado por la variable "j"
  21.    */
  22.  
  23.   printf("\"%s\"\n", a);
  24.  
  25.   return EXIT_SUCCESS;
  26. }

Un saludo
En línea

C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language
amchacon


Desconectado Desconectado

Mensajes: 1.211



Ver Perfil
Re: Problema leyendo cadenas con memoria dinamica [solucionado]
« Respuesta #7 en: 24 Enero 2014, 18:04 pm »

Un comentario: en este momento los caracteres ' ' no se eliminan correctamente (solo se sobrescriben con el siguiente carácter). Para eliminarlos de la cadena hay que utilizar un bucle mas o menos así
Te refieres a que sobran caracteres al final no?

Serviría el mismo código, solo habría que hacer un realloc con el nuevo tamaño de la cadena y listo.
En línea

Por favor, no me manden MP con dudas. Usen el foro, gracias.

¡Visita mi programa estrella!

Rar File Missing: Esteganografía en un Rar
rir3760


Desconectado Desconectado

Mensajes: 1.639


Ver Perfil
Re: Problema leyendo cadenas con memoria dinamica [solucionado]
« Respuesta #8 en: 24 Enero 2014, 18:28 pm »

Te refieres a que sobran caracteres al final no?
En parte ya que otro problema se presenta si la cadena es "a  b  c" (dos espacios como separacion) la cadena resultante sera "a bb cc".

Un saludo
En línea

C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language
dato000


Desconectado Desconectado

Mensajes: 3.034



Ver Perfil
Re: Problema leyendo cadenas con memoria dinamica [solucionado]
« Respuesta #9 en: 24 Enero 2014, 18:37 pm »

Cierto, se sobreescriben al final, pero ya seria el manejo del indice del arreglo, a modo de laboratorio podrian dejarse los espacios sobrantes como un valor cero o '\0' o usar un realloc para eso, pero pues, el objetivo esta cumplido, yo sigo con otro ejercicio.
En línea


Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines