用C语言数一数一系列弦中元音的数目

问题描述 投票:0回答:1

我正在用C语言编写一个程序,它可以计算一系列由用户决定的字符串中的元音数,甚至连字符串的元素数也由用户决定。问题是这个函数给出的元音数总是相同的,也就是第一个字符串的元音数。

下面是代码。

#include <stdio.h>
#include <string.h>

int vowels(char str[]);

int main(){
    int n, i, x;

    printf("How many strings do you want to insert?");
    scanf("%d", &n);

    printf("How many characters per string?");
    scanf("%d", &x);
    char str[x];

    if(x < 10){
        for(i = 0; i < n; i++){
            printf("Insert a string:");
            scanf("%s", str);

            if(strlen(str) == x){
                vowels(str);
            }
            else{
                printf("Error\n");
            }
        }
    }
    else{
        printf("Error: the number of characters must be < 10");
    }

    return 0;
}

int vowels(char str[]){
    int i, j;

    while(str[i] != '\0'){
        if(str[i] == 'a' || str[i] == 'A' || str[i] == 'e' || 
           str[i] == 'E' || str[i] == 'i' || str[i] == 'I' || 
           str[i] == 'o' || str[i] == 'O' || str[i] == 'u' || 
           str[i] == 'U'){
            j++; }
    i++;
    }

    printf("Number of vowels in the string:%d\n", j); 

return 0;
}

c string counting
1个回答
1
投票

你的代码包含两个错误。

  1. i 和... j 指数 vowels() 函数没有初始化,所以它们包含垃圾,会导致你的循环行为不可预测。这是因为局部变量与全局变量不同,默认情况下不初始化为0。

请使用

int i=0, j=0;
  1. 缓冲区 char str[x]; 将不能包含一个带有x字符的字符串。事实上,字符串结束符 '\0'.

所以应该是

char str[x+1];

做了这些改动后,你的代码就可以用了。

但是... ...

...但这还不够。事实上,当你得到输入的字符串时,你并没有执行任何检查,以检索到的字符数。

scanf("%s", str);

通过插入一个很长的字符串,你会发现 出界 远超 str 字符串,导致未定义的行为,很可能导致程序崩溃。

如何解决这个问题? 由于您的输入字符串的最大长度可以是9,因此只需定义一个 定长阵列:

char str[11];

为什么是11号? 首先,你的数组必须包含最多9个字符和结束符。所以是10。但它也必须包含一个额外的字符,所以可以检测到超过9个字符的输入。

之后,只要接收输入字符串,并加上

scanf("%10s", str);

通过这种方式,所有合法的输入字符串都可以被存储(从大小1到大小9)。所有长10个或更多字符的字符串将被截断为10个字符的长字符串,你的长度检查将失败。

请注意,在长字符串的情况下,所有超过前10个字符的字符将在本产品的 stdin 缓冲区。所以,如果出现错误,你需要一个机制来消耗这些字符,否则你会在下一个 scanf. 我写了这个技巧。

while( fgets( str, 10, stdin ) != NULL )
{
    if( strlen(str) < 10 )
        break;
}

经过我描述的所有修改后得到的代码就是下面这个

#include <stdio.h>
#include <string.h>

int vowels(char str[]);

int main(){
    int n, i, x;

    printf("How many strings do you want to insert?");
    scanf("%d", &n);

    printf("How many characters per string?");
    scanf("%d", &x);

    if(x < 10){
        char str[11];
        for(i = 0; i < n; i++){
            printf("Insert a string:");
            scanf("%10s", str);

            if(strlen(str) == x){
                vowels(str);
            }
            else{
                printf("Error\n");
                while( fgets( str, 10, stdin ) != NULL )
                    if( strlen(str) < 10 )
                        break;
            }
        }
    }
    else{
        printf("Error: the number of characters must be < 10");
    }

    return 0;
}

int vowels(char str[]){
    int i=0, j=0;

    while(str[i] != '\0')
    {
        if(str[i] == 'a' || str[i] == 'A' || str[i] == 'e' || 
           str[i] == 'E' || str[i] == 'i' || str[i] == 'I' || 
           str[i] == 'o' || str[i] == 'O' || str[i] == 'u' || 
           str[i] == 'U')
        {
            j++;
        }
    i++;
    }

    printf("Number of vowels in the string:%d\n", j); 

    return 0;
}

