I still have one precise question that my test will remember more than one date, you know how I can do that? since even using it as vector it is not yet saving
I tried to guess what you intend to do with this code and I really think you could have posted more information.
Yet for what is there and for what you asked there are some things I can add
What did you want
- declare a vector of structures
- read a value
n
which will be the total of structures to read
- allocate space for all these structures
- read Date one by one and save to vector
- call for
imprime_data()
, a type of filter that will extract k
of these n
structures according to a criterion that is dia
, mes
and ano
module 10 less than or equal to k
, and return as a vector of Data
which may have from 0 to n
elements. This is because it may be that none or all of the n
elements read meet this criterion
'Cause it didn’t work out
Data* datas;
is not actually declaring a vector. It is not even allocating space for a Data
. You’re just declaring a pointer to Data
, even though he called it datas
and then declared
datas = malloc(n * sizeof(Data));
But datas
is Data*
. C does not understand plural. malloc()
will yes allocate space for n
dates, but you won’t be able by the hand in this space.
If you need a vector with 30 Data
declaring
Data data[30];
and can access data[0]
until data[29]
. Note that using the plural is no longer and is less readable because it will use one date at a time only.
- you really want to
n
structures and then might want to declare
Data data[n];
Only it can’t. It has to be a constant number, like the 30 in the example above, or dynamically allocate space to n
structures Data
.
- another problem is
imprime_data()
: she will part k
structures Data
that meet that folkloric criterion of module 10. Only the value of k
will forever be buried within the function, since the only thing that returns from it is a pointer to a structure Data
- and
Data* teste;
declares a pointer to a Data structure. Only one. And even allocates memory to it. And you need more than one because k
values can meet your criteria, maybe none, maybe all n
imprime_data()
is a silly name, because it doesn’t print anything. It could be filtra_datas()
- and could have a
imprime_data()
even, that did this and you could use to test your program, calling at the beginning with the n
structures read and then with the k
filtered
- you did not allocate memory right nor tried to release after
- you shouldn’t read the
n
Data
keyboard and yes a file because it is much easier and safe to test and play
How could it work
I’ll explain a way to do it and you can tell me if that’s what you meant. And I’m going to leave an example program because it’s one of the most common things to err on vector structures, so it can help others
the changes
The simple way to use a structure vector is what the system prepares for every C program for example. See the main prototype()
int main(argc, char** argv)
In the case of main()
a vector of structures is created char*
, strings, with argc
strings corresponding to the parameters typed in the command line that activated the program. In your case a structure vector Data
, with n
structures will be read at the beginning, and then a vector of Data
with k
values will be created by the function imprime_data()
- because
argc
exists? It is the same problem of k
in its function imprime_data()
: one thing is to return a vector with k
structures, but another thing is to say how many are inside such a vector
- The type for the date vector is Date**
Data** data;
- print_date() will be
Data** imprime_data(int n, Data** data, int* ext);
the third value is passed by a pointer and thus can return the total of values extracted from the original vector. The vector itself will be at the address that will be returned by the function. A more elegant solution would be to write the program around such a structure:
typedef struct
{
int N;
Data** data;
} Datas;
and I think I’ve already understood why: this is unity: a vector of N structures. No news, since it’s what we have: n
* Data
at date and k
* Data
in teste
A program EXAMPLE after all
Test input file : "data.txt"
1 1 1
2 2 2
3 3 3
4 4 4
5 5 5
6 6 6
7 7 7
8 8 8
9 9 9
The program output to that file
Total de valores a ler do arquivo: 9
vai ler 9 datas de '../../../src/datas.txt'
Vetor com 9 datas:
1: 1 1 1
2: 2 2 2
3: 3 3 3
4: 4 4 4
5: 5 5 5
6: 6 6 6
7: 7 7 7
8: 8 8 8
9: 9 9 9
----------
Valor de 'k', a constante para a selecao: 4
o valor de k: 4
Vetor com 4 datas:
1: 1 1 1
2: 2 2 2
3: 3 3 3
4: 4 4 4
----------
The program
#include <stdlib.h>
typedef struct
{
int dia;
int mes;
int ano;
} Data;
typedef struct
{ // exemplo mais legível
int N;
Data** data;
} Datas;
Data** imprime_data(int,Data**,int*); // filtra
int mostra_data(int,Data**); // mostra na tela
int main(void)
{
const char* padrao = "../../../src/datas.txt";
FILE* entrada = fopen(padrao, "r");
if (entrada == NULL)
{
printf(" nao abriu '%s'\n", padrao);
return -1;
};
int n;
int res = 0;
printf("\n Total de valores a ler do arquivo: ");
while ((res = scanf("%d", &n)) != 1){}; // le n
if (res != 1) return -2;
printf(" vai ler %d datas de '%s'\n", n, padrao);
Data** data = (Data**) malloc(n * sizeof(Data*));
for (int i = 0; i < n; i++)
{
data[i] = (Data*)malloc(sizeof(Data));
res = fscanf(entrada, "%d %d %d",
&data[i]->dia,
&data[i]->mes,
&data[i]->ano); // loop para ler k valido
}; // for()
fclose(entrada);
mostra_data(n, data); // mostra o que leu
int k;
printf("\n Valor de 'k', a constante para a selecao: ");
while ((res = scanf("%d", &k)) != 1){}; // le k
printf(" o valor de k: %d\n", k);
Data** teste = imprime_data(n, data, &k);
mostra_data(k, teste); // mostra o que selecionou
// apaga os vetores
for (int i = 0; i < n; i++) free(data[i]);
free(data);
for (int i = 0; i < k; i++) free(teste[i]);
free(teste);
return 0;
}
Data** imprime_data(int n, Data** data, int* k)
{
// para facilitar aloca com n valores
Data** teste = (Data**)malloc(n * sizeof(Data*));
int ext = 0; // vai contar o total de extraidos
for (int i = 0; i < n; i++)
{
if (
data[i]->dia % 10 <= *k &&
data[i]->mes % 10 <= *k &&
data[i]->ano % 10 <= *k)
{
// ok: vai copiar esse
teste[ext] = (Data*)malloc(sizeof(Data));
*(teste[ext]) = *(data[i]); // copia esse
ext += 1; // avanca k ou vai escrever em cima
}; // if()
}; // for()
*k = ext; // vai retornar o valor
// copiou *k elementos, entre 0 e n inclusive
if (ext == 0)
{ // nao tinha nenhum
free(teste);
return NULL;
};
if (ext == n) return teste; // todos foram copiados
// libera via realloc() o que nao foi usado e retorna
return (Data**)realloc(teste, ext * sizeof(Data*));
}; // imprime_data()
int mostra_data(int N, Data** V)
{
// simplesmente mostra o vetor V de N datas na tela
printf("\nVetor com %d datas:\n\n",N);
for (int i = 0; i < N; i += 1)
{
printf("%4d: %d %d %d\n", 1 + i,
V[i]->dia, V[i]->mes, V[i]->ano
);
}; // for()
printf("----------\n");
return N;
};
Of course the file name should be passed in the command line as parameter and not buried in the program...
teste
is just a pointer to a variable of typeData
, failed to allocate memory.– anonimo
Can you give me an example? I’m a beginner and I’m lost in c kkkk
– Pedro