Stack Overflow em Português Asked on November 5, 2021
Estou tentando fazer uma função que me retorne uma data de acordo com um inteiro e sempre a aparece o erro:
exited, segmentation fault
O código que criei é basicamente este:
#ifndef DATA_H
#define DATA_H
typedef struct{
int dia;
int mes;
int ano;
}Data;
Data imprime_data(Data *datas, int n, int k);
#endif
#include <stdio.h>
#include <stdlib.h>
#include "data.h"
int main (void){
Data * datas;
int n;
scanf ("%d", &n);
datas = malloc(n * sizeof(Data));
for(int i = 0; i < n; i++){
scanf("%d %d %d", &datas[i].dia, &datas[i].mes, &datas[i].ano);
}
int k;
scanf("%d", &k);
Data * teste;
* teste = imprime_data(datas, n, k);
for(int i = 0; i < n; i++){
printf("%d %d %d", teste[i].dia, teste[i].mes, teste[i].ano);
}
return 0;
}
#include "data.h"
Data imprime_data(Data *datas, int n, int k){
Data * teste;
for(int i = 0; i < n; i++){
if(datas[i].dia % 10 <= k && datas[i].mes % 10 <= k && datas[i].ano % 10 <= k){
teste[i] = datas[i];
}
}
return *teste;
}
ainda tenho uma dúvida preciso que o meu teste guarde na memoria mais de uma data, sabe como posso fazer isso? já que mesmo usando ele como vetor ele ainda não está guardando
Tentei adivinhar o que pretende fazer com esse código e eu acho mesmo que você podia ter postado mais informação.
No entanto pelo que está lá e pelo que perguntou tem umas coisas que posso acrescentar
n
que vai ser o total de estruturas a lerimprime_data()
, um tipo de filtro que vai extrair k
dessas n
estruturas de acordo com um critério que é dia
, mes
e ano
módulo 10 menores ou iguais a k
, e retornar como um vetor de Data
que pode ter de 0 a n
elementos. Isso porque pode ser que nenhum ou todos os n
elementos lidos satisfaçam a esse critério Data* datas;
não está de fato declarando um vetor. Sequer está alocando espaço para uma Data
. Só está declarando um ponteiro para Data
, muito embora tenha até chamado de datas
e depois declarado
datas = malloc(n * sizeof(Data));
Mas datas
é Data*
. C não entende plural. malloc()
vai sim alocar espaço para as n
datas, mas você não vai poder por a mão nesse espaço.
Se você precisa de um vetor com 30 Data
declara
Data data[30];
e pode acessar data[0]
até data[29]
. Note que usar o plural não é mais e sim menos legível porque vai usar uma data por vez apenas.
n
estruturas e então podia querer declarar Data data[n];
Só que não pode. Tem que ser um número constante, como o 30 no exemplo acima, ou então alocar dinamicamente espaço para n
estruturas Data
.
imprime_data()
: ela vai separar k
estruturas Data
que atendam àquele critério folclórico do módulo 10. Só que o valor de k
vai ficar para sempre enterrado dentro da função, já que a única coisa que retorna dela é um ponteiro para uma estrutura Data
Data* teste;
declara um ponteiro para uma estrutura Data. Só uma. E sequer aloca memória para ela. E você precisa de mais de uma porque k
valores podem atender ao seu critério, talvez nenhum, talvez todos os n
imprime_data()
é um nome bobinho, porque ela não imprime nada. Podia ser filtra_datas()
imprime_data()
mesmo, que fizesse isso e você podia usar pra testar seu programa, chamando no início com as n
estruturas lidas e depois com as k
filtradasn
Data
do teclado e sim de um arquivo porque é muito mais fácil e seguro de testar e reproduzirVou te explicar uma maneira de fazer isso e pode me dizer se era o que pretendia. E vou deixar um programa de exemplo porque é uma das coisas mais comuns de se errar em vetores de estruturas, então pode ajudar a outros
A maneira simples de usar um vetor de estruturas é a que o sistema prepara para todo programa C por exemplo. Veja o protótipo de main()
int main(argc, char** argv)
No caso de main()
é criado um vetor de estruturas char*
, strings, com argc
strings correspondendo aos parâmetros digitados na linha de comando que ativou o programa. No seu caso um vetor de estruturas Data
, com n
estruturas será lido no início, e depois um vetor de Data
com k
valores será criado pela função imprime_data()
argc
existe? É o mesmo problema de k
em sua função imprime_data()
: uma coisa é retornar um vetor com k
estruturas, mas outra coisa é dizer quantas tem dentro do tal vetor Data** data;
Data** imprime_data(int n, Data** data, int* ext);
o terceiro valor é passado por um ponteiro e assim pode retornar o total de valores extraídos do vetor original. O vetor em si vai estar no endereço que será retornado pela função. Uma solução mais elegante seria escrever o programa em torno de uma estrutura assim:typedef struct
{
int N;
Data** data;
} Datas;
e acho que já deu pra entender porque: essa é a unidade: um vetor de N estruturas. Sem novidades, já que é o que temos: n
* Data
em data e k
* Data
em teste
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
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
----------
#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: %dn", 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:nn",N);
for (int i = 0; i < N; i += 1)
{
printf("%4d: %d %d %dn", 1 + i,
V[i]->dia, V[i]->mes, V[i]->ano
);
}; // for()
printf("----------n");
return N;
};
Claro que o nome do arquivo deveria ser passado na linha de comando como parâmetro e não estar enterrado no programa...
Answered by arfneto on November 5, 2021
O maior problema é que não está alocando memória para o array chamado teste
na função secundária, então estoura a memória.
E claro, eu liberei essa memória e a outra alocada. Para um exercício não causa problema, mas em outros código pode causar, então acostume fazer certo.
Mas o retorno da função também está errado e um bom compilador com as configurações certas nem deixaria compilar. Você quer retornar um array, então tem que retornar um ponteiro e não a estrutura simples.
Tem um outro problema, esse novo array terá um tamanho menor e você não pode tentar imprimí-lo inteiro. Coloquei mais um parâmetro para ter essa informação retornada. Pra falar a verdade eu faria de forma muito diferente disso, mas não sei o que o exercício pede de fato.
E claro, organizei o código.
#include <stdio.h>
#include <stdlib.h>
typedef struct {
int dia;
int mes;
int ano;
} Data;
Data *imprime_data(Data *datas, int n, int k, int *total) {
Data *teste = malloc(n * sizeof(Data));
*total = 0;
for (int i = 0; i < n; i++) {
if (datas[i].dia % 10 <= k && datas[i].mes % 10 <= k && datas[i].ano % 10 <= k) {
teste[i] = datas[i];
(*total)++;
}
}
return teste;
}
int main() {
int n;
scanf ("%d", &n);
Data *datas = malloc(n * sizeof(Data));
for (int i = 0; i < n; i++) scanf("%d %d %d", &datas[i].dia, &datas[i].mes, &datas[i].ano);
int k;
scanf("%d", &k);
int total = 0;
Data *teste = imprime_data(datas, n, k, &total);
for (int i = 0; i < total; i++) printf("%d %d %d", teste[i].dia, teste[i].mes, teste[i].ano);
free(datas);
free(teste);
}
Veja funcionando no ideone. E no repl.it. Também coloquei no GitHub para referência futura.
Sugiro pegar exercícios mais simples até poder resolver por conta própria. Não pule conceitos, não tente fazer algo com mecanismos que ainda não domina.
Answered by Maniero on November 5, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP