Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: NOB2014 en 3 Octubre 2016, 23:02 pm



Título: Arreglo de cadenas con memoria dinámica (realloc) lenguaje C.
Publicado por: NOB2014 en 3 Octubre 2016, 23:02 pm
Hola a todos.
Alguien me podría decir como solucionar el siguiente error:
Citar
repaso.c: In function ‘main’:
repaso.c:44:3: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
   printf( "\n %s ", frases[n] );
   ^

Créanme que con lo tedioso que me resulta buscar la solución en inglés lo hice por un montón de páginas y no logré dar con la solución, creo que el error lo tengo en la línea 29 pero no lo logro.

Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. #define MAX_CHAR 30
  6.  
  7. void limpiar( void );
  8.  
  9. int main( void ){
  10. size_t contador=0, ch, n;
  11. char *frases=NULL, *tmpFrases=NULL, ingreso[MAX_CHAR], salir, *p=NULL;
  12.  
  13. do{
  14. limpiar();
  15. printf("\n Ingrese frase(maximo %d)....: ", MAX_CHAR);
  16. fgets( ingreso , MAX_CHAR, stdin );
  17. if((p=strchr(ingreso, '\n'))){
  18. *p='\0';
  19. }
  20. else{
  21. while((ch = getchar()) !='\n' && ch!=EOF);
  22. }
  23. contador++;
  24.  
  25. tmpFrases = (char*)realloc( frases, contador * sizeof(char) );
  26.  
  27. if( tmpFrases!=NULL ){
  28. frases=tmpFrases;
  29. frases[contador-1] = *ingreso ;
  30. }
  31. else{
  32. free( frases );
  33. puts( "Error (re)allocating memory" );
  34. exit(1);
  35. }
  36.  
  37. printf("\n Para continuar \"S\" para finalizar \"N\"....:");
  38. scanf("%c", &salir);
  39. while((ch = getchar()) !='\n' && ch!=EOF);
  40. }while ( salir != 'n' && salir != 'N' );
  41.  
  42. printf ("\n Frases introducidas.....: ");
  43. for( n=0; n < contador-1; n++ )
  44. printf( "\n %s ", frases[n] );
  45.  
  46. free( frases );
  47.  
  48.  
  49. return 0;
  50. }
  51.  
  52. void limpiar( void ){
  53. system("cls||clear");
  54. }
dato000 gracias por ocuparte del tema anterior. -
Saludos


Título: Re: Arreglo de cadenas con memoria dinámica (realloc) lenguaje C.
Publicado por: MAFUS en 4 Octubre 2016, 01:07 am
frases no es un array de cadenas, es solo una cadena, prueba de ello es su definición:
char *frases

para que sea un array dinámico de frases deberías hacer
char **frases

después a cada frase nueva haces crecer el puntero con calloc

Código:
char frases = calloc(frases, (tam_frases + 1) * sizeof(char*))

seguidamente cargas la nueva frase al array

Código:
scanf("%m[^\n]%*c", &frases[tam_frases]);

y actualizas tam_frases

Código:
++tam_frases

Para acabar acuérdate de liberar toda la memoria adquirida por scanf para cada cadena.
Código:
for(i = 0; i < tam_frases; ++i)
    free(cadena[i])


Título: Re: Arreglo de cadenas con memoria dinámica (realloc) lenguaje C.
Publicado por: NOB2014 en 4 Octubre 2016, 01:37 am
Hola, MAFUS.
En mucho tiempo es la primera vez que no me resulta(tus ayudas) y además no entiendo los trozos de código que propones, por lo tanto, voy a intentarlo de otra manera, estoy desconcertado, tal vez otra propuesta me aclare las cosas. -

Un abrazo. -


Título: Re: Arreglo de cadenas con memoria dinámica (realloc) lenguaje C.
Publicado por: geeke en 4 Octubre 2016, 03:09 am
También puedes usar array de punteros

Código
  1. char *frases[size]
  2. for (i = 0; i < size; i++)
  3.    frases[i] = malloc(len_frase * sizeof(char));


Título: Re: Arreglo de cadenas con memoria dinámica (realloc) lenguaje C.
Publicado por: MAFUS en 4 Octubre 2016, 11:30 am
Un array de cadenas es fijo, no podrá crecer más si así lo necesita.

En unas horas te voy a pasar un código ejecutable que pone en práctica lo que te he dicho.


