如何在C中将字符附加到字符串数组

How to append characters to a string array in C

我是 C 的新手,我正在尝试编写一个程序来检查字符串是否包含任何大写字母,如果包含,则打印出来。我正在使用 https://www.onlinegdb.com/online_c_compiler# 作为我的编译器(因为我现在无法访问我的个人计算机)并且在测试 运行 之后,结果是(p.s。我知道得到不安全):

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;
}

您希望循环为:

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

即单独保留一个大写字母数组的索引。并且不要忘记终止它。

更好的循环方式是:

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

因为这只调用 strlen 一次。

编辑:正如用户 LxerLx 所指出的,不是小写字母的字符不一定是大写字母。我为此更新了循环。

这个循环

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
一直认为你没有做。此外,如果字符不是小写字符,则并不意味着该字符是大写字符。例如一般情况下可以是数字或标点符号。

也不需要调用函数strlen。函数调用的参数应转换为 unsigned char。否则可能会发生函数调用将调用未定义的行为。

带有 continue 语句的循环部分是多余的。

循环可以通过以下方式查找示例

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

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

如果程序的其他部分需要大写字母的数量,那么循环可以像这样

size_t n = 0;
for ( size_t i = 0; str[i] != '[=12=]'; 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] );
    }
    //…

或者代替循环

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

你可以写

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

因为数组是零初始化的,因此它包含一个字符串。

正如编译器所报告的那样,函数 gets 是不安全的,并且不受 C 标准支持。而是使用函数 fgets.

例如

fgets( str, sizeof( str ), stdin );

我不会将 !?#%& 之类的数字或字符视为大写字母,但您的程序将它们视为大写字母。您绝对不能使用 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;
}

(注意原程序只看输入的第一行,不知道是bug还是故意的,如果是故意的,在第一个换行后加一个check跳出循环字符被读取。)