Autor
|
Tema: Problema leyendo cadenas con memoria dinamica [solucionado] (Leído 7,175 veces)
|
dato000
Desconectado
Mensajes: 3.034
|
Buenas gente, necesito una mano, ayudenme con este problema Poco a poco avanzo con memoria dinamica, me gusta más usar calloc 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. /* Escribir un programa para leer n cadenas de caracteres. Cada cadena tiene una longitud variable y esta formada por cualquier carácter. La memoria que ocupa cada cadena se ha de ajustar al tamaño que tiene. Una vez leidas las cadenas se debe realizar un proceso que consiste en eliminar todos los blancos, siempre manteniendo el espacio ocupado ajustado al número de caracteres. El programa debe mostrar las cadenas leídas y las cadenas transformadas. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #define longitud 100 int main() { char *cadena; int contador=0; int i; cadena = (char*) calloc(longitud , sizeof(char)); if(cadena == NULL) { printf("\n\t Error de asignación de memoria, adios!!"); } fgets(cadena , longitud , stdin ); for(i=0; i<strlen(cadena); i++) { if(cadena[i] == ' ') { cadena[i] = cadena[i+1]; contador++; } } printf("\n\n\t La cadena es: %s", cadena ); printf("\t Cantidad de espacios: %d", contador ); printf("\n\t longitud: %d -- strlen(cadena): %d", longitud , strlen(cadena )); return 0; }
Les agradezco cualquier pista slds
|
|
« Última modificación: 22 Enero 2014, 01:30 am por dato000 »
|
En línea
|
|
|
|
rir3760
Desconectado
Mensajes: 1.639
|
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: #include <stdio.h> #include <stdlib.h> #define MAX_CHARS 4096 int main(void) { char **linea; int num_lineas; int ch; int i; scanf("%d", &num_lineas ); while ((ch = getchar()) != EOF && ch != '\n') ; /* Reserva del bloque de memoria principal */ linea = malloc(num_lineas * sizeof *linea ); /* Lectura de cada una de las lineas */ for (i = 0; i < num_lineas; i++){ /* Reserva del bloque de memoria inicial para cada linea */ printf("Introduce la linea no %d:\n", i + 1); fgets(linea [i ], MAX_CHARS , stdin ); } /* Impresion de cada una de las lineas */ for (i = 0; i < num_lineas; i++) printf("%2d: %s", i + 1, linea [i ]); /* Primero se libera la memoria de cada linea ... */ for (i = 0; i < num_lineas; i++) /* ... a continuacion el bloque de memoria principal */ return EXIT_SUCCESS; }
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
Mensajes: 1.276
¿Habra que sacarla de paseo?
|
¡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: 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
Mensajes: 3.034
|
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?? /* Escribir un programa para leer n cadenas de caracteres. Cada cadena tiene una longitud variable y esta formada por cualquier carácter. La memoria que ocupa cada cadena se ha de ajustar al tamaño que tiene. Una vez leidas las cadenas se debe realizar un proceso que consiste en eliminar todos los blancos, siempre manteniendo el espacio ocupado ajustado al número de caracteres. El programa debe mostrar las cadenas leídas y las cadenas transformadas. */ #include <stdio.h> #include <stdlib.h> #include <string.h> #define longitud 100 int main() { char **cadena; int num_cadenas; int contador=0; int i,j; do { printf("Digite el numero de cadenas: "); scanf("%d%c", &num_cadenas ); }while(num_cadenas < 1); cadena = (char**) calloc(num_cadenas , sizeof(char*)); if(cadena == NULL) { printf("\n\t Error de asignación de memoria, adios!!"); } // leyendo cada linea en memoria for(i=0; i<num_cadenas; i++) { // Reservando el bloque de memoria para cada linea cadena [i ] = (char*) calloc(longitud , sizeof(char)); // +1 por '\n' printf("Digite la cadena # %d: ", i +1); fgets(cadena [i ], longitud , stdin ); } for(i=0; i<num_cadenas; i++) { for(j=0; j<strlen(cadena[i]); j++ ) { if(cadena[i][j] == ' ') { cadena[i][j] = cadena[i][j+1]; } } } for (i = 0; i < num_cadenas; i++) printf("cadena # %2d: %s", i + 1, cadena [i ]); /* Primero se libera la memoria de cada linea ... */ for (i = 0; i < num_cadenas; i++) /* ... a continuacion el bloque de memoria principal */ return 0; }
|
|
|
En línea
|
|
|
|
amchacon
Desconectado
Mensajes: 1.211
|
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": #include <stdio.h> #include <stdlib.h> #include <string.h> void LeerLinea(char** Linea) { const int Incremento = 5; int tam = 0; int max = Incremento; int ch; (*Linea ) = (char*) calloc(max ,sizeof(char)); while((ch = getchar()) != '\n' && ch != EOF ) { (*Linea)[tam++] = ch; if (tam == max) { max += Incremento; (*Linea ) = (char*)realloc (*Linea ,max ); if (*Linea == NULL) { printf("\n\t Error de asignación de memoria, adios!!"); } } } (*Linea)[tam] = 0; // caracter nulo } int main() { char **cadena; int num_cadenas; int contador=0; int i,j; do { printf("Digite el numero de cadenas: "); scanf("%d", &num_cadenas ); } while(num_cadenas < 1); cadena = (char**) calloc(num_cadenas , sizeof(char*)); if(cadena == NULL) { printf("\n\t Error de asignación de memoria, adios!!"); } // leyendo cada linea en memoria for(i=0; i<num_cadenas; i++) { LeerLinea(&cadena[i]); } for(i=0; i<num_cadenas; i++) { for(j=0;cadena[i]; j++ ) { if(cadena[i][j] == ' ') { cadena[i][j] = cadena[i][j+1]; } } } for (i = 0; i < num_cadenas; i++) printf("cadena # %2d: %s\n", i + 1, cadena [i ]); /* Primero se libera la memoria de cada linea ... */ for (i = 0; i < num_cadenas; i++) /* ... a continuacion el bloque de memoria principal */ return 0; }
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
|
|
|
|
dato000
Desconectado
Mensajes: 3.034
|
Cierto es, pero a modo de laboratorio me ayudo bastante, muchas gracias.
|
|
|
En línea
|
|
|
|
rir3760
Desconectado
Mensajes: 1.639
|
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í: #include <stdio.h> #include <stdlib.h> int main(void) { char a[] = "Esta es alguna cadena con espacios"; int i; int j; i = j = 0; do { if (a[i] != ' ') a[j++] = a[i]; }while (a[i++] != '\0'); /* ** En tu programa el bloque debe reajustarse, el ** numero de bytes esta dado por la variable "j" */ return EXIT_SUCCESS; }
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
Mensajes: 1.211
|
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
|
|
|
|
rir3760
Desconectado
Mensajes: 1.639
|
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
Mensajes: 3.034
|
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
|
|
|
|
|
Mensajes similares |
|
Asunto |
Iniciado por |
Respuestas |
Vistas |
Último mensaje |
|
|
Problema con asignación dinamica de memoria.
Programación C/C++
|
ThePinkPanther
|
9
|
5,083
|
4 Febrero 2013, 00:56 am
por ThePinkPanther
|
|
|
[SOLUCIONADO] C++ - Error con memoria dinámica: ¿Puntero por referencia?
Programación C/C++
|
xaps
|
7
|
6,080
|
22 Noviembre 2013, 17:16 pm
por lapras
|
|
|
arreglo de cadenas con memoria dinamica
Programación C/C++
|
wolftdark
|
2
|
2,253
|
7 Julio 2015, 03:30 am
por wolftdark
|
|
|
Concatenar cadenas con memoria dinámica en lenguaje C.
Programación C/C++
|
NOB2014
|
3
|
4,554
|
19 Junio 2016, 19:22 pm
por AlbertoBSD
|
|
|
Arreglo de cadenas con memoria dinámica (realloc) lenguaje C.
Programación C/C++
|
NOB2014
|
9
|
7,277
|
4 Octubre 2016, 17:42 pm
por MAFUS
|
|