计算C中一系列字符串中元音的数量
Count the number of vowels in a series of strings in C
我正在用 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] != '[=10=]'){
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;
}
我正在粘贴您的代码并添加内嵌注释。注意:我没有修复任何东西,只是指出要修复的地方。
#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] != '[=10=]'){ // 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.
}
vowels
函数中的问题是由未初始化的变量引起的。 i
和 j
都没有给出初始值。一个好的编译器会生成一个警告。如果您使用 gcc 或 clang 进行编译,请务必使用 -Wall -Wextra
进行编译。然后阅读警告,并修复所有的警告。
变量i
可以用for
循环声明和初始化,如下所示。应该给变量 j
一个更具描述性的名称,例如 count
,并在循环之前对其进行初始化。您可能还想 return 来自 vowels
函数的 count
,然后让 main
进行打印。这样,您可以在需要计算元音但不希望打印计数的不同程序中重用 vowels
函数。
int vowels(char str[]){
int count = 0;
for (int i=0; str[i] != '[=10=]'; 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 为 1。
在您的程序中,您将字符串长度限制为小于 10 的数字,因此您可以只声明具有固定大小的 str
数组,例如char str[16]
,而且永远够大。 OTOH, 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;
}
您的代码包含两个错误:
i
和 j
函数的 vowels()
索引未初始化,因此它们包含垃圾并且会导致循环出现不可预测的行为。这是因为局部变量与全局变量不同,默认情况下不会初始化为 0。
改用
int i=0, j=0;
- 缓冲区
char str[x];
将无法包含具有 x 个字符的字符串。实际上,字符串终止字符'[=21=]'
. 所要求的space
所以应该是
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] != '[=16=]')
{
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 编写一个程序,它计算用户决定的一系列字符串中元音的数量,甚至字符串的元素数量也由用户决定。问题是该函数总是给出相同数量的元音,这是第一个字符串中的一个。
代码如下:
#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] != '[=10=]'){
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;
}
我正在粘贴您的代码并添加内嵌注释。注意:我没有修复任何东西,只是指出要修复的地方。
#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] != '[=10=]'){ // 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.
}
vowels
函数中的问题是由未初始化的变量引起的。 i
和 j
都没有给出初始值。一个好的编译器会生成一个警告。如果您使用 gcc 或 clang 进行编译,请务必使用 -Wall -Wextra
进行编译。然后阅读警告,并修复所有的警告。
变量i
可以用for
循环声明和初始化,如下所示。应该给变量 j
一个更具描述性的名称,例如 count
,并在循环之前对其进行初始化。您可能还想 return 来自 vowels
函数的 count
,然后让 main
进行打印。这样,您可以在需要计算元音但不希望打印计数的不同程序中重用 vowels
函数。
int vowels(char str[]){
int count = 0;
for (int i=0; str[i] != '[=10=]'; 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 为 1。
在您的程序中,您将字符串长度限制为小于 10 的数字,因此您可以只声明具有固定大小的 str
数组,例如char str[16]
,而且永远够大。 OTOH, 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;
}
您的代码包含两个错误:
i
和j
函数的vowels()
索引未初始化,因此它们包含垃圾并且会导致循环出现不可预测的行为。这是因为局部变量与全局变量不同,默认情况下不会初始化为 0。
改用
int i=0, j=0;
- 缓冲区
char str[x];
将无法包含具有 x 个字符的字符串。实际上,字符串终止字符'[=21=]'
. 所要求的space
所以应该是
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] != '[=16=]')
{
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;
}