saludos
si tengo que ingresar en un vector 10 datos, por ejemplo: nombres, estos nombres tienen diferente longitud entonces tendria que poner char *nombre[10] pero a la hora de querer ingresar los datos con gets me aparecen warnings
for(i=0;i < 10;i++)
{
printf("Dame el nombre numero %d: ",i+1);
gets(nombre+i);
system("cls");
}
pero si cambio el gets por scanf de esta manera ya no me aparece y no entiendo porque
for(i=0;i < 10;i++)
{
printf("Dame el nombre numero %d: ",i+1);
scanf("%s",nombre+i);
system("cls");
}
si alguien fuera tan amable de explicarme esto se lo agradeceria mucho
Pues sin saber el tipo de variable y sin ver el warning no te podemos ayudar mucho.
Eso sí, gets está anticuada y no está recomendada su uso. En su lugar es preferible usar fgets:
http://www.cplusplus.com/reference/cstdio/fgets/
Que vendría a ser:
fgets(nombre,10,stdin); // Leer del teclado 10 caracteres y meterlos en nombre
saludos amchacon el tipo de dato es char *arreglo[10] y el warning dice:
passing argument 1 of gets from incompatible pointer type
esto en la linea
gets(nombre+i);
y tambien sale una nota que dice expected char* but argument is of type char**
gracias
*arreglo[10] es un vector de punteros... equivalente ( que no igual ) a **arreglo, es decir, "char**"
si tu en una instrucción pones "nombre + i"... el tipo resultante sigue siendo char**, que es incompatible con el que espera gets ( char* )
Para resolver eso tienes que quitar un nivel de indirección en el puntero, es decir, pasar de un puntero doble a un puntero simple.
¿De qué manera has definido la variable "arreglo"?
Sin más información es complicado darte una explicación más acertada.
gets(*nombre[i*10]);
Aunque es solo una suposicion porque sin ver la declaracion...
eferion como es eso de que *arreglo[10] es equivalente a **arreglo???
y otra duda tambien de un vector de punteros
por ejemplo si tengo
char *meses[3] ={"Enero","Febrero","Marzo"};
for(i=0;i < 3;i++)
printf("%s",*meses+i);
aqui me imprime Enero Nero Ero
pero si a la linea del printf le agrego unos parentesis
printf("%s",*(meses+i));
me imprime correctamente Enero Febrero Marzo
no entiendo por que
Cita de: m@o_614 en 17 Julio 2013, 21:32 PM
y otra duda tambien de un vector de punteros
por ejemplo si tengo
char *meses[3] ={"Enero","Febrero","Marzo"};
for(i=0;i < 3;i++)
printf("%s",*meses+i);
aqui me imprime Enero Nero Ero
pero si a la linea del printf le agrego unos parentesis
printf("%s",*(meses+i));
me imprime correctamente Enero Febrero Marzo
no entiendo por que
Si tu dibujas el mapa de memoria tendrás que lo que el vector se encuentra estructurado así ( cada letra una posición de memoria ):
'E' 'n' 'e' 'r' 'o' '\0' 'F' 'e' 'b' 'r' 'e' 'r' 'o' '\0' 'M' 'a' 'r' 'z' 'o' '\0'
y dado que "meses" es una matriz de cadena de caracteres, se cumple que:
*meses es igual a *meses + 0 y apunta al primer carácter ( 'E' ).
*meses + 1 es un desplazamiento de una posición respecto a *meses, es decir, apunta al segundo carácter ( 'n' )
*meses + 2 es un desplazamiento de dos posiciones respecto a *meses, es decir, apunta al tercer carácter ( 'e' )
...
Es decir, primero resuelves el puntero *meses y luego incrementas la posición apuntada.
Con esto, si intentas imprimir las cadenas resultantes te sale:
Enero, nero, ero, ro, o, (nada), Febrero, ebrero, ...
Sin embargo, *( meses + i ) es equivalente a moverte primero una fila y apuntar al caracter que esté en esa posición, de tal forma que:
*(meses + 0) o *meses apunta a 'E'
*(meses + 1) apunta a 'F'
*(meses + 2) apunta a 'M'
Al final el cambio viene promovido porque los paréntesis cambian el orden en el que se ejecutan las operaciones... no es lo mismo resolver un puntero doble y luego incrementar su posición que incrementar un puntero doble y resolver su posición.
Muchas gracias eferion por tus respuestas ahora ya me quedo claro, solo es cuestion de repasar las prioridades de los operadores (),[],*,+, etc...
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 ???
Cita de: m@o_614 en 18 Julio 2013, 20:23 PM
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 ???
Si, esto seria asi:
a[i] = (char *) malloc(n * sizeof(char));
Y para ingresar cada elemento con un bucle for:
int i;
for (i=0; i<5; i++)
{
scanf("%s", a[i]);
}
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
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.
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
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 )
{
// ...
}
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 (http://foro.elhacker.net/programacion_cc/duda_punteros_doblesarray_de_punteros-t378927.0.html).
Un saludo
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
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| (http://foro.elhacker.net/programacion_cc/lo_que_no_hay_que_hacer_en_cc_nivel_basico-t277729.0.html)
Un saludo