How to check if one or more string has uppercase/lowercase initial character (C Language)

Asked

Viewed 1,247 times

0

#include <stdio.h>

char leitura(const char *str){
    int i, resultado;

    for(i = 0; str[i] != '\0'; i++){
        if(str[0] >= 'A' && str[0] <= 'Z' && str[' ' + 1] >= 'A' && str[' ' + 1] <= 'Z'){
            resultado = 1;
        }else{
            resultado = 0;
        }
    }
    printf("O resultado eh: %d", resultado);
    return resultado;
}

int main(){
    char str[30];

    fgets(str, 30, stdin);
    leitura(str);

    return 0;
}
  • Is that syntax right? str[' ' + 1]. For the compiler it’s all right, but it doesn’t make sense to me: '' equals 32 + 1 equals 33 (see an ASCII table). If your str has 30 characters you have already exceeded its capacity. Also why put in a loop if the content of your if is constant for every value of i.

2 answers

1

For starters, str[' ' + 1] doesn’t make sense. It doesn’t do what you expect (probably you thought it would be a position after space, or something?) - actually, char and int are sort of "interchangeable" in C (char, despite the name, is a numerical type). In this case, the character ' ' is the blank, whose code in ascii table is 32, so you’re actually trying to access position 33 of str:

// imprimir como char
printf("%c\n", ' ' + 1); // !
// imprimir como inteiro
printf("%d\n", ' ' + 1); // 33

And how str was declared with 30 positions, trying to access a position beyond this limit generates a undefined behavior (read more about here, here and here).

Another detail is that in loop you are always checking str[0] (the first position of str) but actually you should use the i, because that’s what it’s for: to iterate through the characters of str.


Also, the title is confused. If you want to check the string "uppercase/lowercase initial character", wouldn’t it be enough to check the first character? Then you wouldn’t even need a loop:

char str[30];
fgets(str, 30, stdin);

if ('A' <= str[0] && str[0] <= 'Z') {
    // primeiro caractere é letra maiúscula
} else if ('a' <= str[0] && str[0] <= 'z') {
    // primeiro caractere é letra minúscula
} else {
    // primeiro caractere não é letra maiúscula nem minúscula
}

Or - based on first version of the title - you want to see if there’s any word that starts with uppercase?

In this case, a simple way is to check, for each character, if in addition to being a capital letter, the previous character is not a letter. Something like this:

int maiuscula(char c) {
    return 'A' <= c && c <= 'Z';
}

int letra(char c) {
    return ('a' <= c && c <= 'z') || maiuscula(c);
}

int main() {
    char str[30];
    fgets(str, 30, stdin);
    int encontrou = 0;
    for (int i = 0; str[i] != '\0'; i++) {
        if (maiuscula(str[i]) && (i == 0 || !letra(str[i - 1]))) {
            encontrou = 1;
            break; // se já encontrei, nem precisa continuar procurando
        }
    }
    if (encontrou) {
        printf("Encontrei\n");
    } else{
        printf("Não encontrei\n");
    }

    return 1;
}

If I find a word that starts with uppercase, I interrupt the loop, because I understood that finding one is enough and you don’t have to keep looking for others.

I created functions to check if a char is a capital letter, or any letter. In for, the verification is done in the if, which verifies two conditions:

  • maiuscula(str[i]): checks if the current letter is uppercase
  • i == 0 || !letra(str[i - 1]): checks if it is the first character of the string (i == 0), or if the previous one is not letter (the operator || is the "or", and the operator ! is the negation, then !letra(str[i - 1]) checks if the character in the position i - 1 is not a letter)

Both of the above conditions must occur to enter the if, because I used the operator && ("and"). That is, if it is not a capital letter, or if it is, but it is not the first or the previous one is a letter, it does not enter the if.

Thus the code becomes more generic than if we consider only spaces to separate words (the string can be something like "-blablabla,Etc" for example - as no detail has been specified in this regard, it is better to assume that the user can type "anything").


In another answer (currently deleted) it was suggested that instead of the for, using pointer arithmetic. That is, something like this:

int maiuscula(char c) {
    return 'A' <= c && c <= 'Z';
}

int letra(char c) {
    return ('a' <= c && c <= 'z') || maiuscula(c);
}

int temInicialMaiuscula(char *str) {
    int i = 0;
    while (*str) {
        if ((i++ == 0 || !letra(*(str - 1))) && maiuscula(*str)) {
            return 1; // se já encontrei, nem precisa continuar procurando
        }
        str++;
    }
    return 0;
}

int main() {
    char str[30];
    fgets(str, 30, stdin);
    if (temInicialMaiuscula(str)) {
        printf("Encontrei\n");
    } else{
        printf("Não encontrei\n");
    }

    return 1;
}

Which basically does the same thing as the previous version (the main logic is the same). The difference is that instead of making a for by the indices of the string, we used pointer arithmetic to make each iteration str point to the next character. To better understand, I suggest reading here.


Another option is to reverse the logic: first I see if the current character is not letter, and if not, I see if the next one is uppercase:

int temInicialMaiuscula(char *str) {
    while (1) {
        if (! letra(*str)) { // se caractere atual não é letra, verifica o próximo
            str++;
            if (! *str) // chegou no final da string
                return 0;
            if (maiuscula(*str))
                return 1; // encontrei palavra que começa com maiúscula, retorna
        } else str++;
    }
    return 0;
}

0

Your show is really complicated, and I really don’t get it. You can use something simple like

int inicial_minuscula(const char* str)
{
   return (((*str) >= 'a') && ((*str) <= 'z'));
};

And

int inicial_maiuscula(const char* str)
{
    return (((*str) >= 'A') && ((*str) <= 'Z'));
};

Only

Browser other questions tagged

You are not signed in. Login or sign up in order to post.