Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I create a (C) function to read data from a file into a linked-list using 'read'?

Tags:

c

io

linked-list

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?

My Attempt

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);
}
like image 669
ClintCC Avatar asked Nov 07 '22 11:11

ClintCC


1 Answers

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 to count bytes from file descriptor fd into the buffer starting at buf.

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;
}
like image 192
Marco Bonelli Avatar answered Nov 15 '22 11:11

Marco Bonelli