I am trying to create a function that reads all characters in a given file into a linked-list, returning a pointer to the list. I cannot use fopen, fread, or fclose. I have confirmed that this is working code if operating on a string:
Note that ft_lstnew creates a link with the content as the first peram, returning a pointer to that link.
head = ft_lstnew(&str[i++], 1);
curr = head;
while(str[i])
{
curr->next = ft_lstnew(&str[i++], 1);
curr = curr->next;
}
curr->next = ft_lstnew(&str[i], 1);
How can I alter this code to operate on character in a file instead of in a string using the read function?
t_list *ft_lstnew(void const *content, size_t content_size);
t_list *read_tetriminos(char *file)
{
int fd;
char c;
t_list *curr;
t_list *head;
fd = open(file, O_RDONLY, 0);
read(fd, &c, 1);
head = ft_lstnew(&c, 1);
curr = head;
while(curr->content != EOF)
{
read(fd, &c, 1);
curr->next = ft_lstnew(&c, 1);
curr = curr->next;
}
close(fd);
return(head);
}
You're almost there. The only thing that you are doing wrong is assuming that read
will write EOF
inside the provided buffer when reaching the end of the file. EOF
is just a special value used by higher level functions provided by stdio.h
to signal the end of a FILE
object has been reached. Furthermore, EOF
is not a char
, but a int
. Here you're using raw syscalls such as open
and read
to accomplish your task, and EOF
has nothing to do with those.
You can take a look at the manual page for read
to see what happens when the end of the file is reached:
ssize_t read(int fd, void *buf, size_t count);
read()
attempts to read up tocount
bytes from file descriptorfd
into the buffer starting atbuf
.On files that support seeking, the read operation commences at the file offset, and the file offset is incremented by the number of bytes read. If the file offset is at or past the end of file, no bytes are read, and
read()
returns zero.
Therefore, your program can be re-written like this (I also added some error checking):
t_list *read_tetriminos(char *file)
{
int fd;
ssize_t nread;
char c;
t_list *curr;
t_list *head;
fd = open(file, O_RDONLY);
if (fd == -1) {
// Open failed.
return NULL;
}
nread = read(fd, &c, 1);
if (nread == -1) {
// Read error.
return NULL;
} else if (nread == 0) {
// File is empty.
return NULL;
}
head = ft_lstnew(&c, 1);
curr = head;
while (read(fd, &c, 1) == 1) // You can check for errors here too, this is just simplified.
{
curr->next = ft_lstnew(&c, 1);
curr = curr->next;
}
close(fd);
return head;
}