Search code examples
cgetlinefile-descriptor

issue handle returned buffer with consecutives newlines in my own get_line implementation


To this project i need to read a file and returned a line when it encounters a newline or the EOF. My function does that correctly, but when the file has consecutive newlines is suppose to returned a new line for each consecutive appearence. Ex: if a file is:

1."hello there
2.
3.
4.
5."

it should return five lines, because each time it encounter a newline the function returns. but my function for this example return two times instead of 5. will give more outputs after the code.

Here are the parts of the code where i believe the issue is:

int find_newline(char *buffer) // RETURN POSition WHERE IT FINDS THE FIRST '\N' IN THE BUFFER
{
    int i;

    i = 0;
    if (!buffer)
        return (-1);
    while (buffer[i])
    {
        if (buffer[i] == '\n')
            return (i);
        i++;
    }
    return (-1);
}

static int  update_remainder_buffer(char **buffer, int newline_pos) 
{    //IS EXPECTED TO TREAT THE CHARACTERS IN BUFFER AFTER THE NEWLINE, PREP FOR NEXT CALL
    int remaining_len;

    remaining_len = strlen(*buffer + newline_pos);
    if (remaining_len > 0)
        memmove(*buffer, *buffer + newline_pos, remaining_len + 1);
    else
        (*buffer)[0] = '\0';
    *buffer = realloc(*buffer, strlen(*buffer), remaining_len + 1);
    if (!*buffer)
        return (0);
    return (1);
}

char    *extract_line(char **buffer, int newline_pos)
//EXTRACT BUFFER FROM BEGINNING TO THE POINT WHERE IT FINDS THE NEWLINE. USE UPDATE_REMAINDER_BUFFER AS HELPER
{
    char    *line;
    int     line_len;

    if ((*buffer)[0] == '\n' && newline_pos >= 0)
    {//ISSUE PROBABLY HERE or 
        line = malloc(2);
        line[0] = '\n';
        line[1] = '\0';
        if (!update_remainder_buffer(buffer, 1))
            return (free(line), NULL);
        return (line);
    }
    if (newline_pos == -1)
        newline_pos = strlen(*buffer);
    line_len = newline_pos;
    if ((*buffer)[newline_pos] == '\n')
        line_len = newline_pos + 1;
    line = malloc(line_len + 1);
    if (!line)
        return (NULL);
    memcpy(line, *buffer, line_len);
    line[line_len] = '\0';
    if (!update_remainder_buffer(buffer, line_len))
        return (free(line), NULL);
    return (line);
}

so basically what i tried to do was to check either in the begin if the buffer readed started with a newline so we return right the way a newline, AND if we got a part in buffer with consecutive newlines. i add some controls to test but messed the buffer content, so i remove the ifs and elses that prob would cause more confusion and stick with this implementation to avoid this. Here are the rest of the code, the code is in order, and some outputs:

int read_newpiece(int fd, char **buffer)
{
    int         bytes_readed;
    char        current_buffer[BUFFER_SIZE + 1];
    char        *new_buffer;

    bytes_readed = read(fd, current_buffer, BUFFER_SIZE);
    if (bytes_readed <= 0)
        return (bytes_readed);
    current_buffer[bytes_readed] = '\0';
    if (!*buffer)
    {
        *buffer = malloc(1);
        if (!*buffer)
            return (-1);
        (*buffer)[0] = '\0';
    }
    new_buffer = ft_realloc(*buffer, ft_strlen(*buffer),
            ft_strlen(*buffer) + bytes_readed + 1);
    if (!new_buffer)
        return (-1);
    *buffer = new_buffer;
    strncat(*buffer, current_buffer, bytes_readed);
    return (bytes_readed);
}

char    *get_next_line(int fd)
{
    static char *buffer = NULL;
    char        *line;
    int         newline_index;

    if (fd < 0 || BUFFER_SIZE <= 0)
        return (NULL);
    if (!buffer)
    {
        buffer = malloc(1);
        if (!buffer)
            return (NULL);
        buffer[0] = '\0';
    }
    newline_index = -1;
    while (newline_index == -1 && read_newpiece(fd, &buffer) > 0)
        newline_index = find_newline_eof(buffer);
    if (newline_index == -1 && (!buffer || buffer[0] == '\0'))
    {
        free (buffer);
        buffer = NULL;
        return (NULL);
    }
    line = extract_line(&buffer, newline_index);
    return (line);
}

int main(int ac, char **av)
{
    int     fd;
    char    *line;

    if (ac < 2)
        return (write(1, "Usage: ./a.out <filename>\n", 27));
    fd = open(av[1], O_RDONLY);
    if (fd <= -1) 
        return (write(1, "error opening file\n", 20));

    while ((line = get_next_line(fd)) != NULL)
    {
        printf("()%s", line); // () TO KEEP TRACK HOW MANY TIMES A BUFFER IS PRINTED
        free (line);
    }
    close (fd);
    return (0);
}

