-2

问题:

设计一个单词和字符计数器并显示特定字符​​的直方图。

直方图可以使用任何字符来表示特定字母的单个实例,例如X,并且应该在行尾打印该字母的实例数。仅打印在输入的句子中出现一次或多次的字符的结果。您的程序必须将相同字母的小写和大写视为单独的字符。

下面是一个直方图可能看起来像句子的例子:i_Looooove__eps_II

Word total: 4
Character total: 18
Character total omitting underscore: 14

e: XX (2)
i: X (1)
o: XXXXX (5)
p: X (1)
s: X (1)
v: X (1)
I: XX (2)
L: X (1)
_: XXXX (4)

这是我到目前为止所拥有的:

void histogram(char array3[]){
    char alphabet[25] = {0};
    int count;
    char *locate;
    int i;
    int j;

    for(i=0; array3[i] != '\0'; i++){
        array3[i] = tolower(array3[i]);
    }
    count = 0;
    for(i = 0; i <= 25; i++){
        locate = &array3[i];
        while(locate = strchr(locate, 'a' + i)){
            ++count;
            locate++;
        }
        alphabet[i] = count;
    }
    printf("\nThe number of occurrences of each letter is: \n");

    for(i = 0; i <= 25;i++){
        printf("%c:%3d\n", 'a' + i, alphabet[i]);
    }
    return;
}

有些东西没有按我的预期工作:

直方图的输出是全1,而不是每个字符的出现次数。

4

2 回答 2

1

这不是一个好的开始:

locate = &array3[i];

您正在检查i字母表中的每个字母(不区分大小写),并从i输入字符串的第 th 位置开始搜索该字母。这是错误的。count您还应该在每次循环中重置。

与传统方式相比,您的方法有点倒退。您应该简单地计算遇到的那些字符,而不是在整个字符串中搜索每个可能的字符。这应该大致是您想要的:

int counts[256] = {0};

int num_words = 0;         // Total number of words
int num_chars = 0;         // Total number of characters (including underscores)
int num_underscores = 0;   // Total number of underscores
int in_word = 0;           // Are we currently inside a word?

for( int i = 0; str[i] != 0; i++ )
{
    if( isalpha(str[i]) )
    {
        counts[str[i]]++;
        num_chars++;

        if( !in_word ) {
            in_word = 1;
            num_words++;
        }
    }
    else if( str[i] == '_' )
    {
        counts[str[i]]++;
        num_underscores++;
        in_word = 0;
    }
    else {
        // Unhandled character.  Treat as word-break?
        in_word = 0;
    }      
}

你可以从这里解决剩下的问题。

[编辑]我猜不是...

printf( "Word total: %d\n", num_words );
printf( "Character total: %d\n", num_chars );
printf( "Character total omitting underscore: %d\n", num_chars - num_underscores );

for( int i = 0; i < 256; i++ )  // Yes, this loop range is excessive...
{
    if( counts[i] == 0 ) continue;
    printf( "%c: ", (char)i );
    for( int x = 0; x < counts[i]; x++ ) fputc('X', stdout);
    printf( " (%d)\n", counts[i] );
}

如果您仍然对此感到困惑,这里是提炼出纯字符频率计数的代码:

int counts[256] = {0};

for( int i = 0; str[i] != 0; i++ )
{
    counts[str[i]]++;
}

请注意,每个可能的字符值都有一个数组位置。对于字符串中的每个字符,您只需增加其计数。您只对counts['a'],counts['b'] (大写和下划线类似)真正感兴趣。但是,如果您的输入表现良好,那么这很好,因为所有其他字符数都将保持为零。

于 2013-04-10T03:06:17.113 回答
0

这会导致问题

for(i = 0; i <= 25; i++)

i 从 0..25 即 26 个字符开始,但您的数组的尺寸仅为 25 个字符:

char alphabet[25] = {0};

你的循环应该是

for(i = 0; i < 25; i++)
于 2013-04-10T05:11:45.933 回答