Как добавить символы в массив строк в C - PullRequest
0 голосов
/ 08 января 2020

Я очень плохо знаком с C, и я пытаюсь написать программу, которая проверяет, содержит ли строка какие-либо заглавные буквы, и, если это так, печатает их. Я использую https://www.onlinegdb.com/online_c_compiler# в качестве компилятора (потому что у меня нет доступа к моему персональному компьютеру прямо сейчас), и после пробного запуска получаются следующие результаты (ps, я знаю, что это небезопасно) :

main.c:16:5: warning: ‘gets’ is deprecated [-Wdeprecated-declarations]
/usr/include/stdio.h:638:14: note: declared here
main.c:(.text+0x26): warning: the `gets' function is dangerous and should not be used.
sTrInG
Contains Uppercase!
Uppercase Letters:0

...Program finished with exit code 0
Press ENTER to exit console.

В этом случае я ожидаю вывод что-то вроде этого:

Contains Uppercase!
Uppercase Letters: TIG

Мой сценарий:

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

int main()
{
    char str[100];
    gets(str);
    int containsUpper = 0;
    char upperLetters[100] = {0};
    for (int i=0; i < strlen(str); i++) {
        if (islower(str[i])) {
            continue;
        } else {
            containsUpper = 1;
            upperLetters[i] = str[i]; // is this the bad line?
        }
    }
    if (containsUpper) {
        printf("Contains Uppercase!\n");
        printf("Uppercase Letters:");
        printf("%zu\n", strlen(upperLetters)); // prints 0 so upperLetters is empty..?
        for (int i=0; i < strlen(upperLetters); i++) {
            printf("%c", upperLetters[i]);
        }
    } else {
        printf("Does not contain Uppercase!");
    }
    return 0;
}

Ответы [ 3 ]

1 голос
/ 08 января 2020

Это l oop

for (int i=0; i < strlen(str); i++) {
    if (islower(str[i])) {
        continue;
    } else {
        containsUpper = 1;
        upperLetters[i] = str[i]; // is this the bad line?
    }
}

1) неверно и 2) страдает от плохого стиля программирования.

Вы должны добавлять буквы верхнего регистра к массиву символов upperLetters
последовательно, что вы не делаете. Также, если символ не является символом нижнего регистра, это не означает, что символ является символом верхнего регистра. Например, в общем случае это может быть ди git или пунктуация.

Также нет необходимости вызывать функцию strlen. Аргумент вызова функции должен быть приведен к unsigned char. В противном случае может случиться так, что вызов функции вызовет неопределенное поведение.

Часть l oop с оператором continue избыточна.

l oop может искать Например, следующий способ

for ( size_t i = 0, j = 0; str[i] != '\0'; i++ ) 
{
    if ( isupper( ( unsigned char )str[i] ) )
    {
        upperLetters[j++] = str[i];
    }
}

containsUpper = upperLetters[0] != '\0';

Если вам нужно количество заглавных букв в другой части программы, то l oop может выглядеть как

size_t n = 0;
for ( size_t i = 0; str[i] != '\0'; i++ ) 
{
    if ( isupper( ( unsigned char )str[i] ) )
    {
        upperLetters[n++] = str[i];
    }
}

if ( n ) 
{
    printf( "Contains Uppercase!\n" );
    printf( "Uppercase Letters: " );
    printf("%zu\n", n );
    for ( size_t i = 0; i < n; i++ ) 
    {
        printf( "%c", upperLetters[i] );
    }
    //…

или вместо l oop

    for ( size_t i = 0; i < n; i++ ) 
    {
        printf( "%c", upperLetters[i] );
    }

вы могли бы просто написать

printf( "%s\n", upperLetters );

, потому что массив был инициализирован нулем и поэтому содержит строку.

Как сообщил компилятор функция get небезопасна и не поддерживается стандартом C. Вместо этого используйте функцию fgets.

Например

fgets( str, sizeof( str ), stdin );
0 голосов
/ 08 января 2020

Я бы не стал считать цифры или символы типа !?#%& заглавными буквами, но ваша программа считает их таковыми. Вы абсолютно не должны использовать gets, но в этом случае нет никаких оснований заменять его на fgets, поскольку ваша программа не ориентирована на строки. Вы просто не заботитесь о линиях. Просто сделайте:

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

int
main(void)
{
        int c;
        char upperLetters[100] = {0};
        unsigned k = 0;

        while( ( c = getchar()) != EOF && k < sizeof upperLetters ) {
                if( isupper(c)) {
                        upperLetters[k++] = c;
                }
        }
        if (k) {
                puts("Contains Uppercase!");
                printf("Uppercase Letters: %u\n%s\n", k, upperLetters);
        } else {
                fprintf(stderr, "Does not contain Uppercase!");
        }
        return k != 0;
}

(Обратите внимание, что исходная программа просматривает только первую строку ввода. Не ясно, является ли это ошибкой или преднамеренной. Если это преднамеренно, добавьте проверку и выйдите из l oop при чтении первого символа новой строки.)

0 голосов
/ 08 января 2020

Вы хотите, чтобы l oop было:

int i, j=0;
for (i=0; i < strlen(str); i++) {
    if (isupper((unsigned char)str[i])) {
        upperLetters[j++] = str[i];
    }
}
upperLetters[j]= '\0';
containsUpper = (j>0);

То есть, ведите отдельный индекс массива верхних букв. И не забудьте прекратить его.

Лучший способ для l oop:

int i, j, k;
for (i=0, j=0, k=strlen(str); i < k; i++) {

, так как strlen это вызывает только один раз.

РЕДАКТИРОВАТЬ: Как указал пользователь LxerLx, символ, который не является строчной буквой, не обязательно должен быть заглавной буквой. Я обновил l oop для этого.

...