句子中字符出现的直方图

时间:2013-04-10 02:45:39

标签: c

问题:

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

直方图可以使用任何字符来表示特定字母的单个实例,例如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而不是每个字符的出现次数。

2 个答案:

答案 0 :(得分:1)

这不是一个好的开始:

locate = &array3[i];

您正在检查字母表中的每个i字母(不区分大小写),并从输入字符串中的i位置开始搜索该字母。这是错的。您还应该每次循环重置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;
    }      
}

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

[edit] 我猜不是......

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'] 感兴趣(对于大写和下划线也是如此)。但是如果您的输入表现良好,那么这很好,因为所有其他字符数将保持为零。

答案 1 :(得分:0)

这引起了问题

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

我从0..25开始,即26个字符,但你的数组的尺寸只有25个字符:

char alphabet[25] = {0};

你的循环应该是

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