C lang compare a 2d array of strings, based on the number of consonants in each string

Viewed 192

So I have this program, I have to compare the rows based on the number of consonants,i made an array char voc[12] where I've put all the vocals, then I tried to make a function that calculates the total number of vocals and consonants, but it as well doesn't work.

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
    
int main()
{
    srand(time(NULL));
    char rand_string[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    char voc[12] = {'a','e','i','o','u','A','E','I','O','U','Y','y','\0'};
    int m,n,i,j,elem=0,vocale=0;
    printf("Introduceti numarul de linii si coloane:");
    scanf("%d %d", &m, &n);
    char a[m][n];
    for (i=0; i<m; i++)
    {
        for(j=0; j<n; j++)
        {
            a[i][j]=rand_string[rand() % (sizeof(rand_string) - 1)];
        }
    }
    printf("Matrita e:\n");
    for (i=0; i<m; i++)
    {
        printf(" \n ");
        for(j=0; j<n; j++)
        {
            printf(" %c\t ", a[i][j]);
        }
    }

    for ( i = 0; a[i][j] != '\0'; i++)
    {
        for (j = 0; a[i][j] != '\0'; j++)
        {
            if(a[i][j] == voc[i])
            {
                vocale++;
            }
            else
            {
                elem++;
            }
        }
        printf("\n %d ", vocale);
        printf("\n %d ", elem);
    }
    return 0;
}
4 Answers

First instead of

char voc[12] = {'a','e','i','o','u','A','E','I','O','U','Y','y','\0'};

declared it like you did for

char rand_string[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

namely:

char voc[] = {"aeiouAEIOU"};

it is less error-prone, you do neither have to enter '\0' nor the size of the array.

The main problems with your code are, during the filling up of the matrix with the random values, you should to add ''\0' to the end of each row:

for (int i=0; i<m; i++)
{
    for(int j=0; j<n; j++)
    {
        a[i][j]=rand_string[rand() % (sizeof(rand_string) - 1)];
    }
    a[i][n] = '\0'; // <--- this
}

A second problem is your double loop to search the vocals

 for ( i = 0; a[i][j] != '\0'; i++)
        for (j=0; a[i][j]!='\0'; j++)
        

you are using j with a value from the previous computations, since you already have the matrix dimensions stored on the local variables m and n just use them:

  for (int i = 0; i < m; i++)
            for (int j=0; j < m; j++)

The other problem with your code is this part:

if(a[i][j]==voc[i])
{
     vocale++;
}
else
{ 
     elem++;
}

you are just comparing the matrix against one vocal at the position i (i.e., voc[i]). What you need to do instead is to compare this a[i][j] against all the positions of the array voc. You can extract that logic into a separate method:

int is_vocal(char c){
    char voc[] = {"aeiouAEIOU"};
    for(int i = 0; voc[i] != '\0'; i++)
       if(c == voc[i])
          return 1;
    return 0;
}

and then:

int elem=0,vocale=0;
for (int i = 0; i < m; i++)
    for(int j=0; j < n; j++){
        if(is_vocal(a[i][j])){
            vocale++;
        }
        else {
            elem++;
        }
    }
}

Other tips are to declare your variables close to the code that they will be used, and you should extract more methods to increase code readability.

IMO, unless you are not allowed to do it, it is better to do for (int i=0; i<m; i++) instead of for (i=0; i<m; i++) with int i declared somewhere else.

If you would have extracted the methods for the filling up of the matrix with random numbers, the printing of the matrix, and the finding of the number of vocals, it would be much easier to read your code. For example:

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


int main()
{
    srand(time(NULL));
    char rand_string[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    ...
    fill_up_matrix_with_random_values(m, n, a);
    print_matrix(m, n, a)
    vocals = find_number_of_vocals(m, n, a);
    printf("\n Total of vocals {%d} ", vocals);
    printf("\n Total of Consonantsd ", (m * n) - vocals);

    return 0;
}

Well, I've done it. Firstly I wrote a bool function, that determines if a character is a vowel, and if it's not, it counts as a consonant, then I create a random matrix made of random characters, after that, the program calculates the number of consonants for each row then it compares them and it's typing, which row has the most amount of consonants.

Thanks everybody for your help.

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

bool is_vowel(char c)
{
    char voc[13] = {'a','e','i','o','u','A','E','I','O','U','Y','y','\0'};
    for (int i=0; i<13; i++)
    {
        if(voc[i]==c)
        {
            return true;
        }
    }
    return false;
}


int main()
{
    srand(time(NULL));
    char rand_string[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
    int m,n,i,j,elem=0,cons[10],vocale=0;
    printf("Rows and columns:");
    scanf("%d %d", &m, &n);
    char a[m][n];
    for (i=0; i<m; i++)
    {
        for(j=0; j<n; j++)
        {
            a[i][j]=rand_string[rand() % (sizeof(rand_string) - 1)];
        }
    }
    printf("The matrix is:\n");
    for (i=0; i<m; i++)
    {
        printf(" \n ");
        for(j=0; j<n; j++)
        {
            printf(" %c\t ", a[i][j]);
        }
    }
    for (i = 0; i<m; i++)
    {
        for(j=0; j<n; j++)
        {
            if(is_vowel(a[i][j]))
            {
                vocale++;
            }
            else
            {
                elem++;
            }
        }
    }
    printf("\nSum of consonants:%d", elem);
    for (i = 0; i<m; i++)
    {
       cons[i]=0;
       for(j=0;j<n;j++)
       {
           if(!(is_vowel(a[i][j])))
           {
               cons[i]++;
           }
       }
       printf("\n Row %d has %d consonants", i, cons[i]);
                      if(cons[i]>cons[i-1] && cons[i]!=0)
               {
                   printf("\nThe row with the biggest num of consonants:%d", i);
               }
    }


    return 0;
}

You need to see the diffrence beetwen those two initialization:

char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
char vowels[12] = {'a','e','i','o','u','A','E','I','O','U','Y','y'};

The first one creates an array of given chars and null terminate it. The second one is a regular array and it is not null-terminated by default.

With the difference above in mind, you generate a 2-dim array of chars. It's not a null-terminated string so you shouldn't iterate until a char != '\0'.

To check whether a char is a vowel or not it's best to create a function that will do that check and return a pseudo-boolean result. Then use it while you iterate through the array.

    int isVowel(char letter)
    {
        char vowels[12] = {'a','e','i','o','u','A','E','I','O','U','Y','y'};
        for (int i = 0 ; i < 12 ; i++) 
        {
            if (letter == vowels[i]) 
            {
                return 1;
            }
        }
        return 0;
    }

You have several problems. Mostly, you don't have any null terminators on any of your strings, yet you are checking for null terminators.

At you start checking using a variable that is not really initialized.

You have a 2D array of characters, not strings, and you set every one of them to a non-null character.

If you change the initialization to properly null terminate, still consider your outer loop:

for ( i = 0; a[i][j] != '\0'; i++)

This sets i=0 but j is left at whatever value it had before (in this case, n), so it is testing a[0][n] which is not a valid index because n is out of range. You also are not checking range on i or j in these loops.

Related