【问题标题】:splitting a full filename into parts将完整的文件名拆分为多个部分
【发布时间】:2010-11-02 08:15:25
【问题描述】:

我正在创建一个函数,它将完整的 unix 文件名(如 /home/earlz/test.bin)拆分为各个部分。我有一个函数,它适用于前两部分完美,但之后它会产生错误的输出......

strlcpy_char 将使用 term 作为终止符以及 0 来复制字符串。 如果以 term 结尾,则 term 将是字符串的最后一个字符,然后为 null。

返回 trg 字符串长度...

int strlcpy_char(char *trg,const char *src,int max,char term){
    int i;
    if(max==0){return 0;}
    for(i=0;i<max-1;i++){
            if(*src==0){
                    *trg=0;
                    return i;
            }
            if(*src==term){
                    *trg=term;
                    trg++;
                    *trg=0; //null terminate
                    return i+1;
            }
            *trg=*src;
            src++;
            trg++;
    }
    *trg=0;
    return max; 
}

.

int get_path_part(char *file,int n,char *buf){
    int i;
    int current_i=0;
    //file is assumed to start with '/'so it skips the first character.
    for(i=0;i<=n;i++){
            current_i++;
            current_i=strlcpy_char(buf,&file[current_i],MAX_PATH_PART_SIZE,'/');
            if(current_i<=1){ //zero length string..
                    kputs("!"); //just a debug message. This never happens with the example
                    return -1; //not enough parts to the path
            }
    }
    if(buf[current_i-1]=='/'){
            return 1; //is not the last part
    }else{
            return 0; //is the last part(the file part)
    }
}

我用这段代码来测试它:

        kputs("test path: ");
        kgets(cmd);
        kputs("\n");
        char *tmp=malloc(256);
        int i=0;
        get_path_part(cmd,i,tmp);
        kputs(tmp);
        kputs("\n");
        i=1;
        get_path_part(cmd,i,tmp);
        kputs(tmp);
        kputs("\n");
        i=2;
        get_path_part(cmd,i,tmp);
        kputs(tmp);
        kputs("\n");

当我尝试“/home/test.bin”之类的东西时,它可以正常输出

/家 /test.bin

但是当我尝试“/home/earlz/test.bin”时,我得到了

/家 /厄尔兹 /arlz

任何人都在我的代码中看到了问题,正如我一直在寻找的那样,但我只是看不到任何问题。

另外,在你说“但是有一个库”之前,我是在操作系统内核中执行此操作的,所以我几乎没有标准库。我只有 string.h 的一部分,这就是标准的内容。

【问题讨论】:

    标签: c string filenames kernel


    【解决方案1】:

    试试我下面的代码。

    如果您需要标准 C 函数(如 strchr())的实现,请尝试 koders.com 或直接在谷歌上搜索 strchr.c。

    #include <stdio.h>
    #include <string.h>
    
    const char *NextToken(const char *pStart, char chSep, char *pToken, size_t nTokMax)
    {
        const char *pEnd;
        size_t nLength;
    
        /* set output to empty */
        *pToken=0;
    
        /* make sure input is OK */
        if (!pStart || *pStart!=chSep)
            return NULL;
    
        /* find end of token */
        pEnd = strchr(pStart+1, chSep);
        if (pEnd)
            nLength = pEnd - pStart;
        else
            nLength = strlen(pStart);
    
        if (nLength >= nTokMax) /* too big */
            return NULL;
    
        strncpy(pToken, pStart, nLength);
        pToken[nLength] = 0;
    
        return pEnd;
    }
    
    int main()
    {
        #define BUFFSIZE 256
        char cmd[BUFFSIZE];
        char tmp[BUFFSIZE];
        const char *pStart=cmd;
        int i=0;
    
        puts("test path: ");
        fgets(cmd, BUFFSIZE, stdin);
        puts("");
    
        do {
            pStart = NextToken(pStart, '/', tmp, BUFFSIZE);
            if (tmp[0])
                puts(tmp);
        } while (pStart);
        return 0;
    }
    

    【讨论】:

      【解决方案2】:

      我就是这样做的

      char ** split_into_parts(char *path) {
        char ** parts = malloc(sizeof(char *) * 100);
        int i = 0;
        int j = 0;
      
        if (*path == '/') {
          path++;
        }
      
        parts[0] = 0;
        while (*path) {
          if (*path == '/') {
            parts[i][j] = 0;
            i++;
            parts[i] = 0;
            j = 0;
          } else {
            if (parts[i] == 0) {
              parts[i] = malloc(sizeof(char) * 100);
            }
            parts[i][j] = *path;
            j++;
          }
          path++;
        }
        parts[i+1] = 0;
      
        return parts;
      }
      

      【讨论】:

        【解决方案3】:

        你不需要做类似的事情

        tocurrent_i += strlcpy_char...
        

        而不是

        tocurrent_i = strlcpy_char...
        

        【讨论】:

        • 啊。太晚了。 +1 Tobuesque :)
        【解决方案4】:

        我认为您需要跟踪您的 current_i for i>1,因为从 strlcpy 返回的最大值不知道您在整个文件字符串中的位置。有意义吗?

        current_i=strlcpy_char(buf,&file[current_i],MAX_PATH_PART_SIZE,'/');
        

        【讨论】:

        • 我认为 Tobiesque 在我输入答案时遇到了同样的问题。他是对的。 +1 给他。
        【解决方案5】:

        您会覆盖current_i,而不是在您走过路径时将其添加。

        所以

        current_i++;
        current_i=strlcpy_char(buf,&file[current_i],MAX_PATH_PART_SIZE,'/');
        

        应该是

        current_i += strlcpy_char(buf,&file[current_i+1],MAX_PATH_PART_SIZE,'/');
        

        【讨论】:

          【解决方案6】:

          如果您使用 Glib,g_strsplit 非常好用且易于使用。

          【讨论】:

          • 操作系统内核。没有我自己不实现的库。
          【解决方案7】:

          您的代码是否必须可重入? 如果不使用strtok,则在strings.h中

          STRTOK(P)
          
          NAME
                 strtok, strtok_r - split string into tokens
          
          SYNOPSIS
                 #include <string.h>
          
                 char *strtok(char *restrict s1, const char *restrict s2);
          
                 char *strtok_r(char *restrict s, const char *restrict sep,
                        char **restrict lasts);
          

          很抱歉没有评论您的代码:)

          【讨论】:

          • 我认为我不想自己实现它(因为我必须这样做,或者从其他地方移植它以在我的内核上编译)另外,我的代码必须是可重入的..将成为各种进程在任何未知时间使用的文件系统驱动程序的一部分......
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-08-29
          • 2014-03-28
          • 1970-01-01
          • 2020-05-04
          • 2012-11-10
          • 1970-01-01
          相关资源
          最近更新 更多