Problema con scanf en un *char en estructura

Iniciado por dato000, 10 Diciembre 2013, 14:56 PM

0 Miembros y 1 Visitante están viendo este tema.

dato000

Buenas, muchas sigo con problemas mediante punteros, es un problema interesante, me interesa saber porque ocurre este error, y no encuentro nada relacionado con el tema, por favor una ayudita.

Al momento de escanear el *char mes, me sale un error de Segmentation Fault, y es que eso ocurre con el scanf de esa cadena, no se porque carajos ocurre eso, conceptualmente. no se como corregir ese error y no se porque tanto dilema con ese apuntador, que ni siquiera esa usandose en la otra estructura, dejandolo independiente de la otra estructura anidada "fecha"


#include <stdio.h>
#include <stdlib.h>

struct fecha
{
    int d, m, a;
    float x;
};

struct dato
{
    char* mes;
    struct fecha* r;
}t ;

int main()
{
    struct dato nuevoDato;
    printf("++++++****FECHAS****++++++\n\n");
    printf("Digite La fecha:  \n");
    printf("Día:  ");
    scanf("%d", &nuevoDato.r->d);

    printf("Mes Letras:  ");
    scanf("%s", &nuevoDato.mes);

    printf("Mes número:  ");
    scanf("%d", &nuevoDato.r->m);

    printf("Año:  ");
    scanf("%d", &nuevoDato.r->a);

    printf("Número coma flotante:  ");
    scanf("%f", &nuevoDato.r->x);


    printf("El día anotado es:  %d\n", nuevoDato.r->d);
    printf("El mes letras anotado es:  %s\n", &nuevoDato.mes);
    printf("El mes número anotado es:  %d\n", nuevoDato.r->m);
    printf("El año anotado es:  %d\n", nuevoDato.r->a);
    printf("El número coma flotante anotado es:  %.2f\n", nuevoDato.r->x);
    return 0;
}



me sale esto:



Poco a poco avanzo en el tema de punteros... :silbar: :silbar:



amchacon

El error se debe a:

scanf("%s", &nuevoDato.mes);

Estás metiendo un texto entero en la dirreción de la variable char*, pero claro solo tiene un byte asi que el resto de caracteres cogen otras zonas de la memoria, probablemente estes modificando otras variables sin darte cuenta... Que haya llegado a hacer segmentation fault ha sido lo mejor, si no estarías como un loco mirando porque las variables cambian de valor de repente.

Prueba a reservar memoria estática previa:
struct dato
{
  char mes[300];
  struct fecha* r;
}t ;


Dado que un array se representa por la dirreción de su primer elemento, no necesitas el operador &:
scanf("%s",nuevoDato.mes);

Aunque yo haría:

fscanf(nuevoDato.mes,299,stdin); // stdin simboliza el teclado

Así te asegura que no se lean más de 300 caracteres.
Por favor, no me manden MP con dudas. Usen el foro, gracias.

¡Visita mi programa estrella!

Rar File Missing: Esteganografía en un Rar

dato000

#2
lo raro es que el enunciado del ejercicio indica que la asignación *char deberia funcionar, pues en el capitulo indica que el uso de punteros a cadenas maneja el *char como un espacio de memoria para arreglos.

Pensaba que era algo así, entonces lo indicado es siempre usar un arreglo para estas caracteristicas  y no confiarse tanto del apuntador, vale muchas gracias amchacon

Una ultima cosa más, implementando tu solución encontre lo siguiente

1. En la estructura, debo seguir apuntando a un arreglo:


struct dato
{
  char* mes[300];
  struct fecha* r;
}t ;


Y para leer un máximo de caracteres con scanf como en el ejemplo que dejaste mes[300]


scanf("%300s", nuevoDato.mes);


La verdad estoy más acostumbrado a usar scanf  :xD :xD


Otra cosa sobre el fscanf es que, intente usarlo con demás variables, pero solo me funciona con archivos presentes, como puedo leer una de las otras variables de las estructuras??



amchacon

fscanf? Quería decir fgets, con tanto scanf se me fue la pinza :silbar:

Cita de: dato000 en 10 Diciembre 2013, 16:49 PMUna ultima cosa más, implementando tu solución encontre lo siguiente

1. En la estructura, debo seguir apuntando a un arreglo:


struct dato
{
  char* mes[300];
  struct fecha* r;
}t ;


Y para leer un máximo de caracteres con scanf como en el ejemplo que dejaste mes[300]


