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

 

 


Tema destacado: Introducción a Git (Primera Parte)


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  scanf y gets
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: 1 [2] Ir Abajo Respuesta Imprimir
Autor Tema: scanf y gets  (Leído 7,728 veces)
m@o_614


Desconectado Desconectado

Mensajes: 389


Ver Perfil
Re: scanf y gets
« Respuesta #10 en: 19 Julio 2013, 01:13 am »

Caster si es un arreglo de punteros tengo que asignarle memoria a cada uno de los 5 punteros de char *a[5]????por eso pusiste:

Código
  1. a[i] = (char *) malloc(n * sizeof(char));


y la n para que es???

gracias


En línea

Caster


Desconectado Desconectado

Mensajes: 786


Ver Perfil WWW
Re: scanf y gets
« Respuesta #11 en: 19 Julio 2013, 01:23 am »

No llevo mucho tiempo manejando los arrays de punteros, pero si, creo que es obligatorio asignar memoria a todos los punteros. La "n" es el numero de elementos de cada array. Si el array a[0] tiene 10 elementos, n = 10, si el array a[1] tiene 12 elementos, n=12. Al hacer la reserva de memoria con un ciclo for, el numero de elementos reservados es igual para todos los arrays, si por el contrario quieres reservar distinto numero de elementos para cada array, tendras que ir uno por uno.


En línea

m@o_614


Desconectado Desconectado

Mensajes: 389


Ver Perfil
Re: scanf y gets
« Respuesta #12 en: 19 Julio 2013, 06:48 am »

entonces si por ejemplo quiero ingresarle no se... 5 nombres cualquieras:

char *a[5]
 
*(a+0)="Maria";
*(a+1)="Jose";
etc...

pero no quiero estar contando el numero de letras cada vez que tenga que asignar memoria para cada nombre, como se le asignaria la memoria??

perdona que pregunte tanto pero es que los punteros no se me dan
En línea

eferion


Desconectado Desconectado

Mensajes: 1.248


Ver Perfil
Re: scanf y gets
« Respuesta #13 en: 19 Julio 2013, 08:40 am »

entonces si por ejemplo quiero ingresarle no se... 5 nombres cualquieras:

char *a[5]
 
*(a+0)="Maria";
*(a+1)="Jose";
etc...

pero no quiero estar contando el numero de letras cada vez que tenga que asignar memoria para cada nombre, como se le asignaria la memoria??

perdona que pregunte tanto pero es que los punteros no se me dan

Los arrays de caracteres no se pueden copiar "a pelo" con el operador igual... tienes que utilizar funciones de copia ( strcpy, memcpy, etc ).

Para el caso que planteas necesitarías tener por un lado el array de cadenas de caracteres y por otro una variable que te indique cuántas posiciones están ocupadas. Esto mismo lo puedes agrupar en una estructura para que su uso sea más cómodo:

Código
  1. struct cadenas
  2. {
  3.  // De las dos opciones siguientes elige una:
  4.  
  5.  // * Si quieres gestionar la memoria dinámicamente con malloc y free
  6.  char **a;
  7.  
  8.  // * Si quieres que de la gestión de la memoria se encargue el sistema
  9.  char a[5][20];
  10.  
  11.  int index;
  12. };

De esta forma, si inicializas index a 0 y lo vas incrementando después de añadir un nombre al vector, gestionar las cadenas se vuelve una tarea bastante sencilla:

Código
  1. struct cadenas cadena;
  2.  
  3. // ...
  4.  
  5. // Nuevo elemento
  6. strcpy( cadena.a[ cadena.index ], "nombre" );
  7. cadena.index++;
  8.  
  9. // Preguntar por el numero de elementos
  10. int numero_elementos = cadena.index;
  11.  
  12. // Recorrer todos los elementos
  13. int i;
  14. for ( i=0; i<cadena.index; ++i )
  15. {
  16.  // ...
  17. }
En línea

rir3760


Desconectado Desconectado

Mensajes: 1.639


Ver Perfil
Re: scanf y gets
« Respuesta #14 en: 19 Julio 2013, 17:24 pm »

eferion como es eso de que *arreglo[10] es equivalente a **arreglo???
Porque en C en la mayoría de los casos el uso de un array resulta en la dirección en memoria de su primer elemento. El caso usual es la llamada a funcion. Por ejemplo:
Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. void imprimir(char const *texto);
  5.  
  6. int main(void)
  7. {
  8.   char linea[] = "Texto de prueba\n";
  9.  
  10.   imprimir(linea);
  11.  
  12.   return EXIT_SUCCESS;
  13. }
  14.  
  15. void imprimir(char const *texto)
  16. {
  17.   int i;
  18.  
  19.   for (i = 0; texto[i] != '\0'; i++)
  20.      putchar(texto[i]);
  21. }

Tu caso es similar: si el array se declara como "char *arreglo[10]" en expresiones su nombre resulta en un puntero al primer elemento del array ("char *arreglo[10]" ==> "char **")

----

Una ultima pregunta cuando yo declaro un arreglo de punteros char *a[5]; para despues con un for ingresarle cada uno de los elementos (a+1),(a+2),etc..., primero tengo que asignarle memoria dinamica con malloc, calloc?
No exactamente.

