如何从字符串中删除子字符串
how to remove substring from string c++
我有一个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
呢?
我不建议使用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
。如果指定的路径不包含任何或
/
字符,则返回整个路径作为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));
}
当然,您也可以修改此函数,使其在路径不具有预期格式时抛出错误,而不是优雅地退出。
几点:首先,您使用strtok
是未定义行为;在对于g++,它甚至可能导致一些非常奇怪的行为。你不能修改std::string
后面字符串的内容并期望逃脱惩罚。(const_cast
的必要性应该我已经给你通风报信了
其次,如果您要操作文件名,我强烈推荐boost::filesystem
。它知道所有的东西,比如路径分隔符之类的,以及路径的最后一个组成部分通常是特殊的(因为它可以是文件名,而不是目录)。
第三,如果这只是一个one-of,或者由于其他原因,您不能或不希望使用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() );
查看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" }
不能在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);
两个建议:
- 永远不要使用strtok
- 如果您正在使用文件系统路径,请查看boost::filesystem
- 如果你想玩一般的标记化使用流操作符
- 或boost::tokenizer
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 如何从给定字符串中删除第二次和第三次出现的$
- 在C++的字符串中搜索和删除某些字符
- 从 C 样式字符串中删除子字符串 "in place" 在C++代码中
- 使用另一个字符串从字符串中删除空格
- 删除/替换C++字符串中的多字符 (ÿû)
- 删除所有字符串后如何恢复 QStringList?
- 如何删除字符串中的前 2 个字符(如果它有"-")
- 根据新的行分隔符从字符串中删除子字符串
- C ++,如何从控制台中输入的字符串中删除字母?
- 删除字符串后C++检测到堆损坏
- 我正在尝试使用 while 循环从字符串中删除字母,直到没有字母。我在这里做错了什么?
- 如何在 c++ 中删除字符串中的某些字符?
- 删除字符串数组
- 删除字符串中具有相同值的任何相邻字母"pair"
- 高效的字符串截断算法,按顺序删除相等的前缀和后缀
- 如何使用双黑斜杠从字符串中删除单反斜杠
- 如何在编译时从string_view中删除子字符串?
- 从文件中读取多行.txt字符串删除空格并创建新文件进行输出
- c字符串 删除非字母/非空格字符 - C++