在C中优化for()循环

在C中优化for()循环,c,for-loop,optimization,C,For Loop,Optimization,我的老师说我可以优化这个for()循环,但我不知道如何优化,任何帮助都是很好的 void vowels(char strng[]) { int i, j, word_len, vowels_len, vowel_count; char vowels[] = "aeiouAEIOU"; word_len = strlen(strng); vowels_len = strlen(vowels); vowel_count = 0; for (i = 0; i < word_len;

我的老师说我可以优化这个for()循环,但我不知道如何优化,任何帮助都是很好的

void vowels(char strng[])
{
int i, j, word_len, vowels_len, vowel_count;
char vowels[] =  "aeiouAEIOU";
word_len = strlen(strng);     
vowels_len = strlen(vowels);
vowel_count = 0;

for (i = 0; i < word_len; ++i) {         
    for (j = 0; j < vowels_len; ++j) {   
       if (strng[i] == vowels[j]) {
           ++vowel_count;
           break;
       }
    }
}

printf("%s: %d vowels\n", strng, vowel_count);    
}
无效元音(char strng[]
{
int i,j,单词,元音,元音计数;
字符元音[]=“aeiouAEIOU”;
单词_len=strlen(strng);
元音=strlen(元音);
元音计数=0;
对于(i=0;i
一种方法是完全删除嵌套循环,将其替换为一个数组,该数组将字符代码映射到一个标志,指示
char
是否为元音:

int isVowel[256] = {0};
for (int i = 0 ; vowels[i] != '\0' ; i++) {
    isVowel[(unsigned char)vowels[i]] = 1;
}
现在主回路可以优化如下:

for (int i = 0; i != word_len ; i++) {         
    vowel_count += isVowel[(unsigned char)string[i]];
}
使用
开关
语句,您可以获得相当的性能:

for (int i = 0; i != word_len ; i++) {
    switch(string[i]) {
        case 'a':
        case 'e':
        case 'i':
        case 'o':
        case 'u':
        case 'A':
        case 'E':
        case 'I':
        case 'O':
        case 'U':
            vowel_count ++;
            break;
    }
}

一种方法是完全删除嵌套循环,将其替换为将字符代码映射到指示
char
是否为元音的标志的数组:

int isVowel[256] = {0};
for (int i = 0 ; vowels[i] != '\0' ; i++) {
    isVowel[(unsigned char)vowels[i]] = 1;
}
现在主回路可以优化如下:

for (int i = 0; i != word_len ; i++) {         
    vowel_count += isVowel[(unsigned char)string[i]];
}
使用
开关
语句,您可以获得相当的性能:

for (int i = 0; i != word_len ; i++) {
    switch(string[i]) {
        case 'a':
        case 'e':
        case 'i':
        case 'o':
        case 'u':
        case 'A':
        case 'E':
        case 'I':
        case 'O':
        case 'U':
            vowel_count ++;
            break;
    }
}

比Dasblinkenlight更简单的优化是:

char vowels[] =  "AEIOU";
vowels_len = sizeof(vowels)-1;
    ...
    for (char c=strng[i]&~32, j = 0; j < vowels_len; ++j) {
        if (c == vowels[j]) {
char元音[]=“AEIOU”;
元音_len=sizeof(元音)-1;
...
for(char c=strng[i]&~32,j=0;j<元音_len;++j){
if(c==元音[j]){

c&~32
在ascii中更为突出。)

一个比DasLinkenLight更简单的优化是:

char vowels[] =  "AEIOU";
vowels_len = sizeof(vowels)-1;
    ...
    for (char c=strng[i]&~32, j = 0; j < vowels_len; ++j) {
        if (c == vowels[j]) {
char元音[]=“AEIOU”;
元音_len=sizeof(元音)-1;
...
for(char c=strng[i]&~32,j=0;j<元音_len;++j){
if(c==元音[j]){

(<代码> C和32 是ASCII中的ToupP.)

< P >不确定你的老师是否会考虑这种作弊,但这是一种可能比使用2个嵌套循环更能优化元音的方法。
char *pos;
int vowel_count=0;

pos=strng;
while(pos)
    {
    pos=strpbrk(pos,"aeiouAEIOU");
    if(pos)
        {  
        vowel_count++;
        pos++;
        }
    }

不确定你的老师是否会考虑这种作弊行为,但这是一种寻找元音的方法,它比使用2个嵌套循环更为合适。

char *pos;
int vowel_count=0;

pos=strng;
while(pos)
    {
    pos=strpbrk(pos,"aeiouAEIOU");
    if(pos)
        {  
        vowel_count++;
        pos++;
        }
    }

为了优化代码,您必须首先了解瓶颈是什么。在算法级别,您有以下基本性能问题:

  • 您必须意识到
    strlen
    遍历整个字符串以搜索空终止符,因此您遍历同一字符串
    strng
    两次。这是低效的-最好在检查数据的同时检查空终止符
  • 文本
    “aeiouAEIOU”
    是一个常量,因此您知道它在编译时的大小。无需在运行时使用strlen()计算它。您可以使用
    sizeof
    ,它在编译时进行计算
  • 通过同时检查大写和小写,您可以加倍工作。相反,暂时将您要查找的字符转换为大写,然后只在大写元音中查找匹配项
您还有一个主要错误,即函数不返回结果

因此,“天真”手动优化的第一步是这样的:

#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>

int vowels(const char str[])
{
  const char VOWEL_LOOKUP[] = "AEIOU";
  int vowel_count = 0;

  for(; *str != '\0'; str++)
  {
    char ch = toupper(*str);
    for(size_t i=0; i<sizeof(VOWEL_LOOKUP)-1; i++)
    {
      if(ch == VOWEL_LOOKUP[i])
      {
        vowel_count++;
        break;
      }
    }
  }

  return vowel_count;
}


int main (void)
{
  const char str[] = "Stack Overflow"; // 4 vowels 
  printf("%s: %d vowels\n", str, vowels(str));
}
#包括
#包括
#包括
int元音(const char str[])
{
常量字符元音查找[]=“AEIOU”;
int元音_计数=0;
对于(;*str!='\0';str++)
{
char ch=touper(*str);

对于(size_t i=0;i='A'&&ch为了优化代码,您必须首先了解瓶颈是什么。在算法级别上,您有以下基本性能问题:

  • 您必须意识到
    strlen
    遍历整个字符串以搜索空终止符,因此您遍历同一字符串
    strng
    两次。这是低效的-最好在检查数据的同时检查空终止符
  • 文本
    “aeiouAEIOU”
    是一个常量,因此您知道它在编译时的大小。无需在运行时使用strlen()计算它。您可以使用
    sizeof
    ,它在编译时进行计算
  • 通过同时检查大写和小写,您可以加倍工作。相反,暂时将您要查找的字符转换为大写,然后只在大写元音中查找匹配项
您还有一个主要错误,即函数不返回结果

因此,“天真”手动优化的第一步是这样的:

#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>

int vowels(const char str[])
{
  const char VOWEL_LOOKUP[] = "AEIOU";
  int vowel_count = 0;

  for(; *str != '\0'; str++)
  {
    char ch = toupper(*str);
    for(size_t i=0; i<sizeof(VOWEL_LOOKUP)-1; i++)
    {
      if(ch == VOWEL_LOOKUP[i])
      {
        vowel_count++;
        break;
      }
    }
  }

  return vowel_count;
}


int main (void)
{
  const char str[] = "Stack Overflow"; // 4 vowels 
  printf("%s: %d vowels\n", str, vowels(str));
}
#包括
#包括
#包括
int元音(const char str[])
{
常量字符元音查找[]=“AEIOU”;
int元音_计数=0;
对于(;*str!='\0';str++)
{
char ch=toupper(*str);
对于(size_t i=0;i='A'&&ch有史以来最快的事情

void ultravowulator(const char strng[])
{
    char vowels[] = "aeiouAEIOU";
    int vowelscnt = strlen(vowels);    
    int vocabular[256] = {0};   

    for(; *strng != '\0'; strng++) {    
        vocabular[*strng]++;
    }

    int total = 0;
    for (int i = 0; i < vowelscnt; i++){        
        total += vocabular[vowels[i]];
    }
    cout << total << endl;
}

main()
{
    char word[] = "Stack overflow";
    ultravowulator(word);
}
void超调器(const char strng[]
{
字符元音[]=“aeiouAEIOU”;
int元音lscnt=strlen(元音);
int-vocabular[256]={0};
对于(;*strng!='\0';strng++){
声带[*strng]++;
}
int-total=0;
对于(int i=0;i
void ultravowulator(const char strng[])
{
    char vowels[] = "aeiouAEIOU";
    int vowelscnt = strlen(vowels);    
    int vocabular[256] = {0};   

    for(; *strng != '\0'; strng++) {    
        vocabular[*strng]++;
    }

    int total = 0;
    for (int i = 0; i < vowelscnt; i++){        
        total += vocabular[vowels[i]];
    }
    cout << total << endl;
}

main()
{
    char word[] = "Stack overflow";
    ultravowulator(word);
}
void超调器(const char strng[]
{
字符元音[]=“aeiouAEIOU”;
int元音lscnt=strlen(元音);
int-vocabular[256]={0};
对于(;*strng!='\0';strng++){
声带[*strng]++;
}
int-total=0;
对于(int i=0;i如果(strng[i]='a'| | strng[i]='e'…)可以生成一个长if语句,而不是内部for循环你可以在书中或网上了解更多关于循环展开的知识,这是循环优化的技术之一。优化的目标是什么?性能、代码大小、可维护性、可读性、兼容性?还有
toupper()
tolower()
和带有
大小写'a':大小写'E':…元音_count++;break;
switch
语句,而不是c的内部循环