提问人:HelpMe 提问时间:11/15/2023 最后编辑:HelpMe 更新时间:11/15/2023 访问量:87
应用函数后出现分段错误:!dataValida
Segmentation fault after aplying the function : !dataValida
问:
在我实现函数 dataValida 后,该函数检查 csv 列上的日期是否设置为 dd/mm/yyyy(唯一可能发生的错误如下:25/12/2010 15:01:56 或 1978|04|30),程序给出分段错误。
当我运行程序时,它显示以下内容:(在此之前,它曾经以正确的方式显示printf,包括示例)
File opened with success
Parsing Concluded
Segmentation fault
我已经尝试以不同的方式重做该函数,但它仍然出现相同的错误。除此之外,当我尝试执行其他功能来检查“estado”是处于活动状态还是非活动状态时,也会发生这种情况。
谁能帮我?
(“contemArrobba”和“paisValido”工作正常)
法典:
#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;
}
答:
1赞
Allan Wind
11/15/2023
#1
您的程序在行上出现段错误:
printf("The id of the user 9301 : %s\n", users[9300]->id);
这是因为为 NULL。 为 NULL,因为返回日期为 0,例如,这与预期的格式不匹配。您可以使用以下方法解决此问题:
users
users
dataValida()
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)。如果我将 print 语句更改为:
printf("The id of the user 9301 : %s\n", users[num_users-1]->id);
它现在可以正确打印出最后一条记录的 ID。
奖励:您可以通过添加以下内容来修复内存泄漏:
free(user->tele)
freeUser()
void freeUser(User *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); free(user->tele); }
评论
0赞
HelpMe
11/16/2023
谢谢艾伦!它真的帮助了我很多:)
0赞
Allan Wind
11/16/2023
别客气。如果这回答了您的问题,请单击它旁边的复选标记来接受它。
评论
if
dataValida()
token