我有一个文件路径,来自__FILE__
宏,我想从中提取2个。
格式为:/some/path/to/a/file/AAA/xxx/BBB.cc
。我想要AAA
和BBB
路径。 xxx
通常是src,inc,tst等,文件扩展名通常是.cc,但不能保证。
我知道我可以使用string.find()
甚至将字符串拆分为/
字符上的数组,但考虑到所需的搜索次数,这两种字符似乎都不高效。我想到了sscanf
,并认为这可能是最好的方法,但是,我无法定义格式,以便它将跳过开头的大部分并获得我需要的部分。我如何使用sscanf
来执行此操作,还是有更好的方法?
感谢您的帮助。
答案 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)
自己写这篇文章比尝试让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
请注意,它不处理其中包含/./
元素的非规范路径。