解析$ PATH变量并将目录名称保存到字符串数组中

Sar*_*man 3 c malloc bash gcc strtok

我想解析Linux的$ PATH变量,然后将用':'分隔的目录名保存到字符串数组中.

我知道这是一个简单的任务,但我被困住了,任何帮助都会很好.

到目前为止我的代码是这样的,但有些东西是不对的.

char **array;
char *path_string;
char *path_var = getenv("PATH");
int size_of_path_var = strlen(path_var);

path_string = strtok(path_var, ":");
while (path_string != NULL) {
    ss = strlen(path_string)
    array[i] = (char *)malloc(ss + 1);
    array[i] = path_string; //this is actually all i want to do for every path
    i++;
    path_string = strtok(NULL, ":");
}
Run Code Online (Sandbox Code Playgroud)

Jea*_*bre 6

您的代码有两个主要问题,评论几乎总结如下:

  • 你strtok一个公共缓冲区(返回getenv)
  • 你不知道缓冲区中有多少变量,所以根本不分配数组数组!

让我提出一个使用strtok 的工作实现,从而允许检测空路径(并将其替换.为Jonathan暗示的).使用gcc -Wall -Wwrite-strings以下命令编译时没有任何警告:

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

int main()
{
    const char **array;
    const char *orig_path_var = getenv("PATH");
    char *path_var = strdup(orig_path_var ? orig_path_var : ""); // just in case PATH is NULL, very unlikely
    const char *the_dot = ".";
    int j;
    int len=strlen(path_var);
    int nb_colons=0;
    char pathsep = ':';
    int current_colon = 0;

    // first count how many paths we have, and "split" almost like strtok would do
    for (j=0;j<len;j++)
    {
        if (path_var[j]==pathsep)
        {
            nb_colons++;
            path_var[j] = '\0';
        }       
    }

    // allocate the array of strings
    array=malloc((nb_colons+1) * sizeof(*array));

    array[0] = path_var;  // first path

    // rest of paths
    for (j=0;j<len;j++)
    {
        if (path_var[j]=='\0')
        {
            current_colon++;
            array[current_colon] = path_var+j+1;
            if (array[current_colon][0]=='\0')
            {
                // special case: add dot if path is empty
                array[current_colon] = the_dot;
            }

        }
    }

    for (j=0;j<nb_colons+1;j++)
    {
        printf("Path %d: <%s>\n",j,array[j]);
    }

    return(0);
}
Run Code Online (Sandbox Code Playgroud)

操作细节:

  • 制作一个env字符串的副本,以避免屠杀它
  • 计算冒号(使其适用于窗口,只需替换;)和标记
  • 根据冒号+ 1分配数组(比分隔符数多1个令牌!)
  • 第二次传递再次通过字符串并用标记化字符串的部分填充(不需要再次分配,原始字符串已经分配)
  • 特例:空路径:替换为..可以显示警告,告诉用户这不安全.
  • 打印结果