[英]how to remove substring from string c++
我有一個string s="home/dir/folder/name"
我想在s1="home/dir/folder"
和s2="name";
拆分s
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
怎么樣?
我建議不要使用strtok
。 請改為使用Boost Tokenizer (以下是一些示例 )。
或者,要簡單地找到最后一個'/'
的位置,您可以使用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;
}
如果您的目標只是獲取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));
}
當然,您也可以修改此函數以拋出錯誤,而不是在路徑沒有預期格式時正常退出。
查看提升字符串拆分 。
例:
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" }
幾點:首先,你使用strtok
是未定義的行為; 在g ++的情況下,它甚至可能導致一些非常奇怪的行為。 你不能修改std::string
后面的std::string
的內容,並希望能夠逃脫它。 ( const_cast
的必要性應該讓你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() );
你不能在std::string
上使用strtok
。 strtok
會修改字符串。 它打破了c_str()
契約。
執行const_cast<>
是出錯的重要標志。
只需使用字符串方法:
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);
兩點建議:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.