scanf("%300s", nuevoDato.mes);


La verdad estoy más acostumbrado a usar scanf  :xD :xD
Pues no la conocía, pero si te funciona puede sustituir al fgets.

Cita de: dato000 en 10 Diciembre 2013, 16:49 PMOtra cosa sobre el fscanf es que, intente usarlo con demás variables, pero solo me funciona con archivos presentes, como puedo leer una de las otras variables de las estructuras??
Como te dije, creía que había puesto fgets. fscanf sería:

fscanf(stdin,"%d",&valor); // recordemos que stdin es el fichero del teclado

Pero para eso usas scanf y escribes menos.

Por favor, no me manden MP con dudas. Usen el foro, gracias.

¡Visita mi programa estrella!

Rar File Missing: Esteganografía en un Rar

rir3760

Cita de: dato000 en 10 Diciembre 2013, 14:56 PMAl momento de escanear el *char mes, me sale un error de Segmentation Fault, y es que eso ocurre con el scanf de esa cadena, no se porque carajos ocurre eso
El problema principal no se debe a scanf sino a las direcciones que le pasas a esta. Cuando declaras una variable local:
struct dato nuevoDato;
Esta inicia con un valor no definido o "basura". Si se trata de estructuras esto aplica a sus campos y el programa reventara tan pronto trates de utilizar uno de los punteros.

Para solucionarlo debes primero reservar dos bloques de memoria y almacenar la dirección de estos en los campos de la variable "nuevoDato":
nuevoDato.mes = malloc(1024);
nuevoDato.r = malloc(sizeof *nuevoDato.r);


También debes eliminar la variable "t" ya que no la utilizas en el programa. El programa con los cambios y algunos mas:
#include <stdio.h>
#include <stdlib.h>

struct fecha
{
   int d, m, a;
   float x;
};

struct dato
{
   char *mes;
   struct fecha* r;
};

int main(void)
{
   struct dato nuevoDato;
   
   nuevoDato.mes = malloc(1024);
   nuevoDato.r = malloc(sizeof *nuevoDato.r);
   
   printf("++++++****FECHAS****++++++\n\n");
   printf("Digite La fecha:  \n");
   printf("Dia:  ");
   scanf("%d", &nuevoDato.r->d);

   printf("Mes Letras:  ");
   scanf("%s", nuevoDato.mes);

   printf("Mes numero:  ");
   scanf("%d", &nuevoDato.r->m);

   printf("año:  ");
   scanf("%d", &nuevoDato.r->a);

   printf("Numero coma flotante:  ");
   scanf("%f", &nuevoDato.r->x);

   printf("El dia anotado es:  %d\n", nuevoDato.r->d);
   printf("El mes letras anotado es:  %s\n", nuevoDato.mes);
   printf("El mes numero anotado es:  %d\n", nuevoDato.r->m);
   printf("El año anotado es:  %d\n", nuevoDato.r->a);
   printf("El numero coma flotante anotado es:  %.2f\n", nuevoDato.r->x);
   
   return 0;
}


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

dato000

gracias por sus respuestas gente, todavia no me he metido con reserva dinamica de memoria, pero muy valiosa la info que me dejaste.

Ya que uds saben, entonces el mejor para leer entradas de teclado seria fgets?? o fscanf??? ambas me parecen buenas opciones, pero quisiera saber opiniones expertas.



amchacon

Cita de: dato000 en 10 Diciembre 2013, 20:53 PM
gracias por sus respuestas gente, todavia no me he metido con reserva dinamica de memoria, pero muy valiosa la info que me dejaste.

Ya que uds saben, entonces el mejor para leer entradas de teclado seria fgets?? o fscanf??? ambas me parecen buenas opciones, pero quisiera saber opiniones expertas.
fgets para cadenas de texto y scanf para todo lo demás.

PD: Sí, scanf sin f.
Por favor, no me manden MP con dudas. Usen el foro, gracias.

¡Visita mi programa estrella!

Rar File Missing: Esteganografía en un Rar

dato000

Cita de: amchacon en 10 Diciembre 2013, 21:50 PM
fgets para cadenas de texto y scanf para todo lo demás.

PD: Sí, scanf sin f.

oh muchas gracias lo tendre en cuenta, me di cuenta que fscanf y scanf son casi lo mismo XD, pero fgets si captura toda una cadena de texto incluyendo espacios, aunque termina cada cadena con un "\n" pero no es nada dificil maneja eso.

muchas gracias  ;-) ;-)