在C++中统计字符串中字符出现的次数

276

如何计算类似于"bla_bla_blabla_bla"这样的字符串中"_"出现的次数?

15个回答

555
#include <algorithm>

std::string s = "a_b_c";
std::string::difference_type n = std::count(s.begin(), s.end(), '_');

29
第三个参数是 char 类型,即单引号,而不是双引号... - Emerson Xu
2
这是最好的答案。 - Konchog
2
小笔记,但是返回类型通常为有符号的。不知何故,std::count 返回类型为 iterator_traits<InputIt>::difference_type,对于大多数标准容器来说,这是 std::ptrdiff_t,而不是 std::size_t - Daniel Stevens
正如 @DanielStevens 指出的那样,std :: count返回值所保存的变量应该是 std :: string :: difference_type类型以获取最大的正确性。我提交了一个编辑答案的请求:std :: string :: difference_type n = std :: count(s.begin(),s.end(),'_'); - FriskySaga
5
这可能是使用auto的好例子。 ;) - Daniel Stevens
@EmersonXu,是的 - 给出的答案甚至无法编译。/usr/include/c++/9/bits/predefined_ops.h:241:17: 错误:ISO C++禁止指针和整数之间的比较[-fpermissive] 241 | { return *__it == _M_value; } | ~~~~~~^~~~~~~~~~~ - Raleigh L.

40
伪代码:
count = 0
For each character c in string s
  Check if c equals '_'
    If yes, increase count

编辑:C++示例代码:
int count_underscores(string s) {
  int count = 0;

  for (int i = 0; i < s.size(); i++)
    if (s[i] == '_') count++;

  return count;
}

请注意,这是与`std::string`一起使用的代码。如果您正在使用`char*`,请将`s.size()`替换为`strlen(s)` - 但是将其分配给`for`循环外的变量,以避免在每次循环迭代中扫描整个字符串。
另外请注意:我理解您希望尽可能地“小”,但我建议您改用这个解决方案。正如您所见,您可以使用一个函数来封装代码,这样您就不必每次都编写`for`循环,而只需在代码的其他部分使用`count_underscores("my_string_")`即可。在这里,使用高级C++算法当然是可能的,但我认为这是过度设计。

39
我们可以通过使用lambda函数和bind2nd()调用来创建一个完全无法阅读的模板版本,但不会改变原意。 - Martin Beckett
@Martin 我其实正在考虑这个问题。不幸的是,我的 C++ 函数式编程基本上是一窍不通。 - jdmichal
14
我认为调用 Web 服务比使用 Lambda 更有趣,因为核心算法不仅难以理解,而且存储在其他地方。 - Ben Voigt
1
这不是作业问题。我对C++很新,没有足够的知识以高级方式编程。尽可能简单。我能用for循环等简单方式编程,但我正在寻找一种复杂的解决方案,类似于Diego的解决方案。下次我会提供更多关于问题原因的信息。 - andre de boer
此外,如果您不想要重复项,您需要消耗连续出现的内容。例如,计算通过所需字符拆分字符串后可以获得多少个片段。 - TheRealChx101
如果你正在使用char*,请用strlen(s)替换s.size()。如果只是这样做而没有其他代码修改,你将会在每次循环迭代中调用strlen并扫描整个字符串,使得实现变为二次方。为了避免这种情况,需要缓存字符串的长度。 - Sergey Shevchenko

36

使用名称恰当的旧式解决方案。这使得代码有些灵性。

#include <cstdio>
int _(char*__){int ___=0;while(*__)___='_'==*__++?___+1:___;return ___;}int main(){char*__="_la_blba_bla__bla___";printf("The string \"%s\" contains %d _ characters\n",__,_(__));}

编辑:大约8年后,看着这个答案,我感到很惭愧(即使我当初是把它当作对一个低质量问题的讽刺)。这是有害的,不好的。我不会删除这篇帖子;我会添加这个道歉来帮助改变 StackOverflow 的氛围。所以 OP:我道歉,并希望你在我的恶作剧之下能正确完成你的作业,而像我这样的答案没有让你放弃在该网站上参与。


