Thread: From a string, remove all the words with `n` number of vowels

  1. #1
    Registered User
    Join Date
    Apr 2021
    Posts
    2

    Question From a string, remove all the words with `n` number of vowels

    I've been trying to write a program, that will remove all the words, that contain the `n` amout of vowels in them. The text is read from a test.txt file which contains the following:

    astazi nu este maine


    Code:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    
    
    
    
    void count1 (char* str)// count number of vowels for each word
    {
        for (int i = 0;;)
            for (int v = 0, w = i;;)
            {
                int len;
                char c = str[i++];
                switch (c)
                {
                case 'A':
                case 'E':
                case 'I':
                case 'O':
                case 'U':
                case 'a':
                case 'e':
                case 'i':
                case 'o':
                case 'u':
                    v++;
                default:
                    continue;
                case ' ':
                case '\t':
                case '\n':
                case '\0':
                    len = i - 1 - w;
                    printf("'%.*s': %d characters, %d vowels\n", len, str+w, len, v );
                    if (c)
                        break;
                    else
                        return;
                }
                break;
            }
    }
    
    
    void count2 (char* str, int n)// my attempt to use basically the same functions from 
    //above, to verify if v==n -> delete the word
    {
        char line2[128];
        int ls=strlen(str);
        for (int i = 0;;)
            for (int v = 0, w = i;;)
            {
                int len;
                char c = str[i++];
                switch (c)
                {
                case 'A':
                case 'E':
                case 'I':
                case 'O':
                case 'U':
                case 'a':
                case 'e':
                case 'i':
                case 'o':
                case 'u':
                    v++;
                default:
                    continue;
                case ' ':
                case '\t':
                case '\n':
                case '\0':
                    for(int k = 0; str[k] != '\0'; k++)
                    {
                        if (k == 0 || isspace(str[k]))
                        {
                            if(v==n)
                            {
                                strcat(line2, str+1);
                            }
                        }
                    }
                    printf("%s ", line2);
                    if (c)
                        break;
                    else
                        return;
                }
                break;
            }
    }
    
    
    int main()
    {
        FILE *fp;
        char line[128];
        int c=0, count[26]= {0}, x;
        int n;
    
    
        fp = fopen("test.txt", "r");
    
    
        fscanf(fp, "%[^\n]", line);
        fclose(fp);
        printf("%s\n\n", line);
    
    
        while (line[c] != '\0')
        {
            if (line[c] >= 'a' && line[c] <= 'z')
            {
                x = line[c] - 'a';
                count[x]++;
            }
            c++;
        }
    
    
        for (c = 0; c < 26; c++)
        {
            printf("%c occurs %d times.\n", c + 'a', count[c]);
        }
        printf("\n");
        count1(line);
        printf("\nInsert n: ");
        scanf("%d", &n);
        count2(line, n);
    
    
        return 0;
    }

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    38,658
    First off, count1 and count2 are poor names for your functions.

    Points for you to think about.
    As much as you can, write the code in stages and try to write some kind of test for it.
    If your functions are simple enough (they should be broken up if not), you only need one or two test cases for each one to be fairly sure it's working.

    Writing a whole program with no idea if any of it works isn't a good place to be.


    Code:
    #include <stdio.h>
    #include <ctype.h>
    
    int countVowels(const char *s) {
      int result = 0;
      for( int i = 0 ; s[i] != '\0' ; i++ ) {
        switch( toupper(s[i]) ) {
          case 'A':
          case 'E':
          case 'I':
          case 'O':
          case 'U':
            result++;
        }
      }
      return result;
    }
    
    void doTests() {
      char test[] = "hello";
      printf("Count=%d\n", countVowels(test) );
    }
    
    int main ( ) {
      doTests();
      char word[100];
      FILE *fp = fopen("input.txt","r");
      while ( fscanf(fp,"%s",word) == 1 ) {
        if ( countVowels(word) != 3 ) {
          printf("%s ", word);
        }
      }
      fclose(fp);
    }
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    May 2012
    Posts
    502
    Quote Originally Posted by dape View Post
    I've been trying to write a program, that will remove all the words, that contain the `n` amout of vowels in them.
    Start with the function isvowel(char ch) that tells you whether a character is a vowel or not. Then build countvowels(char *str) on top of it.
    That's the logic for you program.
    Now the hard part is breaking up the input into words. Since the input is not English (Spanish?) you might have slightly different rules for what constitutes a "word" in Spanish than in English. But basically a word is a alpha charcter, followed by apostrophes or alpha characters.

    A word can't be more than about 30 characters long, so give it 256 for luck. Be sure to reject input of words greater than 256 characters as an attacker could construct such an input to cause a buffer overrun.

    So the logic is - read a character from the input. If it is non-alpha, put it to the output. Otherwise unget the character (makes it easier) and read the word into a 256 character buffer. If you have more than 255 characters in the word, exit with an error message. Unget the last character, which is non-alpha. Now count the number of vowels in the word. If not n, write the word to ouput. Otherise skip.

    Are you meant to remove spaces to close up the gap or not? The problem doesn't say. If it's a homework exericse, you can provide two options. Then you have a case for an extra mark.
    I'm the author of MiniBasic: How to write a script interpreter and Basic Algorithms
    Visit my website for lots of associated C programming resources.
    https://github.com/MalcolmMcLean


  4. #4
    Registered User
    Join Date
    Apr 2021
    Posts
    2
    Here's what I've came up with:

    Code:
    #include <stdio.h>#include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
    
    
    
    
    void count1 (char* str)// count numbers of vowels for each word
    {
        for (int i = 0;;)
            for (int v = 0, w = i;;)
            {
                int len;
                char c = str[i++];
                switch (c)
                {
                case 'A':
                case 'E':
                case 'I':
                case 'O':
                case 'U':
                case 'a':
                case 'e':
                case 'i':
                case 'o':
                case 'u':
                    v++;
                default:
                    continue;
                case ' ':
                case '\t':
                case '\n':
                case '\0':
                    len = i - 1 - w;
                    printf("'%.*s': %d characters, %d vowels\n", len, str+w, len, v );
                    if (c)
                        break;
                    else
                        return;
                }
                break;
            }
    }
    
    
    void print_x(char* str, int n)
    {
        char* tmp;
        unsigned int cnt = 0, stat = 0;
        const char aeiou[] = "AEIOUaeiou";
        while(*str)
        {
            switch(stat)
            {
            case 0:// the word did not start
                if (!isalpha(*str))
                {
                    putchar(*str);
                    break;
                }
                stat = 1;
                tmp = str;
                cnt = 0;
            case 1:// the word did start
                if (strchr(aeiou, *str))
                {
                    cnt++;
                    break;
                }
                if (! isalpha(*str))
                {
                    if (cnt != n)
                    while(tmp <= str) putchar(*(tmp++));
                    else putchar(*str);
                    stat = 0;
                }
            } // end switch
            ++str;
        }
        if (stat)
        {
            --str;
            if (cnt != n) while(tmp <= str) putchar(*(tmp++));
        }
    }
    
    
    
    
    int main()
    {
        FILE *fp;
        char line[128], line2[128];
        int c=0, count[26]= {0}, x;
        int n,a;
        int i,j;
    
    
        fp = fopen("test.txt", "r");
    
    
        fscanf(fp, "%[^\n]", line);
        fclose(fp);
        printf("%s\n\n", line);
    
    
        while (line[c] != '\0')
        {
            if (line[c] >= 'a' && line[c] <= 'z')
            {
                x = line[c] - 'a';
                count[x]++;
            }
            c++;
        }
    
    
        for (c = 0; c < 26; c++)
        {
            printf("%c occurs %d times.\n", c + 'a', count[c]);
        }
    
    
        for (i = 0; i < 26; ++i)
        {
            for (j = i + 1; j < 26; ++j)
            {
                if (count[i] < count[j])
                {
                    a = count[i];
                    count[i] = count[j];
                    count[j] = a;
                }
            }
        }
        printf("\n\n");
    
    
        for (c = 0; c < 26; c++)
        {
            printf("%c occurs %d times.\n", c + 'a', count[c]);
        }
    
    
        printf("\n");
        count1(line);
        printf("\nInsert n: ");
        scanf("%d", &n);
    
    
        if (!(fp = fopen("./test.txt", "r")))
        {
            printf("unable open file\n");
            return 1;
        }
        while (fgets(line, 128, fp))
            print_x(line, n);
        fclose(fp);
    
    
        return 0;
    }

  5. #5
    Registered User rstanley's Avatar
    Join Date
    Jun 2014
    Location
    New York, NY
    Posts
    810
    Quote Originally Posted by dape View Post
    Here's what I've came up with:
    ...
    Have you studied Salem's solution carefully? If not, please do.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Remove first few words from a string
    By dubya1382 in forum C Programming
    Replies: 4
    Last Post: 11-29-2020, 01:53 AM
  2. using indexof to remove first two words of string
    By jeremy duncan in forum C# Programming
    Replies: 3
    Last Post: 08-05-2017, 04:17 PM
  3. Text processing. Deleting words not starting with vowels
    By Ignas Kalnietis in forum C Programming
    Replies: 1
    Last Post: 10-30-2016, 10:48 AM
  4. Number of words in a string problem
    By MVK059 in forum C Programming
    Replies: 6
    Last Post: 06-11-2014, 06:39 PM
  5. number of words in a string
    By jackhasf in forum C Programming
    Replies: 11
    Last Post: 12-26-2009, 03:37 PM

Tags for this Thread