'Pointers and all that [C] [closed]
well, I'm trying to create a simple program that simply print the name of a list of students, the thing is,I do all that's required but when I try to print all the elements come out as the same. It's in portuguese but I don't think it should be a problem.
Here is the program:
#include <stdlib.h>
#include <stdio.h>
typedef struct struct_t{
char * nome;
int * notas;
}DADOS_ALUNOS;
typedef struct struct_s{
DADOS_ALUNOS total_alunos;
}ALUNOS;
int main (){
ALUNOS * Classe;
DADOS_ALUNOS aluno;
int numero_alunos, quantidade_provas, i;
printf("Digite a quantidade de alunos\n");
scanf("%d", &numero_alunos);
printf("Agora, digite a quantidade de provas dadas\n");
scanf("%d", &quantidade_provas);
printf ("Total numeoro alunos: %d\n", numero_alunos);
Classe = (ALUNOS *) malloc (numero_alunos * sizeof(ALUNOS));
aluno.nome = (char *) malloc (sizeof(char) * 20);
for (i = 0; i < numero_alunos; i++){
printf("Digite o nome do aluno\n");
scanf("%s", aluno.nome);
//printf("O que está contindo na variavael temporaria: %s", aluno.nome);
Classe[i].total_alunos.nome = (char *) malloc (sizeof(aluno.nome));
Classe[i].total_alunos.nome = aluno.nome;
//printf("O que está contindo na variavael : %s", Classe[i].total_alunos.nome);
//free(aluno.nome);
}
for (i = 0; i < numero_alunos; i++){
printf("Nome: %s\n", Classe[i].total_alunos.nome);
}
return 0;
}
any suggestions are welcome.
Solution 1:[1]
In these statements:
Classe[i].total_alunos.nome = (char *) malloc (sizeof(aluno.nome));
Classe[i].total_alunos.nome = aluno.nome;
there are produced memory leaks.
At first memory was allocated and its address was assigned to the pointer Classe[i].total_alunos.nome
and then the pointer was reassigned with the address of the memory allocated before the for loop:
Classe[i].total_alunos.nome = aluno.nome;
At least you need to use the string function strcpy
like:
strcpy( Classe[i].total_alunos.nome, aluno.nome );
provided that you allocated enough space for the array pointed to by the pointer Classe[i].total_alunos.nome
because in this allocation
Classe[i].total_alunos.nome = (char *) malloc (sizeof(aluno.nome));
you allocating memory only for pointer. That is sizeof(aluno.nome )
is equal to sizeof( char * )
.
However pay attention to that there will be still a memory leak because the memory pointed to by the pointer aluno.nome
was not freed.
There is no great sense to declare an object of the type DADOS_ALUNOS
:
DADOS_ALUNOS aluno;
and then dynamically allocate memory:
aluno.nome = (char *) malloc (sizeof(char) * 20);
Instead you could declare just a character array as for example:
char nome[20];
and use this array in the for loop:
scanf( " %19[^\n]", nome );
^^^^^^^^^^
Solution 2:[2]
Several issues.
First, change
Classe[i].total_alunos.nome = (char *) malloc (sizeof(aluno.nome));
to
Classe[i].total_alunos.nome = malloc( strlen( aluno.nome ) + 1 );
As of C89 casts on malloc
are unnecessary, and under the C89 standard can suppress a useful diagnostic.
The type of the expression aluno.nome
is char *
, so sizeof( aluno.nome )
gives you the size of the pointer, not the size of the buffer it points to. Use strlen
to get the length of the input string, then add 1 to account for the terminator.
Next, change
Classe[i].total_alunos.nome = aluno.nome;
to
strcpy( Classe[i].total_alunos.nome, aluno.nome );
The =
operator is not defined to copy the contents of one array to another - in order to do that you have to use a library function like strcpy
or memcpy
, or copy elements individually in a loop. All you are doing here is assigning the pointer value stored in aluno.nome
to Classe[i].total_alunos.nome
, and in the process you're losing the reference to the memory you allocated with malloc
, leading to a memory leak.
Finally, instead of using scanf
to read string input, use fgets
- it makes it easier to prevent a buffer overrun:
printf("Digite o nome do aluno\n");
fgets( aluno.nome, 20, stdin );
This will read at most 19 characters into aluno.nome
and terminate the string. You can do that with scanf
as well:
scanf( "%19s", aluno.nome );
but the lengths have to be hardcoded in the conversion specifier; you can't use *
to specify a length at runtime like you can with printf
.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | halfer |
Solution 2 | John Bode |