271

How can I count the number of "_" in a string like "bla_bla_blabla_bla"?

Cœur
  • 37,241
  • 25
  • 195
  • 267
andre de boer
  • 3,124
  • 3
  • 17
  • 15

15 Answers15

550
#include <algorithm>

std::string s = "a_b_c";
std::string::difference_type n = std::count(s.begin(), s.end(), '_');
Nathan Phillips
  • 11,899
  • 1
  • 31
  • 24
Benoit
  • 76,634
  • 23
  • 210
  • 236
  • 2
    This is the best answer. – Konchog Feb 11 '20 at 14:48
  • 2
    Small note, but the return type is typically signed. For some reason [`std::count`](https://en.cppreference.com/w/cpp/algorithm/count) returns type `iterator_traits::difference_type`, which for most standard containers is [`std::ptrdiff_t`](https://en.cppreference.com/w/cpp/types/ptrdiff_t), not `std::size_t`. – Daniel Stevens Apr 15 '20 at 07:48
  • As @DanielStevens pointed out, the variable holding the return value of [`std::count`](https://en.cppreference.com/w/cpp/algorithm/count) should be of type `std::string::difference_type` for maximum correctness. I submitted a request to edit the answer to write: `std::string::difference_type n = std::count(s.begin(), s.end(), '_');` – FriskySaga Oct 16 '21 at 23:03
  • 5
    This might be a good case to use `auto`. ;) – Daniel Stevens Oct 18 '21 at 06:22
  • @EmersonXu, yup -- the answer as given doesn't even compile. ``` /usr/include/c++/9/bits/predefined_ops.h:241:17: error: ISO C++ forbids comparison between pointer and integer [-fpermissive] 241 | { return *__it == _M_value; } | ~~~~~~^~~~~~~~~~~ ``` – Raleigh L. Nov 24 '21 at 22:03
40

Pseudocode:

count = 0
For each character c in string s
  Check if c equals '_'
    If yes, increase count

EDIT: C++ example code:

int count_underscores(string s) {
  int count = 0;

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

  return count;
}

Note that this is code to use together with std::string, if you're using char*, replace s.size() with strlen(s) - but assign that to a variable outside the for loop to avoid scanning the whole string on every loop iteration.

Also note: I can understand you want something "as small as possible", but I'd suggest you to use this solution instead. As you see you can use a function to encapsulate the code for you so you won't have to write out the for loop everytime, but can just use count_underscores("my_string_") in the rest of your code. Using advanced C++ algorithms is certainly possible here, but I think it's overkill.

schnaader
  • 49,103
  • 10
  • 104
  • 136
  • 39
    Surely we can come up with a totally unreadable templated version with lamba functions and a bind2nd() call ? – Martin Beckett Oct 05 '10 at 21:33
  • @Martin I was actually thinking of that. Unfortunately my grasp of C++ functional programming is practically non-existent. – jdmichal Oct 05 '10 at 21:34
  • 14
    I think calling a web service would be much more fun than lambdas, then the core algorithm isn't just inscrutable, it's stored elsewhere. – Ben Voigt Oct 05 '10 at 21:35
  • 1
    This is no homework question. I am new to c++ and don't have enough knowledge of c++ to program this in a advanced manner. Read: as small as possible. I am able to program this in a simple manner with a for loop and so on, but I was looking for an sophisticated solution, something like the solution of Diego. Next time I will give more information for the reason of the question. – andre de boer Oct 06 '10 at 07:41
  • Also, you'd want to consume contiguous occurrences in case you did not want duplicates. Like for instance, counting how many pieces you'd get after splitting a string by the desired character. – TheRealChx101 Jun 23 '16 at 01:26
  • > if you're using char*, replace s.size() with strlen(s). If you do just that with no other code modifications, you'll end up calling `strlen` and scanning the entire string on every loop iteration, making the implementation quadratic. The string length would need to be cached to avoid that. – Sergey Shevchenko Aug 10 '23 at 01:00
36

Old-fashioned solution with appropriately named variables. This gives the code some spirit.

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

Edit: about 8 years later, looking at this answer I'm ashamed I did this (even though I justified it to myself as a snarky poke at a low-effort question). This is toxic and not OK. I'm not removing the post; I'm adding this apology to help shifting the atmosphere on StackOverflow. So OP: I apologize and I hope you got your homework right despite my trolling and that answers like mine did not discourage you from participating on the site.

Tamás Szelei
  • 23,169
  • 18
  • 105
  • 180
  • Also, doesn't test the first character. Switch to do-while to fix. – Ben Voigt Oct 05 '10 at 21:57
  • While that might work in practice, `true` does not equal 1, but an arbitrary value which is not 0. – Tamás Szelei Oct 05 '10 at 22:01
  • 5
    Seriously? A purposefully obfuscated answer is the best you can do and you think it would ever be appropriate here? –  Oct 05 '10 at 22:02
  • 5
    @Tamas: int(true) is always 1 in C++. –  Oct 05 '10 at 22:02
  • 1
    @Roger: Are you always taking yourself so seriously? – Tamás Szelei Oct 05 '10 at 22:04
  • 8
    a truly old fashioned solution would declare a prototype for sprintf instead of #including a *whole header file*! – John Dibling Oct 05 '10 at 22:05
  • 7
    @Tamas: Of course not, but I don't have my fun while "answering" beginners' questions. –  Oct 05 '10 at 22:08
  • 13
    Love it. Shame it violates the double underscore rule. – Martin York Oct 05 '10 at 22:12
  • You could replace some _ with $ signs (not sure if it is legal but it works with gcc) – Martin York Oct 05 '10 at 22:17
  • @Martin: That's a gcc extension. –  Oct 05 '10 at 22:22
  • Why doesn't `int main()` return anything? – hkBattousai Aug 17 '13 at 17:08
  • @hkBattousai in C++, you can leave the return statement out from main, and it will return zero. For other functions, it will also compile, but will be undefined behavior. – Tamás Szelei Aug 17 '13 at 17:51
  • It seems that I found an error: `printf` has to be changed into `std::printf` when using `` – Wolf Apr 02 '14 at 10:28
  • I was not aware, that's a fair point. This is specified in the paragraph 17.6.1.2.4 of the C++11 standard (I only have the [latest draft](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n3242.pdf), not the finished version). In practice though, are there any compilers that implement this? – Tamás Szelei Apr 02 '14 at 10:43
  • This has undefined behavior, double underscore identifiers are [reserved in any scope](https://stackoverflow.com/a/228797), I realize this was intended as a joke or something but I'd recommend editing this into something more constructive. – jrh Aug 12 '20 at 12:40
  • 1
    Frankly, this is the kind of snarky sh*t that keeps me from really participating here and drove me towards Reddit instead, nice effort with the apology, this is a drop in an ocean of toxicity but always nice to see... – Tab Nov 17 '22 at 22:59
  • 1
    @Tab You can experience such behavior everywhere. The only thing you can do is growing a thick skin, expressing your distaste and quickly moving along. No need to focus on the bad apples if the basket is full of healthy ones. – ashrasmun Feb 24 '23 at 14:17
16

Using the lambda function to check the character is "_" then the only count will be incremented else not a valid character

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;
MatejC
  • 2,167
  • 1
  • 18
  • 25
Nagappa
  • 194
  • 2
  • 13
  • 5
    Please add an explanation - try not to post just plain blocks of code alone. – CertainPerformance Aug 07 '18 at 04:32
  • 1
    What do you think, that your answer offers, what a previous answer hasn't already covered? Please edit and expand your answer. – hellow Aug 07 '18 at 06:40
  • 1
    Thank you for this code snippet, which might provide some limited, immediate help. A [proper explanation would greatly improve its long-term value](//meta.stackexchange.com/q/114762/206345) by showing _why_ this is a good solution to the problem, and would make it more useful to future readers with other, similar questions. Please [edit] your answer to add some explanation, including the assumptions you've made. – Tim Diekmann Aug 07 '18 at 08:52
  • Used the lambda function to check the character is "_" then only count will be incremented else not a valid character. – Nagappa Sep 05 '18 at 09:56
  • 1
    `[]( char c ){if(c =='_') return true; }` invokes undefined behavior because you didn't return a value in all code paths – phuclv Jun 30 '20 at 09:33
  • 3
    as @phuclv suggested, there must be also return false statement `size_t count = std::count_if( s.begin(), s.end(), []( char c ){if(c =='_') return true; else return false; });` – Zbyšek Zapadlík Jan 26 '21 at 12:39
  • 3
    You don't need the if statement `size_t count = std::count_if( s.begin(), s.end(), []( char c ){ return c == '_'; });` – JoJo Brandon Coffman May 17 '21 at 17:04
15
#include <boost/range/algorithm/count.hpp>

std::string str = "a_b_c";
int cnt = boost::count(str, '_');
user1977268
  • 151
  • 1
  • 2
8

Count character occurrences in a string is easy:

#include <bits/stdc++.h>
using namespace std;
int main()
{
    string s="Sakib Hossain";
    int cou=count(s.begin(),s.end(),'a');
    cout<<cou;
}
Eric Leschinski
  • 146,994
  • 96
  • 417
  • 335
Md. Sakib Hossain
  • 237
  • 1
  • 3
  • 8
  • 5
    -1 This is the same as the existing top answer from six years earlier – what was this meant to add? There is one difference: this answer uses the wrong header file. stdc++.h is specific to GCC, and even with that compiler it's only intended for use in precompiled headers. – Arthur Tacca Jun 24 '18 at 19:25
  • 9
    **Recommended reading:** [Why should I not #include ?](https://stackoverflow.com/q/31816095/560648) – Lightness Races in Orbit Oct 24 '18 at 10:22
8

You name it... Lambda version... :)

using namespace boost::lambda;

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

You need several includes... I leave you that as an exercise...

Diego Sevilla
  • 28,636
  • 4
  • 59
  • 87
  • 10
    Do you really think a newbie is going to understand any of this? – Josh Stodola Oct 05 '10 at 21:56
  • 2
    @Josh: It appears to be a spinoff of the childish laughter in some [comments](http://stackoverflow.com/questions/3867890/count-character-occurrences-in-a-string/3867921#3867921). –  Oct 05 '10 at 22:00
  • 6
    Some of the world's top programmers have spent the last 15years evolving C++ to the point where we can write this - it's not childish! – Martin Beckett Oct 05 '10 at 23:08
  • Making a point that those who do not know Perl are forced to reinvent it (badly) - now that would be childish! – Martin Beckett Oct 05 '10 at 23:09
  • Oh, come on, this can also be fun! :) @Roger: Yes, it was kind of an answer to a fun comment by Martin Beckett above. @Martin: Well, yes, it is not particularly appealing, but in the expression you can see clearly _1 is refering to the first parameter to the "lambda", and that it is being compared using "==" to the character... C++0x lambda are not much better in shape, but at least they are standard :) – Diego Sevilla Oct 05 '10 at 23:40
  • @Diego: I like your answer (and wasn't calling it childish, but the comments), though I think you have much too little explanation for it to be a good answer to this question. I was just trying to show the context to Josh. –  Oct 06 '10 at 00:00
  • @Diego, I guessed that (in a Perl kind of way) but in c shouldn't the first parameter be _0 ? – Martin Beckett Oct 06 '10 at 01:00
  • 11
    It is ridiculous to leave out the includes. – PascalVKooten May 13 '13 at 11:07
  • 2
    why all the complexity when `std::count` already does all what is needed ? – 463035818_is_not_an_ai Jun 22 '19 at 07:50
4

There are several methods of std::string for searching, but find is probably what you're looking for. If you mean a C-style string, then the equivalent is strchr. However, in either case, you can also use a for loop and check each character—the loop is essentially what these two wrap up.

Once you know how to find the next character given a starting position, you continually advance your search (i.e. use a loop), counting as you go.

4

I would have done it this way :

#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;
}
Shivam Jha
  • 182
  • 3
  • 17
2

You can find out occurrence of '_' in source string by using string functions. find() function takes 2 arguments , first - string whose occurrences we want to find out and second argument takes starting position.While loop is use to find out occurrence till the end of source string.

example:

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();
} 
Amruta Ghodke
  • 115
  • 1
  • 3
1

The range based for loop comes in handy

int countUnderScores(string str)
{
   int count = 0;

   for (char c: str)
     if (c == '_') count++;
   
   return count;
}
int main()
{
   string str = "bla_bla_blabla_bla";
   int count = countUnderScores(str);
   cout << count << endl;
}
epix
  • 133
  • 1
  • 9
0

I would have done something like that :)

