【问题标题】:function to split a filepath into path and file将文件路径拆分为路径和文件的函数
【发布时间】:2009-10-15 21:43:31
【问题描述】:

假设我有一个函数:

void split_path_file(char** p, char** f, char *pf)
{
    //malloc and set *p to file path, malloc and set *f to file name
    //pf is the pointer to the full file and path "C:\sponge\bob\square.pants"
    // edit: leave pf in its origional state
}

最好的方法是什么?

【问题讨论】:

    标签: c string


    【解决方案1】:
    void split_path_file(char** p, char** f, char *pf) {
        char *slash = pf, *next;
        while ((next = strpbrk(slash + 1, "\\/"))) slash = next;
        if (pf != slash) slash++;
        *p = strndup(pf, slash - pf);
        *f = strdup(slash);
    }
    

    (如果pf == slash,则没有目录组件。)

    【讨论】:

    • 我不喜欢使用strdup(),因为它是非标准的,但我真的不喜欢使用strndup(),因为我的编译器没有它。 :P
    • PS:我使用的(旧)编译器没有 strndup()。这是剪切/粘贴的代码(也添加#include stackoverflow.com/questions/12834385/…
    【解决方案2】:

    聚会可能有点晚了,但我发现并使用多年的最佳解决方案是 dirnamebasename 两个函数

    path         dirname    basename
    "/usr/lib"    "/usr"    "lib"
    "/usr/"       "/"       "usr"
    "usr"         "."       "usr"
    "/"           "/"       "/"
    

    它们非常适合分隔路径/文件名的各个部分。与 realpath() 一起,恕我直言,它们在简单性和功能方面无与伦比。

    http://linux.die.net/man/3/basename

    http://man7.org/linux/man-pages/man3/realpath.3.html

    【讨论】:

    • realpath() 的一个限制似乎是它要求您在文件系统所在的机器上执行它,并且您可以访问路径上的所有目录。在某些情况下,这将无法正常工作,或者由于您需要访问硬盘驱动器而导致性能下降。
    【解决方案3】:

    向后遍历字符串直到到达第一个'\\',然后将*f设置为它之后的所有内容,*p设置为之前的所有内容和'\\'。

    【讨论】:

    • 您需要至少进行一次前向传递才能找到 C 字符串的终止 '\0' -- 没有理由在前进时不扫描斜线而不是开始第二次反向传递。
    【解决方案4】:

    最简单的方法似乎是从头开始,从头开始,寻找第一个分隔符。然后你有两种情况:要么你找到了一个,要么你没有。这样的事情应该为你做:

    #include <stdlib.h>
    #include <string.h>
    
    void split_path_file(char **p, char **f, char *pf) {
      char *newcopy = malloc(strlen(pf) + 1);
      strcpy(newcopy, pf);
    
      for (z=newcopy+strlen(newcopy); z>newcopy; z--) {
        if (*z == '/' || *z == '\\')
          break;
      }
    
      if (z > newcopy) {
        *p = newcopy;
        *z = '\0';
        *f = z+1;
      } else {
        *f = newcopy;
        *p = NULL;
      }
    }
    

    更新:@ephemient 在下面的评论指出上述方法不让*p*f 适合调用free()。如果这很重要,则需要像这样更复杂的东西:

    #include <stdlib.h>
    #include <string.h>
    
    void split_path_file(char **p, char **f, char *pf) {
    
      /* Find last delimiter. */
      char *z;
      for (z=pf+strlen(pf); z>=pf; z--) {
        if (*z == '/' || *z == '\\')
          break;
      }
    
      if (z >= pf) {
        /* There is a delimiter: construct separate
           path and filename fragments. */
        printf("--> %i\n", z-pf);
        *p = malloc(z-pf+1);
        strncpy(*p, pf, z-pf);
        (*p)[z-pf] = '\0';
        *f = malloc(strlen(z));
        strcpy(*f, z+1);
      } else {
        /* There is no delimiter: the entire
           string must be a filename. */
        *p = NULL;
        *f = malloc(strlen(pf)+1);
        strcpy(*f, pf);
      }
    }
    

    【讨论】:

    • 这可能违反了 OP 要求 *p*f 成为 malloced 的要求:如果调用者尝试使用 free(*f) 这是另一个 malloced 区域的偏移量,则会发生可怕的失败。
    【解决方案5】:

    我想出了以下内容,当然这假设 pf 是 malloced。

    void split_path_file(char** p, char **f, char *pf)
    {
        char *posp = strrchr(pf, '\\');
        *posp = '\0';
        *p = strdup(pf);
        *f = strdup(posp+1);
        *posp = '\\';
    }
    

    不确定这是否比上述答案更好。

    【讨论】:

    • 这违反了 OP 的要求,即不修改 pf,并且如果存在没有目录的文件名,则会出现段错误。另请注意,正斜杠在 Windows 上仍然是有效的路径分隔符。
    • 别介意第一点:你恢复反斜杠。但是,其他两个可能仍然存在问题。
    【解决方案6】:
    整数 stripfilenameandpath (char *path, char *onlypath, char *onlyfilename) { /* 纪录片 路径 = 路径 com 路径 e arquivo onlypath = somete o path onlyfilename = somete o arquivo sem o 路径 */ 诠释; 诠释我; 诠释 p; 字符温度[255]; 字符 *fixo; #ifdef WIN32 const int 分隔符 = '\\'; #别的 const int 分隔符 = '/'; #万一 修复=路径; 如果(路径 == NULL) { 如果(仅路径!= NULL) { memset (onlypath, 0, 1); } 如果(仅文件名!= NULL) { memset (onlyfilename, 0, 1); } 返回 1; } ret = strlen(路径); 如果 (!ret) { 如果(仅路径!= NULL) { memset (onlypath, 0, 1); } 如果(仅文件名!= NULL) { memset (onlyfilename, 0, 1); } 返回0; } 对于 (i = 0; i -1; i--) { if (temp[i] == 分隔符) { 温度[i + 1] = 0; 休息; } p++; } p = ret - p; 修复 += p + 1; 如果(仅路径!= NULL) { strcpy(唯一路径,临时); } 如果(仅文件名!= NULL) { strcpy (onlyfilename, fixo); } 返回0; }

    【讨论】:

      猜你喜欢
      • 2015-12-20
      • 2020-08-04
      • 2012-05-17
      • 2020-11-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多