Vaibhav Katre
Vaibhav Katre

Reputation: 59

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!!

Upvotes: 1

Views: 1254

Answers (2)

SAIF ALI KHAN
SAIF ALI KHAN

Reputation: 1

# This is my different solution to this question #



char vowels[] = "AEIOUaeiou";
int vowel = 0, consonants = 0, space = 0;
for (int i = 0; str[i] != '\0'; i++)
{
    if (str[i] == ' ')
    {
        space++;
    }

    for (int j = 0; vowels[j] != '\0'; j++)
    {
        if (vowels[j] == str[i])
        {
            vowel++;
        }
    }
}
consonants = strlen(str) - (vowel + space);

Upvotes: 0

Yun
Yun

Reputation: 3812

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:

  • The typical signature of the main function, using no parameters, is int main(void).
  • The scanf version fails if the input is a single newline character. Both versions fail on no input. It is always a good idea the check the return values of input (and output) functions.
  • Inside of the for-loop, you could create a copy of the current character converted to lowercase using the tolower function, and then perform only the lowercase comparisons. I.e.:
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]);
}
  • Another option is to replace the comparisons in the if-statement with a call to strchr, which makes the program a bit more generic and scalable (one string is more easily changed than multiple comparisons):
char ch = tolower(str[i]);
if (strchr("aeiou", ch) != NULL)
    printf("Vowels in the string are: %c \n", str[i]);

Upvotes: 3

Related Questions