-1

I'm a beginner in c++ and i made a code mentions how many times a character existed in a string :-

#include <string>
#include <iostream>
using namespace std;
int main(){
int s=0;
int l=0;
int o=0;
int w=0;
int y=0;
string boo="slowly";
for (size_t j = 0; j < boo.size(); j++) {
while (boo[j] == 's') {
s=s+1;
break;}
while (boo[j] == 'l')
{
l=l+1;
break;}
while (boo[j] == 'o') {
o=o+1;
break;}
while (boo[j] == 'w') {
w=w+1;
break;}
while (boo[j] == 'y') {
y=y+1;
break;}}

cout <<"s ="<<s<<endl;
cout <<"l ="<<l<<endl;
cout <<"o ="<<o<<endl;
cout <<"w ="<<w<<endl;
cout <<"y="<<y<<endl;
system("pause");
return 0;
}

I was wondering how to make a code that automatically detect the character in the string and apply the condition on it without making a while loop for every single alphabet character and making int variables for every character ?

**Excuse my bad Englihs

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
Dreamer
  • 25
  • 5
  • 1
    Possible duplicate of [Count character occurrences in a string](http://stackoverflow.com/questions/3867890/count-character-occurrences-in-a-string) – LogicStuff Mar 05 '16 at 11:49
  • 1
    No sir i don't want exact character i want to automatically detect every character in the string and mention how many times every character repeated – Dreamer Mar 05 '16 at 11:52

5 Answers5

1

You can use a map to keep track of the different character counts. You iterate through the input once, and for each character look it up in the map. If it doesn't already exist in the map, a new entry will be created with the value 0.

After you've created the map where each entry has the character as the key, and the number of occurrences as the value, you iterate through the map and print each entry.

#include <iostream>
#include <map>
#include <string>

int main()
{
    std::string input = "slowly";

    std::map<char, int> occurrences;

    for (char character : input)
    {
        occurrences[character] += 1;
    }

    for (auto& entry : occurrences)
    {
        std::cout << entry.first << '=' << entry.second << std::endl;
    }
}
user764486
  • 160
  • 5
0

Use a little trick. First, observe that all lower-case characters are encoded with numeric codes in ascending order:

      ASCII EBCDIC
'a' - 97    129
'b' - 98    130
'c' - 99    131
...
'z' - 122   169

The codes may not be consecutive, as in the case of EBCDIC, but that does not matter: make an int array of sufficient size, walk through your string, and for each lowercase character ch mark index ch-'a'. The expression represents the distance between the character code and the beginning of the alphabet.

Now you can walk the array of ints, and print the corresponding character by performing the inverse translation of index i:

 char ch = 'a'+i;

Here is a complete example:

string s;
getline(cin, s);
int seen['z'-'a'+1] {0};
for (int i = 0 ; i != s.size() ; i++) {
    char ch = s[i];
    if (!islower(ch))
        continue;
    seen[ch-'a']++;
}
for (int i = 0 ; i != 'z'-'a'+1 ; i++) {
    if (seen[i]) {
        cout << (char)('a'+i) << " - " << seen[i] << endl;
    }
}

Demo.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
0

Try this:

#include <string>
#include <iostream>
using namespace std;
int main(){
   int s=0,l=0,o=0,w=0,y=0;
   string boo="slowly";
   for (int j = 0; j < boo.size(); j++) {
       switch(boo.charAt(j)){
            case 's':
               s++;
               break;
            case 'l':
               l++;
               break;
            case 'o':
               o++;
               break;
            case 'w':
               w++;
               break;
            case 'y':
               y++;
               break;
       }
   }
   cout <<"s ="<<s<<endl;
   cout <<"l ="<<l<<endl;
   cout <<"o ="<<o<<endl;
   cout <<"w ="<<w<<endl;
   cout <<"y="<<y<<endl;
   system("pause");
   return 0;
}
0

If your compiler supports C++ 2011 then you can write the following way providing that letters will be listed in the order in which they are present in the string

#include <iostream>
#include <string>
#include <map>

int main()
{
    std::string s( "slowly" );
    auto comp = [&]( char c1, char c2 ) { return s.find( c1 ) < s.find( c2 ); };
    std::map<char, int, decltype( comp )> m( comp );

    for ( char c : s ) ++m[c];

    for ( auto p : m ) std::cout << p.first << ": " << p.second << std::endl;
}    

The program output is

s: 1
l: 2
o: 1
w: 1
y: 1

Otherwise if the compiler does not support C++ 2011 then instead of the lambda you have to use a function class defined before main. Also youi should substitute the range-based for loop for an ordinary loop.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

I guess the algorithm-header of the STL will help you:

std::string boo="slowly";
std::cout << "s = " << std::count(boo.cbegin(), boo.cend(), 's') << std::endl;
JVApen
  • 11,008
  • 5
  • 31
  • 67