应用该功能后出现分段错误:!dataValida

问题描述 投票:0回答:1

在我实现 dataValida 函数后,检查 csv 列上的日期是否设置为 dd/mm/yyyy (唯一可能发生的错误如下:25/12/2010 15:01:56 或 1978|04|30 ),程序给出了分段错误。

当我运行程序时,它显示以下内容:(之前它曾经以正确的方式显示 printf,包括示例)

File opened with sucess
Parsing Concluded
Segmentation fault

我已经尝试以不同的方式重做该函数,但仍然出现相同的错误。除此之外,当我尝试执行其他功能来检查“estado”是否处于活动状态或不活动状态时,也会发生这种情况。

有人可以帮我吗?

(“contemArrobba”和“paisValido”工作得很好)

CSV 的第一行:

id;name;email;phone_number;birth_date;sex;passport;country_code;address;account_creation;pay_method;account_status
    AlícSá-Mendes;Alícia Sá-Mendes;alícsá[email protected];(351) 259 545 254;1979/11/27;F;CA279133;PT;Avenida Gabriela Guerreiro, 42518-827 Rio Maior;2016/09/10 17:34:41;debit_card;active
    GusFreitas677;Gustavo Freitas;[email protected];937 705 868;1994/03/02;M;LG587674;PT;R. de Lourenço, 478828-081 Vizela;2015/06/01 22:44:07;cash;active
    IMacedo;Isaac Macedo;[email protected];(351) 920986534;1997/03/14;M;ES723156;PT;Travessa Freitas, 8240931-629 Macedo de Cavaleiros;2013/08/04 02:56:33;cash;active
    TomNunes92;Tomás Nunes;[email protected];(351) 965 535 392;1969/09/17;M;KC256283;PT;Largo Melissa Garcia, 794837-387 Oliveira do Hospital;2016/01/24 08:25:19;credit_card;active
    DiCastro;Diogo Castro;[email protected];+351920544405;1981/07/06;M;VM134435;PT;R. Pereira, 851476-943 Porto Santo;2010/06/01 18:00:53;cash;inactive
    LorLoureiro;Lorena de Loureiro;[email protected];(351) 928 485 228;1973/04/12;F;PO057990;PT;Praça Lopes, S/N0767-827 Estremoz;2017/02/27 16:30:51;debit_card;active
    NáFreitas;Nádia Freitas;ná[email protected];(351) 963 845 006;1953/07/06;F;ME328649;PT;R. Cardoso, 907848-130 Torres Vedras;2011/02/27 04:28:24;cash;active
    LetíciOliveira;Letícia Oliveira;letí[email protected];(351) 918173761;1991/08/09;F;MW039393;PT;Av de Henriques, S/N5367-121 Leiria;2014/09/02 00:58:37;cash;active
    ÂngBarros2020;Ângela da Barros;â[email protected];938 073 906;1997/07/25;F;ES763135;PT;R. Ramos, 970241-819 Costa da Caparica;2015/10/19 23:33:54;credit_card;active
    JéssiTavares910;Jéssica Tavares;jé[email protected];+351296366330;1960/02/22;F;ZE466021;PT;Praça de Cintura Interna, 77791-070 Lixa;2015/05/18 07:54:31;cash;active
    JoMota;Jorge Mota;[email protected];932677085;1990/05/11;M;KT062866;PT;R. Eduarda Torres, 528462-868 Vendas Novas;2018/03/28 17:03:23;debit_card;active

代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef struct {
    char* id;
    char* nome;
    char* email;
    char* tele;
    char* data;
    char sexo;
    char* passaporte;
    char* pais;
    char* morada;
    char* cria_conta;
    char* pagamento;
    char* estado;
} User;

void freeUser(User *user) {
    // Esta função libera todos os campos de string alocados dinamicamente de um User->
    free(user->id);
    free(user->nome);
    free(user->email);
    free(user->data);
    free(user->passaporte);
    free(user->pais);
    free(user->morada);
    free(user->cria_conta);
    free(user->pagamento);
    free(user->estado);
}

int dataValida(const char *data) {
    if (strlen(data) != 10) return 0; // Verifica o comprimento da string

    // Verifica se os caracteres nas posições corretas são barras ('/')
    return data[2] == '/' && data[5] == '/';
}

int contemArroba(const char *str) {
    return strchr(str, '@') != NULL; // Retorna 1 se contém '@', senão retorna 0
}

int paisValido(const char* country) {
    return (strcmp(country, "PT") == 0); // Retorna 1 se o país for "PT", caso contrário 0
}