HERE OUTPUT FOR ONLY CONSECUTIVE NEWLINES FILE, NOTE THAT I USE () TO KEEP TRACK OF HOW MANY TIMES A BUFFER IS RETURNED

output 1:

i expect 5 times the "()".

rache@V:~/programing/42/Common Core/get_next_line/04$ ./a.out multiples_nl.txt 
()
()



rache@V:~/programing/42/Common Core/get_next_line/04$ 

output 2:

again expected 10 "()" but return all the newlines at once.

rache@V:~/programing/42/Common Core/get_next_line/04$ ./a.out test60.txt 
()cinccinccinccinccinccinccinccinccinccinccinccincci
()








rache@V:~/programing/42/Common Core/get_next_line/04$ 

this output is bigger so i leave for last: here the file is printed all correctly, but when it comes to the 4.1 step at the bottom it returns all the rest of characters at once.

rache@V:~/programing/42/Common Core/get_next_line/04$ ./a.out 1-brouette.txt 
()Wikipédia l'encyclopédie libre
()
()Rechercher dans Wikipédia
()
()Créer un compte
()
()Outils personnelsreplié
()
()Accueil
()Portails thématiques
()
()Article au hasard
()
()Contact
()
()Contribuer
()
()Débuter sur Wikipédia
()
()-----------------------------------------------------------
()Aide
()Communauté
()Modifications récentes
()Faire un don
()Outils
()Pages liées
()Suivi des pages liées
()Téléverser un fichier
()Pages spéciales
()Lien permanent
()Informations sur la page
()Citer cette page
()Élément Wikidata
()Modifier les liens interlangues
()Imprimer / exporter
()Créer un livre
()Télécharger comme PDF
()Version imprimable
()Dans d’autres projets
()Wikimedia Commons
()ArticleDiscussion
()LireModifierModifier le codeVoir l’historique
()-----------------------------------------------------------
()
()Brouette
()
()C’est un outil ergonomique pour le transport de matériaux ou d’outils sur des terrains qui peuvent être accidentés mais nécessairement peu inclinés. Indispensable sur les chantiers, dans les fermes ou dans les jardins, elle facilite le déplacement de charges qui peuvent être lourdes ou encombrantes. Le principe du levier associé à la position du centre de gravité vers l’aplomb du point d’appui (la roue), lui confère une grande efficacité.
()
()Sommaire
()1     Éléments d’histoire de la brouette
()1.1   La question des origines
()1.2   Une diffusion assez lente
()1.3   La brouette dans les textes
()2     Étude technologique de la brouette
()2.1   Analyse fonctionnelle
()2.1.1 Fonction principale, définition
()2.1.2 Constitution de la solution « brouette »
()2.1.3 Variantes – classification
()2.2   Analyse mécanique
()2.2.1 La roue
()2.2.2 Influence de la position longitudinale de la caisse
()2.2.3 Aptitude au basculement
()2.2.4 Conclusions constructives
()3     Perspectives
()4     Autour de la brouette
()4.1   Dans la littérature et dans les arts
4.2     Polysémie du mot brouette
4.3     Jeux d’enfants (petits ou grands…)
4.4     Décoration
5       En images d’hier et d’aujourd’hui
6       Notes et références
7       Voir aussi
7.1     Bibliographie
7.2     Liens externes
Éléments d’histoire de la brouette
La question des origines

Variantes selon le nombre de roues
Si la brouette selon son étymologie a deux roues, c’est surtout lorsqu’elle n’en a qu’une qu’elle se caractérise comme « brouette. » Toutefois, quand elle a deux roues, celles-ci sont coaxiales.
Critiques : La brouette à deux roues permet de plus grandes contenances, plus stable elle peut se conduire d’une seule main mais elle est très difficile, voire éprouvante, à mener sur les terrains accidentés tandis que la brouette à une roue se joue des irrégularités du terrain. Par ailleurs la place nécessaire pour manœuvrer la brouette à deux roues dépend de la largeur de l’essieu.
rache@V:~/programing/42/Common Core/get_next_line/04$ 

Solution

  • The answer is that you cannot use this line in your code if you want to get line by line from a file:

    bytes_readed = read(fd, current_buffer, BUFFER_SIZE);
    

    You need change the above line to something like this below with fgets():

    bytes_readed = 0;
    if (fgets(current_buffer, BUFFER_SIZE, fd))
        bytes_readed = strlen(current_buffer);
    

    In order to use fgets(), you need use fopen(), instead of open().

    After the above modifications, I think your code should work as what you expected.