开发者

Count no of vowels in a string

I wrote a program to count no of vowels in a string but its not efficient or optimized code. Moreover it will not check caps vowels.

#include<iostream.h>
using namespace std;
int main()
{
unsigned int vow_cnt=0;
char name[15]= "sijith aeu";
cout<<"Enter a name"<<endl;
cin>>name;
for(unsigned int i=0;i<strlen(name);i++)
{ 
  if(name[i] == '开发者_如何学Goa' || name[i] == 'e'||name[i] == 'i'||name[i] == 'o'||name[i] == 'u')
  { 
   vow_cnt++;
  }
 }
cout<<"vow_cnt"<< vow_cnt << endl;
}


Considering your assumption that only a e i o u are vowels and that your string is all lowercase, try this: Of course this going to fail horribly in unicode or for every language that has a different set of vowels.

bool is_vowel(char x) {
  // order by probability of occurrence in the target language
  // e.g. start with e for English
  // nb see comments for further details
  return (x == 'e' || ...); 
}

std::string foo;
long nbVowels = std::count_if(foo.begin(), foo.end(), is_vowel);


  1. Don't test against strlen(name). Compute the length once outside the loop.
  2. Use an array of integers to map from characters to increments (0 or 1).
  3. Ignore points 1 and 2.

Don't optimise code that waits for a person to enter their name and then loops over that name. Your exceedingly inefficient algorithm spends about 99.999% of its time waiting for user input.


  • Mainly cleanupped. Clean code -> less bugs
  • Use standard algorithms (find, count_if)
  • Use std::string
  • Check errors
  • Use up-to-date headers

See it live: http://ideone.com/E6QJy

Edit By popular demand: perhaps I should show case conversion in proper style (?) too :) The link shows output for the following input

krk#!@#^&*
AEIOUÄËÏÖÜÁÉÍÓÚÀÈÌÒÙÂÊÎÔÛðتº
aeiouäëïöüáéíóúàèìòùâêîôûã°øªº

For the record, this is what we had:

static inline bool isvowel(char ch)
{
        static const std::string vowels("aeiouEAIOU");
        return vowels.end() != std::find(vowels.begin(), vowels.end(), ch);
}

My new contraption is far more enterprisey, and it supports your custom character types too! Behold:

#include <iostream>   // avoid old style MSVC++ header!
#include <algorithm>
#include <iterator>
#include <locale>
#include <string>

template <typename T=char>
    struct isvowel
{
    bool operator()(T ch) const
    {
        static std::basic_string<T> vowels("aeiouäëïöüáéíóúàèìòùâêîôûã°øªº"); // etc. for specific languages...
        static int _init = 0;

        while (!_init++) // not thread safe :)
        {
            vowels.reserve(vowels.size()*2);
            // upper case dynamically based on locale, e.g. AEIOUÄËÏÖÜÁÉÍÓÚÀÈÌÒÙÂÊÎÔÛðتº
            std::transform(vowels.begin(), vowels.end(), std::back_inserter(vowels), (int(*)(int)) std::toupper);
        }
        return vowels.end() != std::find(vowels.begin(), vowels.end(), ch);
    }
};

int main()
{
    std::setlocale(LC_ALL, "German"); // set relevant locale for case conversions
    std::cout << "Enter a name: ";

    std::string name;

    while (std::cin >> name) // handle errors?
    {
        size_t vow_cnt = std::count_if(name.begin(), name.end(), isvowel<char>());
        std::cout << "vow_cnt: " << vow_cnt << std::endl;
    }

    return 0;
}

Now if anyone can share authoritative code to get the collection of vowels according to a specific locale... It'll be even more enterprisey. Woot.


Just the important part:

const char *p = name;
while(*p)
  switch(*p++) 
  {
  case 'a': case 'e': case 'i': case 'o': case 'u':
  case 'A': case 'E': case 'I': case 'O': case 'U':
    vow_cnt++;
  }


A look-up table might be faster:

char isvowel[UCHAR_MAX+1] = { 0 }; // or int instead of char, try both
isvowel['a'] = 1;
isvowel['e'] = 1;
isvowel['i'] = 1;
isvowel['o'] = 1;
isvowel['u'] = 1;
isvowel['A'] = 1;
isvowel['E'] = 1;
isvowel['I'] = 1;
isvowel['O'] = 1;
isvowel['U'] = 1;