//  while (!feof(file))
User** organizaUser(FILE *file, int* n_user_out){
    char *linha = NULL;
    size_t tamanho = 0;
    ssize_t valido;

    int linhas = 0;
    User **users = NULL;
    int n_user = 0;

    while ((valido = getline(&linha, &tamanho, file)) != -1) {

        if(linhas == 0) {
            linhas++;
            continue;
        }
        //  user = realloc(users, (n_user + 1) * sizeof(User));

        char *token = strtok(linha, ";");
        if (token == NULL) continue;

        User *newUser = malloc(sizeof(User)); // Aloca memória para um novo User
        if (newUser == NULL) {
            // Tratar erro de alocação
            break;
        }
        *newUser = (User){0};
        newUser->id = strdup(token);
        
        token = strtok(NULL, ";");

        if (token == NULL) {
            free(newUser->id);
            continue;
        }

        newUser->nome = strdup(token);

        token = strtok(NULL, ";");
        if (token == NULL) {
            free(newUser->id);
            free(newUser->nome);
            continue;
        }

        newUser->email = strdup(token);

        token = strtok(NULL, ";");
        if (token == NULL || !contemArroba(newUser->email)) {
            freeUser(newUser);
            free(newUser);
            continue;
        }

        newUser->tele = strdup(token);

        token = strtok(NULL, ";");
        if (token == NULL|| !dataValida(token) ) {
            freeUser(newUser);
            free(newUser);
            continue;
        }

        newUser->data = strdup(token);

        token = strtok(NULL, ";");
        if (token == NULL) {
            freeUser(newUser);
            free(newUser);
            continue;
        }
        newUser->sexo = token[0];

        token = strtok(NULL, ";");
        if (token == NULL) {
            freeUser(newUser);
            free(newUser);
            continue;
        }
        newUser->passaporte = strdup(token);

        token = strtok(NULL, ";");
        if (token == NULL) {
            freeUser(newUser);
            free(newUser);
            continue;
        }
        newUser->pais = strdup(token);

        token = strtok(NULL, ";");
        if (token == NULL || !paisValido(newUser->pais)) {
            freeUser(newUser);
            free(newUser);
            continue;
        }
        newUser->morada = strdup(token);

        token = strtok(NULL, ";");
        if (token == NULL) {
            freeUser(newUser);
            free(newUser);
            continue;
        }    
        newUser->cria_conta = strdup(token);

        token = strtok(NULL, ";");
        if (token == NULL) {
            freeUser(newUser);
            free(newUser);
            continue;
        }   
        newUser->pagamento = strdup(token);

        token = strtok(NULL, ";");
        if (token == NULL ) {
            freeUser(newUser);
            free(newUser);
            continue;
        }            
        newUser->estado = strdup(token);

  
        User **temp = realloc(users, (n_user + 1) * sizeof(User*));
        if (temp == NULL) {
            // Se realloc falhar, libere os recursos alocados e retorne
            // Aqui você deve liberar os campos de newUser que já foram alocados
            freeUser(newUser);
            free(newUser);
            break;
        }
        users = temp;
        // Prosseguir com a atribuição dos demais campos de newUser (nome, email, data, sexo, passaporte, pais, morada, cria_conta, pagamento, status)
        users[n_user] = newUser;

        if (n_user == 11) {
            printf("Usuer 12 (estado): %s\n", newUser->estado);
        }


        n_user++;
        linhas++;

        *n_user_out = n_user;
    }

    free(linha); // Liberar a memória alocada pela getline

    return users; // Retorna o ponteiro para o array de User
} 

int main(void) {

    FILE *file = fopen("/home/rafaelsilva/Projeto/dataset/data/users.csv", "r");

    if (file == NULL) {
        printf("Couldn't open the file.\n");
        return 1;
    } else {
        printf("File opened with sucess.\n");
    }

    int num_users;

    User **users = organizaUser(file, &num_users);

    fclose(file);
    printf("Parsing Concluded.\n");

    printf("The id of the user 9301 : %s\n", users[9300]->id);    

    for (int i = 0; i < num_users; i++) {
        freeUser(users[i]);
        free(users[i]);
    }
    free(users);


    return 0;    
}
c parsing segmentation-fault
1个回答
0
投票

您的程序出现段错误:

    printf("The id of the user 9301 : %s\n", users[9300]->id);    

这是因为

users
为 NULL。
users
为 NULL,因为
dataValida()
对于日期返回 0,例如,
1979/11/27
与预期格式
data[2] == '/' && data[5] == '/';
不匹配。你可以用以下方法解决这个问题:

int dataValida(const char *data) {
    if (strlen(data) != 10) return 0;
    return data[4] == '/' && data[7] == '/';
}

在此更改之后,程序在同一位置出现段错误,但现在是因为示例输入文件包含 11 条记录,并且您尝试访问超出范围的数组 (9300 > 10)。

© www.soinside.com 2019 - 2024. All rights reserved.