1
投票

我把你的代码粘贴过来,并在里面加上注释 注意:我并不是在修正什么,只是指出来让你修正。

#include <stdio.h>
#include <string.h>

int vowels(char str[]);

int main(){
  int n, i, x;

  printf("How many strings do you want to insert?");
  scanf("%d", &n);  // Consider a more descriptive variable name than 'n'

  printf("How many characters per string?");
  scanf("%d", &x);  // Consider a more descriptive name here too.
  char str[x];  // Note, a string needs 1 extra character for the NUL character.

  if(x < 10){  // 10 is a very magic number.  Consider making a constant.  
    for(i = 0; i < n; i++){
      printf("Insert a string:");
      scanf("%s", str);

      if(strlen(str) == x){
        vowels(str);
      }
      else{
        printf("Error\n"); // Consider breaking or returning here if error...
      }
    }
  }
  else{
    printf("Error: the number of characters must be < 10");
  }

  return 0;
}

int vowels(char str[]){  // Do you need a return value?  What does it represent?
  int i, j;

  while(str[i] != '\0'){  // i and j are not initialized (to 0).  Turning on compiler warnings would catch this.  
//  a for() loop may make more sense
    if(str[i] == 'a' || str[i] == 'A' || str[i] == 'e' || 
       str[i] == 'E' || str[i] == 'i' || str[i] == 'I' || 
       str[i] == 'o' || str[i] == 'O' || str[i] == 'u' || 
       str[i] == 'U'){
      j++; }
    i++;
  }

  printf("Number of vowels in the string:%d\n", j); 

  return 0;  // Again, maybe this function returns void if we don't need a return.
}

1
投票

其中的问题 vowels 函数是由未初始化的变量引起的。无论是 i 也不 j 被赋予一个初始值。一个好的编译器会对此产生一个警告。如果你是用gcc或clang编译,请确保用 -Wall -Wextra. 然后阅读警告,并修复 的警告。

变量 i 可以声明和初始化一个 for 循环,如下图所示。变量 j 应该给它一个更有描述性的名字,如 count,并在循环前初始化。你可能还想返回 count 来自 vowels 函数,并让 main 进行打印。这样,你就可以重复使用 vowels 函数在另一个需要计算元音但又不想打印计数的程序中。

int vowels(char str[]){
    int count = 0;

    for (int i=0; str[i] != '\0'; i++){
        if(str[i] == 'a' || str[i] == 'A' || str[i] == 'e' || 
           str[i] == 'E' || str[i] == 'i' || str[i] == 'I' || 
           str[i] == 'o' || str[i] == 'O' || str[i] == 'u' || 
           str[i] == 'U'){
             count++; 
        }
    }

    return count;
}

程序中的另一个问题是 str 数组太小。C 字符串使用一个零字节(称为 NUL 结束符)来标记字符串的结束。所以,举例来说,如果 strlen 字符串的长度为5,那么存放字符串的数组必须至少有6个字节,5个为字符串,加上一个NUL。

在你的程序中,你将字符串长度限制为小于10的数字,因此你可以直接声明 str 数组的固定大小,如 char str[16],它将永远足够大。OTOH, the scanf 不会限制写入字符串的字符数,除非你让它这么做。下面的代码显示了如何限制写进字符串的字符数 scanf 写入字符串中。

int main(){
    int n, x;

    printf("How many strings do you want to insert?");
    scanf("%d", &n);

    printf("How many characters per string?");
    scanf("%d", &x);
    char str[16];

    if(x < 10){
        for(int i = 0; i < n; i++){
            printf("Insert a string:");
            if (scanf("%15s", str) != 1) {
                printf("That wasn't a valid input\n");
                break;
            }
            else if(strlen(str) == x){
                int count = vowels(str);
                printf("Number of vowels in the string:%d\n", count); 
            }
            else{
                printf("Error\n");
                break;
            }
        }
    }
    else{
        printf("Error: the number of characters must be < 10");
    }

    return 0;
}
© www.soinside.com 2019 - 2024. All rights reserved.