Parameter as pointer not being correctly incremented

Viewed 40

I have a function which counts the number of vowels and consonants in a string:

void CountVowelsConsonants(char* str, int *vowels, int *consonants){
    size_t size=strlen(str);
    //size-1 because of the '\n' at the end of the string when pressing enter
    for (int i = 0; i < size ; ++i) {
        char c = str[i];
            if(c=='A' || c== 'E' || c=='I' || c== 'O' || c=='U' ||
                    c=='a' || c== 'e' || c=='i' || c== 'o' || c=='u'){
                *vowels++;
            }
        }
    *consonants= size-1 - *vowels;
    }

But when I call this function, like this for example:

int vowels;
int consonants;
CountVowelsConsonants("abc", &vowels, &consonants);

it returns:

Vowels: -858993460
Consonants: 858993463

instead of:

Vowels: 1
Consonants: 2

I would like to know why this is the case.

I have a factorial function which has a similar implementation of the pointer and it works correctly:

void factorial(int n, int*fac){
    *fac=1;
    for (int i = 2; i <=  n; ++i) {
        *fac*=i;
    }
}

Acessing the fact pointer in the factorial function will alter the value correctly. The only difference is that in the CountVowelsConsonants function I'm incrementing by 1 instead of multiplying.

However, if I access the vowels pointer in the CountVowelsConsonants function to increment it will produce errors in the counting.

My IDE (CLion) will grey out the * in *vowels, indicating that the pointer operator in *vowels++; is useless.

Any ideas as to why this is the case?

2 Answers

Instead of:

*vowels++;

which is equivalent to this:

*vowels;            // this does nothing, that's what your IDE was telling you
vowel = vowels + 1; // this increments the vowels pointer,
                    // which is also pretty useless here

you need to write this:

(*vowels)++;

which is equivalent to this and which is what you actually want:

*vowels = *vowels + 1;

The precedence of the ++ operator is 1, whereas the precedence of the * (dereference) operator is 2.

For starters if the variables vowels and consonants are declared in main (or other function) then they are not initialized and has indeterminate values. You need to write

int vowels = 0;
int consonants = 0;
CountVowelsConsonants("abc", &vowels, &consonants);

The first function parameter should be declared with the qualifier const because the passed string is not changed in the function.

void CountVowelsConsonants( const char* str, int *vowels, int *consonants);

By the way the second and third parameters shall have the type size_t.

void CountVowelsConsonants( const char* str, size_t *vowels, size_t *consonants);

Within the function the call of strlen for the passed string is inefficient.

size_t size=strlen(str);

The variable i within the loop shall be declared with the type size_t.

for ( size_t i = 0; i < size ; ++i) {

But without calling the function strlen the loop could look simpler

for ( ; *str != '\0'; ++str ) {
    char c = *str;
    if(c=='A' || c== 'E' || c=='I' || c== 'O' || c=='U' ||
            c=='a' || c== 'e' || c=='i' || c== 'o' || c=='u'){
        ++*vowels;
    }
    else {
       ++*consonants;
    }
 }

This expression

*vowels++;

is incorrect. It is equivalent to the expression

*( vowels++ );

that is the pointer itself is incremented.

You should write

++*vowels;

This expression

*consonants= size-1 - *vowels;

is also incorrect.

If you are using the variable size obtained by a call of strlen then you have to write

*consonants= size -*vowels;

Pay attention to that the function will work incorrectly if the passed string contains spaces or a punctuation symbol.

So it would be more correct to declare the loop within the function at least the following way

#include <ctype.h>

//...

for ( ; *str != '\0'; ++str ) {
    char c = *str;

    if ( isalpha( ( unsigned char )c ) ) {
        if(c=='A' || c== 'E' || c=='I' || c== 'O' || c=='U' ||
                c=='a' || c== 'e' || c=='i' || c== 'o' || c=='u'){
            ++*vowels;
        }
        else {
           ++*consonants;
        }
    }
 }
Related