Why is my program counting letters and digits not running?

Viewed 47

I wrote this function tat checks for upper, lower and digits in a string but when I'm trying to run the code this pops up and cant seem to understand the problem.

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

#define size 50

void statistics(char str[], int *lower, int *upper, int *digits) {
    for (int i = 0; i < size; i++) {
        if (islower(str[i]) != 0) {
            *lower = *lower + 1;
        } else
        if (isupper(str[i]) != 0) {
            *upper = *upper + 1;
        } else
        if (isalpha(str[i])) {
            *digits = *digits + 1;
        }
    }
}

int main() {
    char str[size] = { " " };
    int upper = 0, lower = 0, digits = 0;

    printf("Enter a string:\n");
    gets_s(str);

    statistics(&str[size], &lower, &upper, &digits);
    printf("Lower: %d\nUpper: %d\nDigits %d", lower, upper, digits);

    return 0;
}

enter image description here

1 Answers

There are multiple problems in your code:

  • the gets_s() function is not portable: it is optional and not supported on many systems. You forget to pass the array size, hence causing undefined behavior. The compiler should output a diagnostic that you should not ignore. You should use fgets() instead.

  • you should not pass char values to the isupper() and similar functions because they are only defined for values of the type unsigned char and the special negative value EOF. Use an unsigned char variable or cast the str[i] argument as (unsigned char)str[i].

  • you pass the address of the end of the char array instead of the beginning. Just pass str as the argument to statistics. The statistics function reads characters beyond the end of the array, invoking undefined behavior, and one of these bytes happens to be a negative char value less than -1 triggering the diagnostic in your Visual C++ compiler runtime. The error message is difficult to interpret, the IDE should point you to the calling code.

  • you iterate on the whole array, beyond the null terminator. The contents of the array is undefined beyond the null terminator set by gets_s() or fgets(). Just stop at the null terminator.

  • you test if (isalpha(ch)) where you probably mean to use if (isdigit(ch))

  • the isxxx functions return a non zero value for true and zero for false. It is idiomatic in C to just write if (isdigit(c)) instead of if (isdigit(c) != 0) which seems redundant.

  • defining size as a macro is error prone. Use upper case and a more explicit name.

Here is a modified version:

#include <ctype.h>
#include <stdio.h>

#define LINE_SIZE 50

void statistics(const char *str, int *lower, int *upper, int *digits) {
    while (*str != '\0') {
        unsigned char ch = *str++;
        if (islower(ch)) {
            *lower += 1;
        } else
        if (isupper(ch)) {
            *upper += 1;
        } else
        if (isdigit(ch) {
            *digits += 1;
        }
    }
}

int main() {
    char str[LINE_SIZE];
    int upper = 0, lower = 0, digits = 0;

    printf("Enter a string:\n");
    if (fgets(str, sizeof str, stdin)) {
        statistics(str, &lower, &upper, &digits);
        printf("Lower: %d\nUpper: %d\nDigits %d", lower, upper, digits);
    }
    return 0;
}
Related