Título: Re: Arreglo de cadenas con memoria dinámica (realloc) lenguaje C.
Publicado por: NOB2014 en 4 Octubre 2016, 12:59 pm
Hola, que tengan un muy buen día. -
De tanto buscar encontré un Ej. que si bien estaba en c++ lo pude adaptar, este código cumple con todas mis expectativas en cuanto a lo que necesitaba sobre el tema, seria bueno que además del código de MAFUS (que deseo con muchas ansias verlo editado) alguien más de su versión de como haria lo mismo pero con otro código. -

Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. #define MAX_CHAR 30
  6.  
  7. void limpiar( void );
  8. void mostrar( char **frases, int numStrings );
  9. void liberar( char **frases, int numStrings );
  10.  
  11. int main( void ){
  12. char **frases = NULL, tmp_frase[MAX_CHAR], *p=NULL;
  13. int i, numStrings = 0, ch;
  14.  
  15. while( 1 ){
  16. limpiar();
  17. if( numStrings > 0){
  18. mostrar( frases, numStrings );
  19. }
  20. printf( "\n Introduzca una cadena (Enter para finalizar)......: ");
  21. fgets(tmp_frase, MAX_CHAR, stdin );
  22. if((p=strchr(tmp_frase, '\n'))){
  23. *p='\0';
  24. }
  25. else{
  26. while((ch = getchar()) !='\n' && ch!=EOF);
  27. }
  28.    if (strlen(tmp_frase) == 0){
  29. break;
  30.    }
  31.    frases = (char **) realloc (frases, (numStrings+1) * sizeof(char *));
  32. if( frases!=NULL ){
  33.     frases[numStrings++] = strdup(tmp_frase);
  34. }else{
  35. printf( "\n Error, no se pudo asignar memoria" );
  36. printf( "\n Pulse [Enter] para finalizar..." ); getchar();
  37. liberar( frases, numStrings );
  38. exit(1);
  39. }
  40. }
  41. liberar( frases, numStrings );
  42.  
  43. return 0;
  44. }
  45.  
  46. void limpiar( void ){
  47. system("cls||clear");
  48. }
  49.  
  50. void mostrar( char **frases, int numStrings ){
  51. int i;
  52.  
  53. printf("\n ========================= Ingresos ========================= " );
  54. for(i=0; i < numStrings; i++){
  55. printf("\n %s", frases[i]);
  56. }
  57. printf("\n ============================================================\n\n " );
  58. }
  59.  
  60. void liberar( char **frases, int numStrings ){
  61. int i;
  62. for (i=0; i < numStrings; i++){
  63. free (frases[i]);
  64. }
  65.  
  66. free (frases);
  67. }

Un fuerte abrazo para todos.


Título: Re: Arreglo de cadenas con memoria dinámica (realloc) lenguaje C.
Publicado por: MAFUS en 4 Octubre 2016, 15:44 pm
Como verás hace uso de argumentos no tan comunes en scanf, pero con ellos obtengo el dato que quiero y además me libero de \n en el buffer, todo en la misma línea.

Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. void limpiar( void ){
  5.    system("cls||clear");
  6. }
  7.  
  8. int main( void ){
  9.    size_t tam_frases = 0, i;
  10.    char **frases = NULL, salir;
  11.  
  12.    do {
  13.        limpiar();
  14.        frases = realloc(frases, (tam_frases + 1) * sizeof(char*));
  15.        if(!frases) {
  16.            fprintf(stderr, "\n\n *** Error al adquirir memoria ***\n\n");
  17.            exit(1);
  18.        }
  19.  
  20.        printf("\nIngrese frase....: ");
  21.        scanf("%m[^\n]%*c", &frases[tam_frases]);
  22.        ++tam_frases;
  23.  
  24.        printf("\nPara continuar \"S\" para finalizar \"N\"....: ");
  25.        scanf("%c%*[^\n]%*c", &salir);
  26.    } while(salir != 'n' && salir != 'N');
  27.  
  28.    printf ("\n Frases introducidas.....: ");
  29.  
  30.    for(i = 0; i < tam_frases; ++i)
  31.        printf("\n>> %s", frases[i]);
  32.  
  33.    for(i = 0; i < tam_frases; ++i)
  34.        free(frases[i]);
  35.  
  36.    return 0;
  37. }


Título: Re: Arreglo de cadenas con memoria dinámica (realloc) lenguaje C.
Publicado por: dato000 en 4 Octubre 2016, 15:55 pm
(http://images1.tickld.com/live/612826.gif)

no puedo parar de reir con ese gif, siempre que lo veo me quedo mirandolo como un idiota contento.

dato000 gracias por ocuparte del tema anterior. -
Saludos

Yo que hice??? en fin, slds

Creo que ya todo esta dicho, punteros no es mi fuerte, pero lo que tengo que añadir del codigo de MAFUS es que no es estandar esa asignación scanf("%m") y que puede variar su resultado dependiendo del compilador, pues he visto casos en los que al recibir caracter espacio o salto de linea obtiene un desbordamiento y almacena basura en un espacio de memoria aleatorio después de la primera palabra de una serie de caracteres, pues scanf se supone que es más para memoria estatica.

Aunque supongo que con la extensión del estandar y las librerias apropiadas junto con un compilador actualizado ese problema seria resuelto y se usaria como un realloc verdadero.


Título: Re: Arreglo de cadenas con memoria dinámica (realloc) lenguaje C.
Publicado por: NOB2014 en 4 Octubre 2016, 16:29 pm

Yo que hice??? en fin, slds

http://foro.elhacker.net/programacion_cc/arreglo_de_apuntadores_vs_arreglo_comun_en_lenguaje_c-t458486.0.html


Título: Re: Arreglo de cadenas con memoria dinámica (realloc) lenguaje C.
Publicado por: MAFUS en 4 Octubre 2016, 17:42 pm
La opción %m está incluida en el estándar POSIX.1-2008: http://pubs.opengroup.org/onlinepubs/9699919799/

Si se usa con %ms no recogerá toda la línea ya que el modificador %s se detiene en el primer carácter en blanco. Para ello se usa el %[^\n] que recoge toda la línea hasta el final o hasta encontrarse un carácter de nueva línea.

Como nota adicional el %*c al final de la cadena de control hace que se recoja el carácter de nueva línea pero no se asigne a ningún sitio, así se quita del buffer de entrada.