Home > Software design >  Add a “/” at the end of each string in an array of strings
Add a “/” at the end of each string in an array of strings

Time:09-09

I have an array of double pointers where each string represents a path.

I would like to add a “/” at the end of each path in my array so that I can then execute them in my program, but I'm having trouble designing the loop.

Any ideas ?

Scheme

Here is my way of doing it for the moment but as you can see it is not at all optimal...

char    **ft_extract_and_delimit_path(char **envp)
{
    char    **array_of_paths;
    int     i;
    int     j;

    array_of_paths = NULL;
    i = 0;

    while(ft_strnstr(envp[i], "PATH", 4) == 0)
        i  ;

    array_of_paths = ft_split(envp[i]   5, ':');
    
    i = 0;
    j = 0;

    while (array_of_paths[i][j] != '\0')
        j  ;
    array_of_paths[i][j] = ft_strjoin(array_of_paths[j], "/");

    i  ;
    j = 0;

    while (array_of_paths[i][j] != '\0')
        j  ;
    array_of_paths[i][j] = ft_strjoin(array_of_paths[j], "/");

    i  ;
    j = 0;

    while (array_of_paths[i][j] != '\0')
        j  ;
    array_of_paths[i][j] = ft_strjoin(array_of_paths[j], "/");

    i  ;
    j = 0;

    ...
}

CodePudding user response:

Assuming that your string has enough space to accommodate the new char:

char *addCharToString(char *str, char c)
{
    if(*str)
    {
        size_t len = strlen(str);
        str[len] = c;
        str[len   1] = 0;
    }
    return str;
}

If not you need to create new string.

char *allocateAndAddCharToString(char *str, char c)
{
    char *newstr = NULL;
    if(*str)
    {
        size_t len = strlen(str);
        newstr = malloc(len   2);
        if(newstr)
        {
            newstr[len] = c;
            newstr[len   1] = 0;
        }
    }
    return newstr;
}

Then call the function from the place in your code where you need to add the char. Always split task into smaller bits and use functions instead of "monotonic" coding in the main function

CodePudding user response:

The code for ft_split is not provided but a specialized ft_split_path could be used to append a slash to the end of each sub-string.
That seems a reasonable objective as memory is being allocated. Allocate an extra character for the slash and append it.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char **ft_split_path ( char *path) {
    char **items = NULL;
    char *token = path;
    size_t count = 0;
    size_t span = 0;

    if ( ! path) {
        return NULL;
    }

    while ( *token) {
        token  = strspn ( token, ":");
        span = strcspn ( token, ":");
        if ( span) {
            char **temp = NULL;
            // allocate an extra pointer as a NULL sentinel
            if ( NULL == ( temp = realloc ( items, sizeof *temp * ( count   2)))) {
                fprintf ( stderr, "realloc problem\n");
                return items;
            }
            items = temp;
            //allocate  2 one for / and one for terminating zero
            if ( NULL == ( items[count] = calloc ( sizeof **temp, span   2))) {
                fprintf ( stderr, "calloc problem\n");
                return items;
            }
            strncpy ( items[count], token, span);
            items[count][span] = '/';
            items[count][span   1] = 0;
              count;
            items[count] = NULL;
        }
        token  = span;
    }

    return items;
}

int main ( void) {
    char **paths = NULL;

    char *env = getenv ( "PATH");
    if ( env) {
        printf ( "%s\n\n", env);
        paths = ft_split_path ( env);
    }
    int each = 0;
    if ( paths) {
        while ( paths[each]) {
            printf ( "%s\n", paths[each]);
              each;
        }
    }

    each = 0;
    if ( paths) {
        while ( paths[each]) {
            free ( paths[each]);
              each;
        }
    }
    free ( paths);

    return 0;
}

CodePudding user response:

You also mention "problems with designing your loops" I will address that topic first.

You repeat all the code again and again and just increment i in between. That is candidate #1 for creating your loop.

DISCLAIMER I assume you are using libft.

ft_split from libft indicates the end of the pointer array by array_of_paths[i]==NULL. Let's use that as condition for your loop.

char    **ft_extract_and_delimit_path(char **envp)
{
    char    **array_of_paths;
    int     i;
    int     j;

    array_of_paths = NULL;
    i = 0;

    while(ft_strnstr(envp[i], "PATH", 4) == 0)
        i  ;

    array_of_paths = ft_split(envp[i]   5, ':');
    
    for (int i = 0; array_of_paths[i] != NULL; i  )
    {
      j = 0;
      while (array_of_paths[i][j] != '\0')
        j  ;
      array_of_paths[i][j] = ft_strjoin(array_of_paths[j], "/");
    }
}

That is the loop about all the paths you have in that array.

Now we need to look at your inner loop.

You are using ft_strjoin which returns a pointer to a string holding both input strings concatenated. You try to assign this into a single character which cannot work. The string you put into this function uses index j which you used for finding the length of the string but you use it as index into the array of pointers. That will likely cause out of bounds access. You also don't free the pointer that you had stored there before, causing a memory leak.

It should be like this:

      char *tmp = ft_strjoin(array_of_paths[j], "/");
      if (tmp != NULL)
      {
        free(array_of_paths[i]);
        array_of_paths[i] = tmp;
      }
      else
        ;  // Do some error handling

Together your code could look like this (not tested):

char    **ft_extract_and_delimit_path(char **envp)
{
    char    **array_of_paths = NULL;
    int     i = 0;

    while(ft_strnstr(envp[i], "PATH", 4) == 0)
        i  ;

    array_of_paths = ft_split(envp[i]   5, ':');

    for (int i = 0; array_of_paths[i] != NULL; i  )
    {
      char *tmp = ft_strjoin(array_of_paths[j], "/");
      if (tmp != NULL)
      {
        free(array_of_paths[i]);
        array_of_paths[i] = tmp;
      }
      else
        ;  // Do some error handling
    }
}

I did not take care about the part with the PATH environment variable. Accoring to comment from Craig Estey you must change this as well:

If you're trying to split the PATH environment variable into a char ** array, there are some issues: Change while(ft_strnstr(envp[i], "PATH", 4) == 0) i ; into while(ft_strncmp(envp[i], "PATH=", 5) != 0) i ;

  • Related