scanf y gets

Iniciado por m@o_614, 17 Julio 2013, 02:37 AM

0 Miembros y 3 Visitantes están viendo este tema.

m@o_614

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:

a[i] = (char *) malloc(n * sizeof(char));

y la n para que es???

gracias

Caster

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.

m@o_614

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

eferion

Cita de: m@o_614 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

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:


struct cadenas
{
  // De las dos opciones siguientes elige una:

  // * Si quieres gestionar la memoria dinámicamente con malloc y free
  char **a;

  // * Si quieres que de la gestión de la memoria se encargue el sistema
  char a[5][20];

  int index;
};


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:


struct cadenas cadena;

// ...

// Nuevo elemento
strcpy( cadena.a[ cadena.index ], "nombre" );
cadena.index++;

// Preguntar por el numero de elementos
int numero_elementos = cadena.index;

// Recorrer todos los elementos
int i;
for ( i=0; i<cadena.index; ++i )
{
  // ...
}

rir3760

Cita de: m@o_614 en 17 Julio 2013, 21:25 PMeferion 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:
#include <stdio.h>
#include <stdlib.h>

void imprimir(char const *texto);

int main(void)
{
   char linea[] = "Texto de prueba\n";
   
   imprimir(linea);
   
   return EXIT_SUCCESS;
}

void imprimir(char const *texto)
{
   int i;
   
   for (i = 0; texto[i] != '\0'; i++)
      putchar(texto[i]);
}


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 **")

----

Cita de: m@o_614 en 18 Julio 2013, 20:23 PMUna 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:
#include <stdio.h>
#include <stdlib.h>

void imprimir(char const *texto);

int main(void)
{
   char *nombre[3];
   int i;
   
   nombre[0] = "Jesus\n";
   nombre[1] = "Maria\n";
   nombre[2] = "Jose\n";
   
   for (i = 0; i < 3; i++)
      imprimir(nombre[i]);
   
   return EXIT_SUCCESS;
}

void imprimir(char const *texto)
{
   int i;
   
   for (i = 0; texto[i] != '\0'; i++)
      putchar(texto[i]);
}

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.

----

Cita de: m@o_614 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??
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
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

#15
CitarA 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


#define MAX 5

int main()
{
   char *nombre[MAX];

   entrada(nombre);
   return 0;
}

void entrada(char *nombre[])
{
   char B[50];
   int i;
   for(i=0;i < MAX;i++)
   {
       printf("Dame la escuela numero %d: ",i);
       gets(B);
       (nombre+i) = (char*)malloc(strlen(B)sizeof(char));
       strcpy(nombre+i,B);
       system("cls");
   }
}
 

de la funcion de malloc no se si tiene algun error porque no se bien como es su estructura

rir3760

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:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX 5

void entrada(char *nombre[]);

int main(void)
{
   char *nombre[MAX];
   
   entrada(nombre);
   
   return EXIT_SUCCESS;
}

void entrada(char *nombre[])
{
   char B[50];
   int i;
   
   for (i = 0; i < MAX; i++){
      printf("Dame la escuela numero %d: ",i);
      fflush(stdout);
      fgets(B, 50, stdin);
      *(nombre + i) = malloc(strlen(B) + 1);
      strcpy(nombre[i], B);
   }
}


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
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