const char* str = "bla_bla_blabla_bla";
char* p = str;    
unsigned int count = 0;
while (*p != '\0')
    if (*p++ == '_')
        count++;
FruityFred
  • 241
  • 2
  • 8
0

Much simpler in C++23 (May be some C++20 compilers also support)

    //Inputs : Your string,Search criteria
    int num_items = std::ranges::count("bla_bla_blabla_bla",'_');
    
    //Print output
    std::cout << num_items << std::endl; //3
Pavan Chandaka
  • 11,671
  • 5
  • 26
  • 34
-4

Try

#include <iostream>
 #include <string>
 using namespace std;


int WordOccurrenceCount( std::string const & str, std::string const & word )
{
       int count(0);
       std::string::size_type word_pos( 0 );
       while ( word_pos!=std::string::npos )
       {
               word_pos = str.find(word, word_pos );
               if ( word_pos != std::string::npos )
               {
                       ++count;

         // start next search after this word 
                       word_pos += word.length();
               }
       }

       return count;
}


int main()
{

   string sting1="theeee peeeearl is in theeee riveeeer";
   string word1="e";
   cout<<word1<<" occurs "<<WordOccurrenceCount(sting1,word1)<<" times in ["<<sting1 <<"] \n\n";

   return 0;
}
Software_Designer
  • 8,490
  • 3
  • 24
  • 28
-9
public static void main(String[] args) {
        char[] array = "aabsbdcbdgratsbdbcfdgs".toCharArray();
        char[][] countArr = new char[array.length][2];
        int lastIndex = 0;
        for (char c : array) {
            int foundIndex = -1;
            for (int i = 0; i < lastIndex; i++) {
                if (countArr[i][0] == c) {
                    foundIndex = i;
                    break;
                }
            }
            if (foundIndex >= 0) {
                int a = countArr[foundIndex][1];
                countArr[foundIndex][1] = (char) ++a;
            } else {
                countArr[lastIndex][0] = c;
                countArr[lastIndex][1] = '1';
                lastIndex++;
            }
        }
        for (int i = 0; i < lastIndex; i++) {
            System.out.println(countArr[i][0] + " " + countArr[i][1]);
        }
    }
Pramod
  • 1