在字符串中查找元音

Find vowels in a string

下面是我在给定字符串中查找元音的代码:

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

int main() {
    char str[100];
    int i, str_length;

    //scanf("%[^\n]%*c", &str[100]);
    fgets(str, sizeof(str), stdin);
    str_length = strlen(str);
    for (i = 0; i < str_length; i++) {
        if (str[i] == 'a' || str[i] == 'e' ||
            str[i] == 'i' || str[i] == 'o' || 
            str[i] == 'u' || str[i] == 'A' ||
            str[i] == 'E' || str[i] == 'I' ||
            str[i] == 'O' || str[i] == 'U')
        {
            printf("Vowels in the string are: %c \n", str[i]);
        }
    }
    return 0;
}

我只想知道,为什么 scanf("%[^\n]%*c",&str[100]) 在我的代码中不起作用? 因为我尝试使用 scanf 多次执行我的程序,但没有成功。

在使用 fgets 之后我得到了想要的输出。

所以,谁能帮我理解一下,我哪里错了!!

scanf 函数调用中,这个 &str[100] 接受一个指向 str 的指针,使其指向索引为 100 的元素(这是数组末尾之后的元素) ),取消引用它,然后获取该(不存在的)元素的地址。这很可能会导致尝试进行无效写入,这可能会被终止程序的操作系统捕获。无论如何,字符串都没有写入正确的位置。

相反,您希望参数指向 str 的第一个元素的内存位置,即:

scanf("%[^\n]%*c", str);

也就是说,使用 fgets 更好,因为它接受防止缓冲区溢出的大小参数。也可以给 scanf 一个大小,但是因为它是格式说明符的一部分,所以它不能是一个变量;只有一个硬编码常量:

scanf("%99[^\n]%*c", str);

请注意,这是针对 99 元素的,因为空终止符 ([=20=]) 也需要有空间。有关 scanf 的更多信息,请参阅 here。但同样,使用 fgets 不太容易出错,因此更受欢迎。

一些额外的建议:

  • 不使用参数的 main 函数的典型签名是 int main(void)
  • 如果输入的是单个换行符,scanf 版本将失败。两个版本都在没有输入时失败。检查输入(和输出)函数的 return 值总是一个好主意。
  • 在 for 循环内部,您可以使用 tolower 函数创建将当前字符转换为小写的副本,然后仅执行小写比较。即:
for (i = 0; i < str_length; i++) {
    char ch = tolower(str[i]);
    if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u')
        printf("Vowels in the string are: %c \n", str[i]);
}
  • 另一种选择是将 if 语句中的比较替换为对 strchr 的调用,这使程序更加通用和可扩展(一个字符串比多次比较更容易更改):
char ch = tolower(str[i]);
if (strchr("aeiou", ch) != NULL)
    printf("Vowels in the string are: %c \n", str[i]);