Antes de utilizar una variable de tipo puntero debes almacenar en esta una dirección de memoria valida, esta puede ser la retornada por la función malloc, la dirección de algún objeto o una cadena literal. Por ejemplo:
Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3.  
  4. void imprimir(char const *texto);
  5.  
  6. int main(void)
  7. {
  8.   char *nombre[3];
  9.   int i;
  10.  
  11.   nombre[0] = "Jesus\n";
  12.   nombre[1] = "Maria\n";
  13.   nombre[2] = "Jose\n";
  14.  
  15.   for (i = 0; i < 3; i++)
  16.      imprimir(nombre[i]);
  17.  
  18.   return EXIT_SUCCESS;
  19. }
  20.  
  21. void imprimir(char const *texto)
  22. {
  23.   int i;
  24.  
  25.   for (i = 0; texto[i] != '\0'; i++)
  26.      putchar(texto[i]);
  27. }
Pero en este caso con el detalle de que las cadenas literales son de solo lectura, no se puedes hacer mas con ellas ademas de imprimirlas.

----

entonces si por ejemplo quiero ingresarle no se... 5 nombres cualquieras:

char *a[5]
 
*(a+0)="Maria";
*(a+1)="Jose";
etc...

pero no quiero estar contando el numero de letras cada vez que tenga que asignar memoria para cada nombre, como se le asignaria la memoria??
A priori no hay forma. Lo mas sencillo es utilizar un array de caracteres para leer ahí cada una de las cadenas tomando nota de su longitud. Lees una cadena, reservas el espacio justo para ella y la copias ahí. Un programa de ejemplo lo puedes revisar en el tema Duda Punteros Dobles/Array de punteros.

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
m@o_614


Desconectado Desconectado

Mensajes: 389


Ver Perfil
Re: scanf y gets
« Respuesta #15 en: 21 Julio 2013, 02:51 am »

Citar
A priori no hay forma. Lo mas sencillo es utilizar un array de caracteres para leer ahí cada una de las cadenas tomando nota de su longitud. Lees una cadena, reservas el espacio justo para ella y la copias ahí.

rir3760 con esto ultimo que me acabas de decir ya me quedo claro como lo tengo que hacer, aqui dejo un pedazo del codigo que estoy haciendo, creo que era a lo que te referias con utilizar un array de caracteres y demas

Código
  1. #define MAX 5
  2.  
  3. int main()
  4. {
  5.    char *nombre[MAX];
  6.  
  7.    entrada(nombre);
  8.    return 0;
  9. }
  10.  
  11. void entrada(char *nombre[])
  12. {
  13.    char B[50];
  14.    int i;
  15.    for(i=0;i < MAX;i++)
  16.    {
  17.        printf("Dame la escuela numero %d: ",i);
  18.        gets(B);
  19.        (nombre+i) = (char*)malloc(strlen(B)sizeof(char));
  20.        strcpy(nombre+i,B);
  21.        system("cls");
  22.    }
  23. }
 

de la funcion de malloc no se si tiene algun error porque no se bien como es su estructura
« Última modificación: 21 Julio 2013, 03:06 am por m@o_614 » En línea

rir3760


Desconectado Desconectado

Mensajes: 1.639


Ver Perfil
Re: scanf y gets
« Respuesta #16 en: 21 Julio 2013, 19:29 pm »

Si vas a publicar código fuente por favor publicalo completo ya que faltan las directivas del preprocesador. En la función "entrada" faltan los operadores de indireccion y multiplicación en la llamada a malloc, no es necesario con esta la conversión explicita como tampoco multiplicar por "sizeof(char)" ya que este ultimo siempre es igual a uno. Y algunos mas.

Con los cambios compila sin problemas:
Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <string.h>
  4.  
  5. #define MAX 5
  6.  
  7. void entrada(char *nombre[]);
  8.  
  9. int main(void)
  10. {
  11.   char *nombre[MAX];
  12.  
  13.   entrada(nombre);
  14.  
  15.   return EXIT_SUCCESS;
  16. }
  17.  
  18. void entrada(char *nombre[])
  19. {
  20.   char B[50];
  21.   int i;
  22.  
  23.   for (i = 0; i < MAX; i++){
  24.      printf("Dame la escuela numero %d: ",i);
  25.      fflush(stdout);
  26.      fgets(B, 50, stdin);
  27.      *(nombre + i) = malloc(strlen(B) + 1);
  28.      strcpy(nombre[i], B);
  29.   }
  30. }

Por ultimo no deberías utilizar la función gets, el porque y mas recomendaciones en el tema |Lo que no hay que hacer en C/C++. Nivel basico|

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
Páginas: 1 [2] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
[C] Comparación entre el gets y el scanf « 1 2 »
Programación C/C++
niñoAtómico 12 5,856 Último mensaje 12 Octubre 2013, 23:24 pm
por vangodp
sustituir scanf « 1 2 »
Programación C/C++
m@o_614 11 6,539 Último mensaje 17 Octubre 2013, 17:59 pm
por Eternal Idol
problema scanf
Programación C/C++
pMV2ere 4 2,927 Último mensaje 1 Noviembre 2013, 08:44 am
por vangodp
Ayuda con el scanf n el for
Programación C/C++
Jorge LuissxX 2 1,436 Último mensaje 18 Mayo 2019, 02:07 am
por K-YreX
scanf C - borland
Programación C/C++
Carlosj1 2 1,789 Último mensaje 24 Julio 2019, 20:26 pm
por Carlosj1
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines