GNL - get_next_line 42

Descrição

O get_next_line é um programa que retornar uma linha do arquivo lido.

O que sei até agora:

- File Descriptor (FD)

O file descriptor segundo o wikipedia é um indicador abstrato para indicar um arquivo.

No GNL iremos usar a função read() da biblioteca <unistd.h>.

read()

protótipo:

1
ssize_t	read(int fd, void *buf, size_t count);
Anotações gerais.

[22/08/21]

O valor de fd é recebido na main.c através do função open(), seria algo do tipo:

fd = open("arquivo", O_RDONLY) e o valor recebido de fd seria passado para o get_next_line

minhas principais dúvidas são:

  • Como saber que é a próxima linha? [check: 24/08]
  • a variável estática é usada para pegar a próxima linha? [check: 24/08]

[24/08/21]

Descobri que a func read() volta a ler de onde o carrinho de leitura parou, essa era uma das preocupações que eu tive, de como eu controlaria para saber qual é a próxima linha.

Criei a função que lê a primeira parte e salva no buffer.

*Não funcionou como deveria

[27/08/21]

Como tinha alguns trabalhos que precisavam ser entregues na faculdade, não consegui retornar antes para o GNL.


Mostrar código
1
2
3
4
5
6
7
while (!ft_strchr(save, '\n'))
{
r = read(fd, buffer, BUFFER_SIZE);
aux = save;
save = ft_strjoin(save, buffer);
free(aux);
}

O protótipo funcionou, a ideia que eu tive é ir guardando o buffer até achar o '\n'assim que ele acha o '\n' na string static que eu guardo tudo que o buffer recebe, o while termina e eu retorno até o '\n' e em seguida guardo o restante na própria string static.

[06/09/21]

Aparentemente tudo funcionando, exceto pelo TIME OUT dado nos testes em que se tem um arquivo sem linha e muito grandes, mas vou tentar resolver assim que der.


Linha geral:

A função read_file é autodescritiva, vou receber como parâmetro o fd do arquivo e a variavel estática. Nela eu crio um buffer com o tamnaho do BUFFER_SIZE e uso a função read() pra ler o arquivo até encontrar o final dele - que seria retornado 0 - ou até encontrar uma linha (\n) , caso ocorra algum erro, o laço de repetição é parado, libero a variavel buffer que tinha mallocado e retorno NULL, caso contrário, uso a função ft_strjoin() para juntar o conteúdo de backup com o buffer.

Mostrar código
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
static char	*read_file(int fd, char *backup)
{
char *buffer;
int read_bytes;
buffer = malloc(sizeof(char) * (BUFFER_SIZE + 1));
if (!buffer)
return (NULL);
read_bytes = 1;
while (read_bytes > 0 && !ft_strchr(backup, '\n'))
{
read_bytes = read(fd, buffer, BUFFER_SIZE);
if (read_bytes < 0)
break ;
buffer[read_bytes] = '\0';
backup = ft_strjoin(backup, buffer);
}
free(buffer);
if (read_bytes < 0)
return (NULL);
else
return (backup);
}

A função get_line() faz o que o nome já diz, ela pega a linha. Como parâmetro ainda vamos usar o backup, faço uma verificação se a backup não está com o primeiro caracter como null byte ('\0'), percorro ela inteira até achar uma ('\n') ou o final dela, crio com o malloc uma string com o tamanho que li + 2 espaços, pra caso haja um \n , eu coloque ele e logo em seguida o (\0) e retorno essa linha.

Mostrar código
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
   static char	*get_line(char	*backup)
{
char *line;
size_t size;

if (!*backup)
return (NULL);
size = 0;
while (backup[size] && backup[size] != '\n')
size++;
line = (char *)malloc(sizeof(char) * (size + 2));
if (!line)
return (NULL);
ft_strlcpy(line, backup, size + 1);
if (backup[size] == '\n')
line[size++] = '\n';
line[size] = '\0';
return (line);
}

A última função é a remove_read_line() que remove a linha lida. Ela recebe como parâmetro a static , nela eu procuro até a quebra de linha \n ou até chegar no final, se chega no final, dou um free na variável e retorno NULL , senão, eu malloco uma nova variavel com o (tamanho total de backup, menos o tamanho da linha), copio o restante de backup pra uma nova variável e dou free nela.

Mostrar código
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
    static char	*remove_read_line(char *backup)
{
int i;
int j;
char *new_backup;

i = 0;
while (backup[i] && backup[i] != '\n')
i++;
if (!backup[i])
{
free(backup);
return (NULL);
}
new_backup = (char *)malloc(sizeof(char) * (ft_strlen(backup) - i + 1));
if (!new_backup)
return (NULL);
i++;
j = 0;
while (backup[i])
new_backup[j++] = backup[i++];
new_backup[j] = '\0';
free(backup);
return (new_backup);
}

Inicio