C++ 计算字符串中的元音数

C++ 计算字符串中的元音数,c++,algorithm,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<strl

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

#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;
}
#包括
使用名称空间std;
int main()
{
无符号整数vow_cnt=0;
字符名称[15]=“sijith aeu”;
库特
  • 不要对strlen(name)
  • 进行测试。在循环外计算一次长度
  • 使用整数数组将字符映射为增量(0或1)
  • 忽略第1点和第2点
  • 不要优化等待某人输入姓名然后在该姓名上循环的代码。效率极低的算法大约花费99.999%的时间等待用户输入。

    查找表可能更快:

    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'];
    

    对于短字符串,这可能会较慢,因为必须为您测试的每个字符串清除
    字符数数组。不过,它有可能会产生大量数据。

    重要的部分是:

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

    考虑到您的假设,即只有一个EIO u是元音,并且字符串都是小写的,请尝试以下方法: 当然,在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);
    
    • 主要是清理升级。清理代码->减少bug
    • 使用标准算法(查找、计数)
    • 使用std::string
    • 检查错误
    • 使用最新的标题
    按流行需求编辑:也许我也应该以适当的样式(?)显示案例转换:) 该链接显示以下输入的输出

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

    我的新发明更具进取心,它也支持你的自定义角色类型!看:

    #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;
    }
    
    #包括//避免旧式MSVC++头!
    
    #包括根据特定区域设置获取的代码…它将是偶数.Woot。

    对于类似的内容,我有两个通用函数,您可以将其用于任何用途(甚至是商业用途),第三个是适合您需要的函数(未经测试):

    count元音只返回计数。虽然函数本身可以修改为计数任何字符,包括大写和小写等。

    可能是这样吗

    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;
         }
    
    
       } 
    }
    
    string元音=“aeiou”
    string query=“dsdlfjsdofkpdsofkdsfdfsoede”;
    int count元音=0;
    for(int i=0;i
    首先,一些答案建议使用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
    }
    
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    使用名称空间std;
    const int MAXN=100;//或任何您想要的值。
    char x[MAXN];
    国际频率[26+1];
    char元音[]=“aeiouy”//或任何你想要的:D
    无效填充频率(){
    对于(int i=0;i>x;
    填充频率();
    int nVowels=strlen(元音);
    int ans=0;
    for(int i=0;iCUT你证明它是慢的吗?为什么你要优化它?<代码> <代码>应该是<代码> <代码>。也可以考虑使用<代码> STD::String 。@日高看起来不像C。IoString、命名空间、CUT、CIN…@哈罗德Car(15)代替STD::String,Strunor,换句话说,我对回答人们的问题感兴趣,并显示他们的C或C++或两者,无论他们想知道什么。我并不十分关心我的答案是否会在他们的作业作业中给他们评分。所以如果他们说C++,我认为扔高功率C++是很好的。但是,这看起来很像家庭作业,任务可能是人工的(算法复杂性与C++入门课程结合),根据实现,编译器可以优化多个调用到<代码> STLLN(Name)< /C>(gcc是这样做的,
    strlen
    函数被标记为纯函数,在这种特殊情况下,编译器可以证明对
    strlen(name)
    的多次调用的结果都将返回相同的值,从而对注入的临时函数执行一次预先调用,然后仅使用该值)--这是另一个先测量和分析然后关心优化的原因。无论如何,这是一个合理的建议:无论何时,只要知道结果不会改变,就避免调用。看看编译器可以为自己提升strlen
    strlen
    name
    vow\u cnt
    都是自动变量,这会很有趣ce不可能是别名,因此优化器不难看出它是一个有效的优化。比我的答案更全面,尽管没有完整的“元音肯定不是你想象的那样。”触摸:)@是的。我没有错过它。我选择了不解决它。如果我知道一个地区设施来分类元音,我会使用it@pmr:好吧,我屈服了。你说得对。让代码更有趣
    CountVowels(Array,strlen(Array);
    
    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;
         }
    
    
       } 
    }
    
    #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
    }