5
认真的吗?你觉得故意模糊的回答是你能做到的最好的,而且你认为这在这里是合适的吗? - Roger Pate
5
@Tamas:在C++中,int(true)始终为1。 - Roger Pate
8
一个真正的老派解决方案会声明 sprintf 的原型,而不是 #包含整个头文件! - John Dibling
7
@Tamas:当然不是,但我在“回答”初学者的问题时并没有感到开心。 - Roger Pate
13
喜欢它。可惜它违反了双下划线规则。 - Martin York
显示剩余12条评论

16

使用 lambda 函数来检查字符是否为“_”,如果是,则仅增加计数,否则不是有效字符

std::string s = "a_b_c";
size_t count = std::count_if( s.begin(), s.end(), []( char c ){return c =='_';});
std::cout << "The count of numbers: " << count << std::endl;

5
请添加解释 - 尽量不要仅发布代码块。 - CertainPerformance
1
你认为你的回答提供了什么之前的回答还没有涵盖的内容?请编辑并扩展你的回答。 - hellow
1
非常感谢您提供的代码片段,它可能会立即带来一些有限的帮助。一个适当的解释将极大地提高其长期价值,因为它展示了为什么这是解决问题的好方法,并使它对未来遇到类似问题的读者更有用。请[编辑]您的回答,添加一些解释,包括您所做的假设。 - Tim Diekmann
3
正如@phuclv建议的那样,这里也必须加上return false语句:size_t count = std::count_if( s.begin(), s.end(), []( char c ){if(c =='_') return true; else return false; }); - Zbyšek Zapadlík
3
不需要if语句size_t count = std::count_if( s.begin(), s.end(), []( char c ){ return c == '_'; }); - JoJo Brandon Coffman
显示剩余2条评论

15
#include <boost/range/algorithm/count.hpp>

std::string str = "a_b_c";
int cnt = boost::count(str, '_');

8

在字符串中统计字符出现次数很容易:

#include <bits/stdc++.h>
using namespace std;
int main()
{
    string s="Sakib Hossain";
    int cou=count(s.begin(),s.end(),'a');
    cout<<cou;
}

5
这与六年前的最佳答案相同,这意味着什么?区别在于:这个答案使用了错误的头文件。stdc++.h是专门为GCC设计的,即使对于该编译器,它也只用于预编译头文件。 - Arthur Tacca
9
推荐阅读:为什么不应该使用 #include <bits/stdc++.h>? - Lightness Races in Orbit

8
你想要什么...Lambda版本...:)
using namespace boost::lambda;

std::string s = "a_b_c";
std::cout << std::count_if (s.begin(), s.end(), _1 == '_') << std::endl;

你需要包含几个文件...我把这留给你作为练习...

10
你真的认为新手会理解这些吗? - Josh Stodola
2
@Josh:这似乎是一些评论中幼稚的笑声的衍生。 (Note: I kept the hyperlink in English as it is a website URL) - Roger Pate
6
世界上一些顶尖的程序员已经花费了过去15年的时间来发展C++,以至于我们可以编写这个 - 这并不幼稚! - Martin Beckett
11
略去 include 是荒谬的。 - PascalVKooten
3
为什么要增加复杂度,当std::count已经可以满足所有需求? - 463035818_is_not_a_number
显示剩余4条评论

4
我会这样做:

我会这样做:

#include <iostream>
#include <string>
using namespace std;
int main()
{

int count = 0;
string s("Hello_world");

for (int i = 0; i < s.size(); i++) 
    {
       if (s.at(i) == '_')    
           count++;
    }
cout << endl << count;
cin.ignore();
return 0;
}

4

std::string有几种搜索方法,但find可能是您要查找的内容。如果您指的是C风格字符串,则相当于strchr。但是,在任何一种情况下,您也可以使用for循环并检查每个字符-循环本质上就是这两个方法包装起来的。

一旦您知道如何在给定起始位置查找下一个字符,您将不断推进搜索(即使用循环),并随着前进计数。


2
您可以使用字符串函数找出源字符串中“_”的出现次数。 find()函数需要2个参数,第一个是要查找其出现次数的字符串,第二个参数是起始位置。while循环用于在源字符串结束之前找到所有出现次数。 示例:
string str2 = "_";
string strData = "bla_bla_blabla_bla_";

size_t pos = 0,pos2;

while ((pos = strData.find(str2, pos)) < strData.length()) 
{
    printf("\n%d", pos);
    pos += str2.length();
} 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接