No puedo entender qué está mal con mi implementación c de: asignar dinámicamente una matriz de estructura dentro de una función para usar en otras funciones.

El problema es que mi .exe deja de funcionar después de leer la primera estructura (que se lee correctamente).

La estructura:

struct student
{
    char name1[30], name2[30];
    float grade;
};

La función:

void read(int *n, struct student **a)
{
    if(scanf(" %d", n) == 1)
    {
        int i;
        *a=(struct student*)malloc((*n)*sizeof(struct student*));
        for(i=0; i<*n; i++)
            scanf("%29s %29s %f",(*a)[i].name1, (*a)[i].name2, &(*a)[i].grade);
            //it stops working right after this line is executed
    }
}

Principal:

int main()
{
    int n;
    struct student *a;
    read(&n, &a);
    return 0;
}

Advertencias:

format '%s' expects argument of type 'char *', but argument 2 has type 'char (*)[30]' [-Wformat=]|

format '%s' expects argument of type 'char *', but argument 3 has type 'char (*)[30]' [-Wformat=]|

Usar una + i en lugar de una [i] no cambia nada. Soy consciente de que & (* a) significa a, pero quería dejar todo lo más claro posible. Siento que hay algo obviamente mal en mi asignación dinámica que me falta. Leí tantas preguntas aquí, pero nada parece resolver mi problema. ¡Gracias por tu tiempo!

EDITAR 1: cambié el código a las sugerencias:

scanf ("% 29s% 29s% f", a [i] .name1, a [i] .name2, a [i] .grade);

Y ahora aparece el siguiente error en su lugar.

Error:

error: solicitud de miembro 'nombre1' en algo que no es una estructura o unión

EDITAR 2: entonces, la línea:

 scanf("%29s %29s %f",*a[i].name1, *a[i].name2, *a[i].grade);

Da el error:

solicitud de miembro 'nombre1' en algo que no es una estructura o unión

Y la linea:

scanf("%29s %29s %f",(*a)[i].name1, (*a)[i].name2, (*a)[i].grade);

Choques.

EDITAR 3:

scanf("%29s %29s %f", (*a)[i].name1, (*a)[i].name2, &(*a)[i].grade);

Trabajos.

-2
Surreal Everything 12 ene. 2017 a las 17:35
Esto tiene muy poco que ver con la programación dinámica
 – 
user3528438
12 ene. 2017 a las 17:37
3
Es un problema sobre prioridad de operador . Usando su código, la expresión *a[i] es igual a *(a[i]) lo cual no es correcto.
 – 
Some programmer dude
12 ene. 2017 a las 17:39
1
Esta es la primera vez, y con suerte la última vez, que he visto a alguien escribir & (* a).
 – 
jarmod
12 ene. 2017 a las 17:40
1
Esto: scanf("%d",&(*n)); da miedo, por supuesto debería ser if(scanf(" %d", n) == 1), no es necesario eliminar la referencia y luego tomar la dirección cuando tenga la dirección para empezar . También la E / S puede fallar, y es muy bueno tener ese espacio antes de %d.
 – 
unwind
12 ene. 2017 a las 17:41

1 respuesta

La mejor respuesta

Aquí

*a=(struct student*)malloc((*n)*sizeof(struct student*));
                                                   ^^^^^

Asigna espacio para *n punteros a struct student pero parece que realmente desea asignar espacio para *n struct student.

Parece que quieres:

*a=malloc((*n)*sizeof(struct student));

También observe que *a[i] es lo mismo que *(a[i]) pero probablemente quiera (*a)[i]. Entonces necesitas algo como:

scanf("%29s %29s %f", (*a)[i].name1, (*a)[i].name2, &(*a)[i].grade);

Observe que necesita & delante de (*a)[i].grade pero no los otros dos lugares porque los otros dos son matrices.

Como lo menciona @unwind en un comentario: scanf es incorrecto

Éste

scanf("%d",&(*n));

Debe ser

scanf("%d", n);

Y luego también debe verificar el valor de retorno, como

if (scanf("%d", n) != 1)
{
    // Add error handling here
    ....
}
1
4386427 12 ene. 2017 a las 18:55
1
Dios mío, otra mentira.
 – 
Peter - Reinstate Monica
12 ene. 2017 a las 17:52
Gracias por el comentario. * a = malloc ((* n) * tamaño de (estructura estudiante)); no cambia nada, pero entiendo lo que dices, y lo mantuve cambiado. Además, cambié el original: & (* (a [i])) al error que genera una [i] y luego a su mencionado * (a) [i] y ahora se bloquea nuevamente.
 – 
Surreal Everything
12 ene. 2017 a las 18:27
*(a)[i] no es lo mismo que (*a)[i], que es lo que recomienda la respuesta.
 – 
Mgetz
12 ene. 2017 a las 18:30
Lo siento. Cometí un error tipográfico en el comentario, pero el código real es como dijiste: "scanf ("% 29s% 29s% f ", (* a) [i] .name1, (* a) [i] .name2, ( * a) [i] .grade); " y se estrella.
 – 
Surreal Everything
12 ene. 2017 a las 18:37
Le sugiero que compile con el desinfectante de direcciones activado. Debería dejar muy claro el motivo del accidente, aunque como parte de un accidente.
 – 
Mgetz
12 ene. 2017 a las 18:47