查找字符串是不是包含 C++ 中的字符(允许提升)
Posted
技术标签:
【中文标题】查找字符串是不是包含 C++ 中的字符(允许提升)【英文标题】:Find if a string contains a character in C++ (boost allowed)查找字符串是否包含 C++ 中的字符(允许提升) 【发布时间】:2012-12-25 06:40:24 【问题描述】:假设我有一个字符串,并且我想查找是否存在特定字符(如“|”),那么最好和最快的技术是什么?我知道字符串查找实现。我要求比这个更快的实现。
【问题讨论】:
查看std::string
引用,您最终会找到find
。
取决于您使用的字符串的“形式”。
请避免在标题中使用“最佳”和“最快”;前者应该[几乎]总是被避免,因为它几乎没有增加价值(“最佳”方法将在“最佳”答案中给出),而后者应该被避免,除非有一个特定的测试用例/场景,其中常见的方法“不够快”(这需要先拥有一些东西来比较它!)
@chris 我知道字符串查找,但有什么比我的问题更有效的吗。
没有比这更有效的方法了。 O(n) 是你能做的最好的。标准库的实现应该是最佳的。
【参考方案1】:
使用std::string::find
if (str.find('|') != std::string::npos)
// ...
没有什么比这更有效了。 O(n) 是你能做的最好的。标准库的实现应该是非常理想的。
【讨论】:
【参考方案2】:来自this source 使用 Visual Studio 2013 编译器完成的经验测试表明,strchr 例程比 std::string::find 快大约 2 倍 strong> 实施。
【讨论】:
【参考方案3】:补充汤姆坦纳的答案。如果您不想进行任何先验计算,您将陷入 O(n),即您正在搜索的字符串的长度与时间消耗之间存在线性相关性。 Tom 建议设置一个布尔数组(或向量)来指示某个字符是否出现。它需要 O(n) 一次来索引字符串,但是如果包含它,您可以检查 O(1) (恒定时间)中的任意数量的字符。这种方法的缺点是您将需要大量内存(一旦您决定需要支持 unicode)。
作为一种折衷方案,您可以使用 std::set 或类似的方法,仅存储输入字符串中实际存在的字符。内存消耗将与字符串中不同字符的数量呈线性关系,但查找时间为 O(log n),即时间上的对数。
当然,您应该测量/分析,然后在这里解释您实际优化的用例。在您这样做之前,请坚持使用最容易理解和阅读的内容。
【讨论】:
【参考方案4】:另一种方法是在对应的c_str字符串上使用strchr函数:
if(strchr(str.c_str(), '|'))
\\found
虽然不确定它与 std find 在速度方面的比较...
找到的字符的位置是
size_t pos = strchr(str.c_str(),'|') - str.c_str();
【讨论】:
"如果找不到字符,函数返回一个空指针"。因此,在您的示例中,在这种情况下,您将从 NULL 指针中减去。指针溢出是 UB。 @namezero 这就是为什么我们在尝试通过减法获取 pos 之前先使用 if 语句,所以如果找不到字符,我们就不会尝试获取 pos。 @Peter 是的,显然我们需要提供我们正在寻找的角色..(固定)【参考方案5】:只有一种方法可以做到这一点。只需遍历字符串以检查您正在寻找的字符是否存在。您可以使用string::find
函数来执行此操作,该函数获取一个字符并返回它在字符串中出现的第一个位置,如果该值不存在,则返回string::npos
。您还可以使用std::find
,它获取两个迭代器begin
和end
以及一个键值'k',并返回一个迭代器,该迭代器指向[begin, end]
或end
范围内第一次出现的k k
未找到。当然,你也可以自己实现 find 函数,像这样:
string::size_type pos=string::npos;
for(string::size_type i=0; i<s.size(); ++i)
if(s[i] == key)
pos=i;
break;
if(pos != string::npos)
// key was found
else
// not found
或者这个:
string::iterator pos=s.end();
for(string::iterator i=s.begin(); i!=s.end(); ++i)
if(*i == key)
pos=i;
break;
if(pos != s.end())
// found
else
// not found
更多关于std::string::find
和std::find
:
【讨论】:
【参考方案6】:鉴于您想要比 string::find 更快的语句,我唯一能想到的就是创建一个具有高度自定义赋值运算符的类,该类在每次更新字符串时都会更新一个内部表,其中包含每个可能字符在字符串中的第一个位置(char 字符串为 256,宽字符串为 65536(?))。这需要 O(1) 查找,但代价是非常量操作增加了相当多的复杂性。
【讨论】:
【参考方案7】:你可以试试这个:
string s1 = "Hello";
string s2 = "el";
if(strstr(s1.c_str(),s2.c_str()))
cout << " S1 Contains S2";
【讨论】:
以上是关于查找字符串是不是包含 C++ 中的字符(允许提升)的主要内容,如果未能解决你的问题,请参考以下文章