获取文件路径的一部分

时间:2011-09-09 12:01:00

标签: c++ scanf

我有一个文件路径,来自__FILE__宏,我想从中提取2个。

格式为:/some/path/to/a/file/AAA/xxx/BBB.cc。我想要AAABBB路径。 xxx通常是src,inc,tst等,文件扩展名通常是.cc,但不能保证。

我知道我可以使用string.find()甚至将字符串拆分为/字符上的数组,但考虑到所需的搜索次数,这两种字符似乎都不高效。我想到了sscanf,并认为这可能是最好的方法,但是,我无法定义格式,以便它将跳过开头的大部分并获得我需要的部分。我如何使用sscanf来执行此操作,还是有更好的方法?

感谢您的帮助。

4 个答案:

答案 0 :(得分:2)

使用rfind,以便您可以从最后开始并向后工作:

string s = "/some/path/to/a/file/AAA/xxx/BBB.cc";

unsigned int a = s.rfind('.');
unsigned int b = s.rfind('/');
string BBB = s.substr(b+1,a-b-1);

a = s.rfind('/',b-1);
b = s.rfind('/',a-1);  
string AAA = s.substr(b+1,a-b-1);

答案 1 :(得分:0)

  1. 正确
  2. 如果它不够快,请改进它
  3. 自己写这篇文章比尝试让sscanf更容易。您的代码将更容易理解并且速度更快(但是,我怀疑这很重要)。

    从字符串的后面循环。当您找到第一个点时,请记住该位置,然后在找到第一个斜线时提取BBB。记住第二个斜杠的位置,并在找到第三个斜杠时提取AAA。

答案 2 :(得分:0)

char *path = ... /* fill this however you like, for example function argument */
char *AAA_start, *AAA_end;
char *BBB_start, *BBB_end;
        // go the end of the string and find the first .
for (BBB_end = path+strlen(path); *BBB_end != '.'; --BBB_end);
        // continue to find the first /
for (BBB_start = BBB_end; *BBB_start != '/'; --BBB_start);
        // Now you have the beginning and end of BBB
        // continue from there to find next /
for (AAA_end = BBB_start-1; *AAA_end != '/'; --AAA_end);
        // continue from there to find next /
for (AAA_start = AAA_end-1; *AAA_start != '/'; --AAA_start);
        // Now you have the beginning and end of AAA

        // Now you can do whatever you want with AAA and BBB, for example
char *AAA = new char[AAA_end-AAA_start+2];  // AAA_end is included in the result
                                            // hence +1. Another +1 for the NULL
char *BBB = new char[BBB_end-BBB_start+2];
memcpy(AAA, AAA_start, AAA_end-AAA_start+1);
memcpy(BBB, BBB_start, BBB_end-BBB_start+1);
AAA[AAA_end-AAA_start+1] = NULL;
BBB[BBB_end-BBB_start+1] = NULL;

这是基本的想法。现在您需要为此添加错误检查:

char *path = ... /* fill this however you like, for example function argument */
char *AAA_start, *AAA_end;
char *BBB_start, *BBB_end;
for (BBB_end = path+strlen(path); *BBB_end != '.' && BBB_end != path; --BBB_end);
if (BBB_end == path) return FAIL;
for (BBB_start = BBB_end; *BBB_start != '/' && BBB_start != path; --BBB_start);
if (BBB_start == path) return FAIL;
for (AAA_end = BBB_start-1; *AAA_end != '/' && AAA_end != path; --AAA_end);
if (AAA_end == path) return FAIL;
for (AAA_start = AAA_end-1; *AAA_start != '/' && AAA_start != path; --AAA_start);
if (AAA_start == path && *AAA_start != '/') return FAIL;

char *AAA = new char[AAA_end-AAA_start+2];
char *BBB = new char[BBB_end-BBB_start+2];
memcpy(AAA, AAA_start, AAA_end-AAA_start+1);
memcpy(BBB, BBB_start, BBB_end-BBB_start+1);
AAA[AAA_end-AAA_start+1] = NULL;
BBB[BBB_end-BBB_start+1] = NULL;

答案 3 :(得分:0)

正则表达式可以解决这个问题:

#include <boost/regex.hpp>
#include <iostream>
#include <cstdlib>

int main() {
    std::string path("/some/path/to/a/file/AAA/xxx/BBB.cc");

    boost::regex path_re(".+/([^/]+)/[^/]+/([^.]+)\\.(.+?)", boost::regex::perl);
    boost::smatch m;
    if(regex_match(path, m, path_re)) {
        std::cout << "part 1 " << m[1] << '\n';
        std::cout << "part 2 " << m[2] << '\n';
        std::cout << "part 3 " << m[3] << '\n';
    }
    else {
        abort();
    }
}

输出:

part 1 AAA
part 2 BBB
part 3 cc

请注意,它不处理其中包含/./元素的非规范路径。