...

  if (isvowel[(unsigned)name[i]]) vow_cnt++;

You could also try letting the compiler decide how to optimize, by using a switch:

switch(name[i]) {
    case 'a':
    case 'e':
    case 'i':
    case 'o':
    case 'u':
    case 'A':
    case 'E':
    case 'I':
    case 'O':
    case 'U':
        ++vow_cnt;
    default:
}

Then again, either or both might be slower. You'd have to test it with more realistic data, since "optimizing" a program that only processes one short string is pretty futile. It will be effectively instantaneous whatever you do, so don't waste your own time. Performance only matters if you're processing a lot of data, so either one enormous string or lots of strings.

ASCII has a trick, that name[i] is a particular letter (either case) if and only if name[i] | 0x20 is that letter (lower case). You can use that to halve the number of case labels or (with care) the size of the lookup table. That may or may not affect performance.

If you want to try a completely different approach, see how it performs, you can take the complicated logic and branching out of the loop:

size_t charcounts[UCHAR_MAX+1] = { 0 };
char *p = name;

while (*p) {
    ++charcounts[(unsigned)*p];
    ++p;
}

vow_cnt = charcounts['a'] + charcounts['e'] + ... + charcounts['U'];

This is likely to be slower for short strings, since the charcounts array has to be cleared for each string you test. It has a chance for large amounts of data, though.


For things like that, I have two generic functions, which you can use for any purpose (even commericial), and the third one is the one adapted to your needs (untested though):

const bool IsChar(const char Target, const char Source, const bool CaseInsensitive = false)
{
    if(Target == Source){ return true; }
    if(CaseInsensitive)
    {
        if( (Source >= 'A') && (Source <= 'Z') )
        {
            if( (Source+32) == Target ){ return true; }
        }

        if( (Source >= 'a') && (Source <= 'z') )
        {
            if( (Source-32) == Target ){ return true; }
        }
    }
    return false;
}

const bool IsCompareChar(const char C, const char CompareChars[], const bool CaseInsensitive = false)
{
    while((*CompareChars))
    {
        if(IsChar(C,*CompareChars,CaseInsensitive)){ return true; }
        CompareChars++;
    }
    return false;
}

const unsigned int CountVowels(const char Array[], const unsigned int Length)
{
    unsigned int N = 0, NumberOfVowels = 0;
    while(N < Length)
    {
        if(IsCompareChar(Array[N],"aioue",true))
        {
            NumberOfVowels++;
        }
    }
    return NumberOfVowels;
}

However, given what you're doing is meant to teach you about coding, I would advise, rather than copying and pasting the given code, you write your own version, given a specific function for a role is more optimised than a generic function.

In main, you'd merely call it by:

CountVowels(Array,strlen(Array);

CountVowels will merely return the count. Although the function itself can be modified to count any character, both upper and lower case etc etc.


First of all, some answers recommended using std :: string, which I don't. It's much slower than using the regular char [] array structure. For counting the vowels more efficiently, you can use a letter frequency count instead, something like this:

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <cstring>
using namespace std;
const int MAXN = 100; // Or whatever you want it to be.
char x[ MAXN ];
int freq[ 26 + 1 ];
char vowels[ ] = "aeiouy" // Or whatever you want it to be too :D
void fillFrequency() {
    for( int i = 0; i <= 26; i ++ ) {
        freq[ i ] = 0;
    }
    int len = strlen( x );
    for( int i = 0; i < len; i ++ ) { 
        freq[ x[ i ] - 'a' ] ++;
    }
}
int main() {
    cin >> x;
    fillFrequency();
    int nVowels = strlen( vowels );
    int ans = 0;
    for( int i = 0; i < nVowels; i ++ ) {
        ans += freq[ vowels[ i ] - 'a' ];
    }
    cout << ans << '\n';
    return 0; // That's it! :D
}

Hope that helps :D


Maybe this way?

string vowels = "aeiou"
string query = "dsdlfjsdofkpdsofkdsfdfsoedede"  ;
int countVowels =0;
for(int i =0 ; i < query.length() ; i++)
{
  int j=0;
  while(j < vowels.length())
  {
     if(query[i] == vowels[j++])
     {
        countVowels++,break;
     }


   } 
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