将基本名称与完整文件路径分开

时间:2016-07-02 13:21:06

标签: c string

#include <stdio.h>
int mosrcat(char *o, int tsize, ...) {
  register int cot = 0;
  va_list ap;
  va_start(ap, tsize);
  char *t = va_arg(ap, char *);
  while(t != NULL) {
    while((*(o++) = *(t++)) != 0) {
      cot++;
      if(cot == tsize) {
        *(o) = 0;
        return cot;
      }
    }
    t = va_arg(ap, char *);
    o--;
  }
  va_end(ap);
  return cot;
}

int mofibasename(const char *file_addr, char *fbasename) {
  register int mo = mosrlen(file_addr) - 1;
  register int n = 1;
  if(*(file_addr+mo) == '/') {
    printf("F\n");
    mo--;
  }
  while(mo != 0) {
    if(*(file_addr+mo) == '/') break;
    mo--;
    n++;
  }
  return mosrcat(fbasename, n, file_addr, NULL);
}

int main(void) {
  char o[255];
  printf("%d:%s\n", mofibasename("/home/Joe/Skh/", o), o);
  return 0;
}

这是我的代码。 mofibasename()用于将文件基本名称与完整文件路径分开。

实施例。 /home/Joe/Downloads/x.pdf - &gt; x.pdf
防爆。 /etc/passwd - &gt; passwd

但是这个功能并没有奏效。它输出为/home(输入:/home/Joe/Skh/)。

我有什么不对吗?我尝试了很多次。

3 个答案:

答案 0 :(得分:1)

你可能会过度思考它。如果你只想修改文件名中的路径(不使用string.h函数),你需要做的就是找到字符串的结尾并向后工作,直到找到/或者开头,例如

char *trimpath (const char *s)
{
    if (!s || !*s) return NULL;  /* validate input string  */
    const char *p = s;

    for (; *p; p++);             /* find null-terminator    */
    --p;                         /* reposition at last char */
    for (; p > s; p--)           /* find char after '/'     */
        if (*(p - 1) == '/')
            break;

    return (char *)p;
}

该函数只返回一个指向文件名开头的指针,其中包含总字符串。一个简短的工作示例,它将/path/filename.ext组合作为第一个参数(或者如果没有给出参数,则使用自己的默认示例名称):

#include <stdio.h>

char *trimpath (const char *s);

int main (int argc, char **argv) {

    const char *path = argc > 1 ? argv[1] : "/some/path/to/a/file.txt";

    printf ("\n full path : %s\n filename  : %s\n", path, trimpath (path));

    return 0;
}

char *trimpath (const char *s)
{
    if (!s || !*s) return NULL;  /* validate input string  */
    const char *p = s;

    for (; *p; p++);             /* find null-terminator    */
    --p;                         /* reposition at last char */
    for (; p > s; p--)           /* find char after '/'     */
        if (*(p - 1) == '/')
            break;

    return (char *)p;
}

示例使用/输出

$ ./bin/trimpath

 full path : /some/path/to/a/file.txt
 filename  : file.txt

使用string.h,您可以将功能缩短为:

char *trimpath (const char *s)
{
    if (!s) return NULL;
    char *p = strrchr (s, '/');
    return p ? p + 1 : s;
}

看看他们两个以及任何其他答案,如果您有任何问题,请告诉我。

答案 1 :(得分:0)

return mosrcat(fbasename, n, file_addr, NULL);

此时n是1 +基本名称中的字符数。您正在复制n开头中的file_addr个字符。

听起来你要做的就是从n开始0,而不是从1开始,然后从file_addr开始的最后一个斜线复制:

return mosrcat(fbasename, n, file_addr+mo+1, NULL);

答案 2 :(得分:0)

如果您的操作系统支持POSIX,POSIX会提供完全符合您要求的basename() function

  

命名

     

basename - 返回路径名的最后一个组件

     

<强>概要

[XSI] [Option Start] #include <libgen.h>

char *basename(char *path); [Option End]
     

<强>描述

     

basename()函数应采用path指向的路径名   并返回指向路径名的最后一个组件的指针,删除   任何尾随'/'字符。

     

...

注意粗体部分 - POSIX basename()可以修改其参数。

另外,在Linux上使用basename()时要小心 - Linux提供了两个具有不同语义的两个 basename()函数。根据{{​​3}}:

  

说明

     

警告:basename()有两个不同的功能 - 见下文。

     

...

在Linux上使用basename()之前阅读该手册页。