Search code examples
clinked-listtokentokenize

Detect the head node of linked list



typedef struct s_tok
{
    int len;
    char *tok;
    int type;
    struct s_tok *next;
} t_tok;

static int      wordlen(char *wordstart, int pos);
static char     *word(char *cmdline, int len, int s_pos);
static void     add_word(char *cmdline, int *pos, t_tok **token);

t_tok   *tokenization(char *cmdline)
{
    t_tok *tokens;
    t_tok *tmp;
    int i;

    i = -1;
    tokens = malloc(sizeof(t_tok));
    if(!tokens)
        return (NULL);
    tokens->tok = ".";
    tokens->next = NULL;
    tmp = tokens;
    while(cmdline[++i])
    {
        if(cmdline[i] && ft_iswordpart(cmdline[i]))
            add_word(cmdline, &i, &tokens);     
    }
    return (tmp);
}

static void add_word(char *cmdline, int *pos, t_tok **token)
{
    char *wordpart;
    int len;

    len = wordlen(cmdline, *pos);
    wordpart = word(cmdline, len, *pos);
    while((*token)->next != NULL)
        (*token) = (*token)->next;

    (*token)->next = new_token(len, wordpart, WORD);
    free(wordpart);
    *pos += len;
}


static int wordlen(char *wordstart, int s_pos)
{
    int i;

    i = 0;
    while(wordstart[s_pos] && ft_iswordpart(wordstart[s_pos]))
    {
        s_pos++;
        i++;
    }
    return (i);
}

static char *word(char *cmdline, int len, int s_pos)
{
    char *word;
    int i;

    i = 0;
    word = malloc(sizeof(char) * (len + 1));
    while(i < len)
    {
        word[i] = cmdline[s_pos];
        s_pos++;
        i++;
    }
    word[i] = '\0';
    return (word);
}

I have a tokenization function which should return me a tokens detected on command prompt. My t_tok struct which you can see above can store length of my token token as (char*) and type of the token. if i launch this while loop I must the top of while loop make a first node because if the head or first node of my tokens struct doesn't exist it shows me segmentation fault. Can you ask me how can I implement the adding node without creating first node by hand.


Solution

  • You do it by treating an initially null pointer as an list-of-none.

    First, change tokenization as follows:

    t_tok *tokenization(char *cmdline)
    {
        t_tok *tokens = NULL; // << Note: initially NULL
        int i = -1;
    
        while (cmdline[++i])
        {
            if (cmdline[i] && ft_iswordpart(cmdline[i]))
                add_word(cmdline, &i, &tokens); // <== pass by address-of-pointer here
        }
        return tokens;
    }
    

    Then, the add-word function accomodates by looking for a null pointer on which to stash the new node. There are better ways to do this, but you seem to be shooting for the simple scan-to-end approach, which would look liks this:

    static void add_word(char *cmdline, int *pos, t_tok **token)
    {
        int len = wordlen(cmdline, *pos);
        char *wordpart = word(cmdline, len, *pos);
    
        // note: this stops immediately if `*token`
        // already points to a null pointer
        while (*token)
            token = &(*token)->next;
    
        *token = new_token(len, wordpart, WORD);
        free(wordpart);
        *pos += len;
    }
    

    That's it. Assuming new_token (which you didn't show) properly allocates a new record and sets all members, including the next member as NULL, this should do what you want.