Andrei Radu
Andrei Radu

Reputation: 109

Deleting consecutive vowels from char array

So I have a homework asking to remove all vowels in a string w/o using an additional string. My problem is that I wanna make it working even if I have some consecutive vowels like aabbbceee, I want it to print bbbc but instead of that it would print something weird.

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

bool isVowel(char a) { 
    if (a == 'a' || a == 'e' || a == 'i' || a == 'o' || a == 'u') return 
       true;
    return false;
}

void main () {
    char* sir = (char*)calloc(256, sizeof(char));

    scanf("%[^\n]s", sir);

    int numarVocale = 0, lungimeSir = strlen(sir);
    for (int i = 0; i < lungimeSir; ++i) {
        if (isVowel(sir[i])) numarVocale++;
    }

    for (int i = 0; i < lungimeSir; ++i) {
        if (isVowel(sir[i])) {
            int pozitie = i;
            pozitie++;
            while (isVowel(sir[pozitie]) && pozitie < lungimeSir) {
               pozitie++;
            }
            sir[i] = sir[pozitie];
            sir[pozitie] = '\0';
       }
   }

   sir = realloc(sir, lungimeSir - numarVocale);

   printf("The string after I deleted the vowels: %s", sir);
}

My thinking was to find a first vowel, then save its position and if next character is also a vowel loop through them until I find a consonant.

Upvotes: 1

Views: 247

Answers (2)

niets
niets

Reputation: 61

sir[pozitie] = '\0'; is what's messing with you.

Try walking through an example on paper.

aabbbceee will find that a is a vowel at the beginning.

while (isVowel(sir[pozitie]) && pozitie < lungimeSir) {
    pozitie++;
}

The above code runs until it finds the first b. sir[i] = sir[pozitie]; replaces your a with b so now you're looking at babbbceee.

sir[pozitie] = '\0'; then replaces the first b with \0. Now you're looking at ba\0bbceee.

You advance to the next vowel, which is the second a. You then look for the next character that fails IsVowel(), which is the \0 you just inserted. At the end of this if-statement, you're now looking at b\0\0bbceee.

At this point you should be able to see the error in your logic. As for what it's outputting, it only shows the first consonant because \0 is the terminating delimiter for C strings. So, printf() only sees b\0 and prints b.

Upvotes: 1

Craig Estey
Craig Estey

Reputation: 33621

There is no need to count the number of vowels beforehand.

Just do a single loop and process one character at a time.

There's no need to use strlen. Just stop the loop if the current character is EOS (e.g. 0).

The important point is to not copy the current character if it is a vowel.

Maintain two index variables: (1) the source/input index (e.g. isrc) and (2) the destination/output index (e.g. idst).

Only advance idst if you're copying a character (i.e. a non-vowel).

A refinement is to not copy the character if idst is isrc. (i.e. you'd just be copying the same character to itself). But, you still have to increment the output index (idst).

And, you have to add a new EOS (string terminator) at the end of the loop.

Here's the refactored code (with some annotations):

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

bool
isVowel(char a)
{
    if (a == 'a' || a == 'e' || a == 'i' || a == 'o' || a == 'u')
        return true;
    return false;
}

void
main(void)
{
// NOTE/BUG: don't cast the result of malloc
#if 0
    char* sir = (char*)calloc(256,sizeof(char));
#else
    char* sir = calloc(256,sizeof(*sir));
#endif

    scanf("%[^\n]s",sir);
    printf("The string before I deleted the vowels: '%s'\n",sir);

    int isrc = 0;
    int idst = 0;

    while (1) {
        // get next char (and advance the source index)
        char chr = sir[isrc++];

        // end of string
        if (chr == 0)
            break;

        // skip any vowel
        if (isVowel(chr))
            continue;

        // copy over char [if different]
        // NOTE: using the "if" is a nicety/speedup
        if (idst != (isrc - 1))
            sir[idst] = chr;

        // advance destination index
        ++idst;
    }

    // add EOS to new [possibly] shorter string
    sir[idst] = 0;

    // trim the output string
    sir = realloc(sir,idst + 1);

    printf("The string after I deleted the vowels: '%s'\n",sir);
}

Upvotes: 1

Related Questions