Reputation: 55
( I'm just authorized to use: malloc, free, read)
I'm trying to get the next line in a file with any BUF_SIZE but it's returning me the wrong value.
So, the returned (wrong value, missing firsts chars) value:
3
1 - #include <stdio.h>
1 - dlib.h>
1 - clude "libft/libft.h"
1 - BUFF_SIZE 32
My source code:
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include "libft/libft.h"
# define BUFF_SIZE 32
int get_next_line(int const fd, char **line)
{
char buffer[BUFF_SIZE + 1];
size_t i;
size_t size;
if (!(*line = malloc(BUFF_SIZE)))
return (-1);
*line[0] = '\0';
while (read(fd, buffer, BUFF_SIZE) > 0)
{
buffer[BUFF_SIZE + 1] = '\0';
if (buffer[0] == '\n')
return (1);
if (ft_strchr(buffer, '\n') != NULL)
{
i = 0;
size = ft_strlen(*line);
buffer[BUFF_SIZE + 1] = '\0';
while (buffer[i] != '\0')
{
if (buffer[i] == '\n')
{
if (!(*line = realloc(*line, i + size)))
return (-1);
buffer[i] = '\0';
ft_strncat(*line, buffer, i);
return (1);
}
i++;
}
}
if (!(*line = realloc(*line, BUFF_SIZE)))
return (-1);
ft_strncat(*line, buffer, BUFF_SIZE);
}
return (0);
}
int main(void)
{
int fd;
int ret;
char *line;
if ((fd = open("main.c", O_RDONLY)) < 3 && fd != 0)
return (-1);
printf("%d\n", fd);
ret = get_next_line(fd, &line);
printf("%d - %s\n", ret, line);
ret = get_next_line(fd, &line);
printf("%d - %s\n", ret, line);
ret = get_next_line(fd, &line);
printf("%d - %s\n", ret, line);
ret = get_next_line(fd, &line);
printf("%d - %s\n", ret, line);
return (0);
}
Upvotes: 0
Views: 15556
Reputation: 164679
I got this to compile by replacing all the ft_blah functions with their string.h equivalents. There are many problems.
Strings in C are null terminated and so need an extra byte allocated to them for that null. If you want to allocate a string of a single character, you have to allocate two bytes.
Next big problem is you keep trying to append to tmp
but it only has a single byte allocated. tmp
needs to have more memory allocated to it as you go.
On the theme of memory allocation, buffer
is never returned so there's no need to allocate memory for it on the heap. It can simply on the stack instead and automatically free'd when the function returns. char buffer[2] = ""
.
You should be using strncat
, not strcpy
, to concatenate strings.
It seems ft_strverif
just copies the string? I don't know why you call it before calling strcpy
which will just copy the string. strcpy(tmp, ft_strverif(buffer));
means buffer
is needlessly copied twice. Worse, that extra copy is never free'd so it will leak memory.
I'd suggest eliminating tmp
entirely and instead append directly to line
. Use realloc
to add more memory to line
, probably best to add memory in chunks or double it every time for efficiency.
If you're emulating getline
note that getline
takes the length of the already allocated line buffer for a reason. This lets line
be reused in the while(getline...)
loop without having to be free'd every loop iteration. In effect, line
becomes a reusable buffer.
Finally, always run with -Wall
or even -Weverything
if your compiler supports it. Fix all the warnings, even if they seem silly. Then, run your code using valgrind, it will tell you when you're using uninitialized memory or where you're leaking memory. Very, very helpful.
Once all that's done, get_next_line
becomes much simpler.
int get_next_line(int const fd, char **line)
{
char buffer[2] = "";
/* Allocate line memory if needed */
if( !*line )
*line = malloc(100 * sizeof(char));
/* Blank out the line */
*line[0] = '\0';
while( read(fd, buffer, 1) > 0 ) {
strncat(*line, buffer, 1);
if( buffer[0] == '\n' )
break;
}
return 0;
}
The exercises left for you are...
line
.line
.get_next_line
grow line
as needed.line
is (like getline
does).Upvotes: 2