在我实现 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;
}
您的程序出现段错误:
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)。