cstringscanf

Find vowels in a string


Given below is my code for finding vowels in a given 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;
}

I just wanna know, why scanf("%[^\n]%*c",&str[100]) is not working in my code? cause I tried executing my program multiple times using scanf but it didn't worked.

And after using fgets I got the desired output.

So, can anyone help me to understand, where I am wrong!!


Solution

  • In the scanf function call, this &str[100] takes a pointer to str, makes it point to the element with the index 100 (which is past the end of the array), dereferences it and then takes the address of that (non-existing) element. This, most likely, leads to an attempt to an invalid write, which is probably caught by the operating system which terminates your program. In any case, the string is not written to the correct location.

    Instead, you want the argument to point to the memory location of the first element of str, i.e.:

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

    That said, using fgets is better as it accepts an argument for the size which prevents buffer overflows. A size can also be given to scanf, but since it is part of the format specifier it cannot be a variable; only a hardcoded constant:

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

    Note that this is for 99 elements, as there needs to be room for the null-terminator (\0) as well. See here for more info on scanf. But again, using fgets is less error prone and to be preferred.

    Some additional advice:

    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]);
    }
    
    char ch = tolower(str[i]);
    if (strchr("aeiou", ch) != NULL)
        printf("Vowels in the string are: %c \n", str[i]);