我有string s="home/dir/folder/name"
我想在s
和s1="home/dir/folder"
s2="name";
我做了:
char *token = strtok( const_cast<char*>(s.c_str() ), "/" );
std::string name;
std::vector<int> values;
while ( token != NULL )
{
name=token;
token = strtok( NULL, "/" );
}
现在s1=name
。那么s2
呢?
答案 0 :(得分:7)
我建议不要使用strtok
。请改为Boost Tokenizer(这里有一些examples)。
或者,要简单地找到上一个'/'
的位置,您可以使用std::string::rfind
:
#include <string>
#include <iostream>
int main() {
std::string s = "home/dir/folder/name";
std::string::size_type p = s.rfind('/');
if (p == std::string::npos) {
std::cerr << "s contains no forward slashes" << std::endl;
} else {
std::string s1(s, 0, p);
std::string s2(s, p + 1);
std::cout << "s1=[" << s1 << "]" << std::endl;
std::cout << "s2=[" << s2 << "]" << std::endl;
}
return 0;
}
答案 1 :(得分:4)
如果您的目标只是获取\
中最后/
或string
的位置,则可以使用string::find_last_of来完成此操作。
从那里,您可以使用string::substr或std::string
的构造函数来获取所需的子部分。
只需确保原始字符串至少包含\
或/
,或者您正确处理案例。
这是一个执行您需要的功能,并返回包含路径两部分的pair
。如果指定的路径不包含任何\
或/
个字符,则整个路径将作为该对的第二个成员返回,并且第一个成员为空。如果路径以/
或\
结尾,则第二个成员为空。
using std::pair;
using std::string;
pair<string, string> extract_filename(const std::string& path)
{
const string::size_type p = path.find_last_of("/\\");
// No separator: a string like "filename" is assumed.
if (p == string::npos)
return pair<string, string>("", path);
// Ends with a separator: a string like "my/path/" is assumed.
if (p == path.size())
return pair<string, string(path.substr(0, p), "");
// A string like "my/path/filename" is assumed.
return pair<string, string>(path.substr(0, p), path.substr(p + 1));
}
当然,您可以修改此函数以抛出错误,而不是在路径没有预期格式时正常退出。
答案 2 :(得分:1)
查看 boost string split 。
示例:
string str1("hello abc-*-ABC-*-aBc goodbye");
typedef vector< iterator_range<string::iterator> > find_vector_type;
find_vector_type FindVec; // #1: Search for separators
ifind_all( FindVec, str1, "abc" ); // FindVec == { [abc],[ABC],[aBc] }
typedef vector< string > split_vector_type;
split_vector_type SplitVec; // #2: Search for tokens
split( SplitVec, str1, is_any_of("-*"), token_compress_on );
// SplitVec == { "hello abc","ABC","aBc goodbye" }
答案 3 :(得分:1)
有几点:首先,您使用strtok
是未定义的行为;在
在g ++的情况下,它甚至可能导致一些非常奇怪的行为。您
无法修改字符串后面的std::string
的内容
并期望逃脱它。 (const_cast
的必要性应该
已经给你了。)
其次,如果你要操纵文件名,我强烈反对
推荐boost::filesystem
。它知道像路径这样的事情
分隔符等,以及路径的最后一个组成部分
通常是特殊的(因为它可能是文件名,而不是目录)。
第三,如果这只是一个,或者由于其他原因你不能或 不想使用Boost:
std::string::const_iterator pivot
= std::find( s.rbegin(), s.rend(), '/' ).base();
将为最后一个'/'之后的第一个字符提供迭代器,或者 如果没有一个字符串,则为字符串中的第一个字符。之后, 使用string的两个迭代器构造函数来获取它是一个简单的方法 两个组成部分:
std::string basename( pivot, s.end() );
std::string dirname( s.begin(), pivot == s.begin() ? pivot : pivot - 1 );
如果您以后必须支持Windows,只需将find
替换为:
static std::string const dirSeparators( "\\/" );
std::string::const_iterator pivot
= std::find_first_of( s.rbegin(), s.rend(),
dirSeparators.begin(), dirSeparators.end() );
答案 4 :(得分:0)
您无法在strtok
上使用std::string
。
strtok
会修改字符串。它违反了c_str()
合同。
执行const_cast<>
是出错的重要标志。
答案 5 :(得分:0)
只需使用字符串方法:
std::string s="home/dir/folder/name"
std::string::size_type n = s.find_last_of("/");
std::string s1 = s.substr(0,n);
if (n != std::string::npos) // increment past the '/' if we found it
{ ++n;
}
std::string s2 = s.substr(n);
两点建议: