Прежде всего настоятельно рекомендую сначала ознакомиться с основами языка, а также используемыми вами функциями ввода вывода. Язык С очень прост: если вы хотите выстрелить себе в ногу, вы стреляете.
Беглый просмотр вашего кода показывает, что вы не заботитесь о входных данных. Например, вот эта конструкция хоть и позволяет вам считать строку, но не даёт никаких гарантий, что она не превысит размер в 21 символ.
#define N 21
...
char str[N];
printf("Enter a string no more than 20 symbols :\n\n");
gets(str);
А вот здесь вы наивно надеетесь, что у строки точно есть конец.
for (int i=0; str[i] != '\0'; i++)
Язык С очень прост: если вы хотите считать строку, вы её считаете. Но какой вы её получите - это ваша проблема.
Что до вашей задачи, то, полагаю, самым простым способом в вашем случае будет цикл в цикле: главным циклом вы проходитесь по полученной строке, побочными циклами ищите совпадения в ваших справочниках (массивы vovels и тд) и при нахождении оного либо выводите сразу, либо копируете символ куда-либо для вывода позже.
Вы значительно упростите код в этой части, если посмотрите таблицу ASCII.
Задача ограничения длины решается, например, чтением справочника языка -
all-ht.ru/inf/prog/c/func/fgets.html - или просто бесцеремонным обрубанием введённой строки. Для принуждения повторного ввода, думаю, вам подойдёт while либо do while - что больше нравится.