不计算字符串中元音的数量

时间:2011-09-15 10:20:44

标签: c++ algorithm

我编写了一个程序来计算字符串中没有元音但是它的效率或优化代码不高。 此外,它不会检查大写元音。

#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] == 'a' || name[i] == 'e'||name[i] == 'i'||name[i] == 'o'||name[i] == 'u')
  { 
   vow_cnt++;
  }
 }
cout<<"vow_cnt"<< vow_cnt << endl;
}

8 个答案:

答案 0 :(得分:5)

考虑到您假设只有一个元素是元音并且您的字符串全部为小写,请尝试以下方法: 当然,这会在unicode或每种具有不同元音的语言中失败。

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 :(得分:3)

  1. 不要对strlen(name)进行测试。在循环外部计算一次长度。
  2. 使用整数数组从字符映射到增量(0或1)。
  3. 忽略第1点和第2点。
  4. 不要优化等待某人输入其名称然后循环该名称的代码。你效率极低的算法花费大约99.999%的时间等待用户输入。

答案 2 :(得分:3)

  • 主要清理。清洁代码 - &gt;少虫子
  • 使用标准算法(find,count_if)
  • 使用std :: string
  • 检查错误
  • 使用最新标题

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

编辑受欢迎的需求:也许我应该以适当的风格(?)展示大小写转换:) 该链接显示以下输入的输出

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

记录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);
}

我的新装置更具企业性,它也支持您的自定义角色类型!看哪:

#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;
}

现在,如果有人可以根据特定区域设置共享authoritative代码来获取the collection of vowels ...它甚至会more enterprisey。活泉。

答案 3 :(得分:2)

只是重要部分:

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++;
  }

答案 4 :(得分:1)

查找表可能更快:

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++;

您还可以尝试让编译器通过使用开关来决定如何优化:

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:
}

然后,其中一个或两个可能会更慢。你必须用更真实的数据来测试它,因为“优化”只处理一个短字符串的程序是徒劳的。无论你做什么都会有效,所以不要浪费你自己的时间。性能仅在您处理大量数据时才有意义,因此要么是一个巨大的字符串,要么是很多字符串。

ASCII有一个技巧,name[i]是一个特定的字母(任何一种情况),当且仅当name[i] | 0x20是该字母(小写)时。您可以使用它来将案例标签的数量减半或(小心)查找表的大小。这可能会也可能不会影响绩效。

如果你想尝试一种完全不同的方法,看看它是如何执行的,你可以采用复杂的逻辑并从循环中分支出来:

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

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

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

对于短字符串,这可能会更慢,因为必须为您测试的每个字符串清除charcounts数组。但它有机会获得大量数据。

答案 5 :(得分:0)

对于类似的东西,我有两个通用功能,你可以用于任何目的(甚至是商业用途),第三个是适合你需要的功能(虽然未经测试):

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;
}

然而,鉴于您正在做的是教你编码,我建议,不是复制和粘贴给定的代码,而是编写自己的版本,因为角色的特定功能比通用功能。

主要是,您只需通过以下方式调用它:

CountVowels(Array,strlen(Array);

CountVowels只会返回计数。虽然可以修改函数本身来计算任何字符,包括大写和小写等等。

答案 6 :(得分:0)

也许这样?

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;
     }


   } 
}

答案 7 :(得分:0)

首先,一些答案建议使用std :: string,我不这样做。它比使用常规char []数组结构要慢得多。为了更有效地计算元音,您可以使用字母频率计数,如下所示:

#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
}

希望有所帮助:D