Error exited, Segmentation fault in C

Asked

Viewed 342 times

1

I’m trying to make a function that returns me a date according to an integer and always appears the error:

exited, Segmentation fault

The code I created is basically this:

#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;


}
  • teste is just a pointer to a variable of type Data, failed to allocate memory.

  • Can you give me an example? I’m a beginner and I’m lost in c kkkk

2 answers

1


The biggest problem is that it is not allocating memory to the array called teste in the secondary function, then burst the memory.

And of course, I released this memory and the other one allocated. For one exercise does not cause problem, but in other code can cause, so get used to do right.

But the return of the function is also wrong and a good compiler with the right settings would not even let compile. You want to return a array, then it has to return a pointer and not the simple structure.

There’s another problem, this new one array will have a smaller size and you can not try to print it whole. I put another parameter to have this information returned. To tell you the truth I would do it very differently than that, but I don’t know what the exercise actually calls for.

And of course, I organized the code.

#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);
}

Behold working in the ideone. And in the repl it.. Also put on the Github for future reference.

I suggest you get some simple exercises until you can figure it out on your own. Don’t skip concepts, don’t try to do something with mechanisms you haven’t mastered yet.

  • Thank you very much for the answer and the advice! but 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 don’t know, because there are millions of ways to do this, and for me it is already doing, if it is not, only you know what you want to do, and programming is before anything else understand the problem completely.

0

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

  • when you declare

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...

Browser other questions tagged

You are not signed in. Login or sign up in order to post.